{"openapi":"3.0.3","info":{"title":"SendSMS","version":"1.20.3","description":"Company-scoped SMS API. Create a token under Users. Send it as Authorization: Bearer, or as the X-Api-Token header."},"servers":[{"url":"https://sendsms.top"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API token starting with sms_"}}},"security":[{"bearerAuth":[]}],"paths":{"/api/v1/me":{"get":{"operationId":"me","summary":"Who this token is","description":"Returns the token name, role, company, and which actions that role is allowed to call. Access: Any token.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Who this token is","content":{"application/json":{"example":{"ok":true,"name":"Billing","role":"normal","roleLabel":"Normal","companyId":"00000000-0000-0000-0000-000000000000","companyName":"Acme","permissions":{"sendSms":true,"manageUsers":false,"viewWallet":true,"allocateWallet":false,"settings":false}}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}}}},"/api/v1/wallet":{"get":{"operationId":"wallet","summary":"Wallet balance","description":"Integer credit balance for the token's company. One accepted outbound SMS costs one credit. Access: Any token.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Wallet balance","content":{"application/json":{"example":{"ok":true,"companyId":"00000000-0000-0000-0000-000000000000","balance":120}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}}}},"/api/v1/wallet/allocate":{"post":{"operationId":"allocate","summary":"Allocate credits","description":"Adds a positive integer number of credits to a company wallet. amount must be a positive integer. Access: Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Allocate credits","content":{"application/json":{"example":{"ok":true,"balance":220,"ledgerId":"00000000-0000-0000-0000-000000000001"}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"requestBody":{"required":true,"content":{"application/json":{"example":{"companyId":"00000000-0000-0000-0000-000000000000","amount":100,"reason":"October top-up"}}}}}},"/api/v1/customers":{"get":{"operationId":"customers","summary":"Customers","description":"Up to 100 customers per page for the token's company, ordered by name. Use page and pageSize. pageSize max is 100. Access: Any token.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customers","content":{"application/json":{"example":{"ok":true,"page":1,"pageSize":50,"total":1,"customers":[{"id":"00000000-0000-0000-0000-000000000002","name":"Ada","phone_e164":"+27821234567","email":"ada@example.com"}]}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"parameters":[{"name":"page","in":"query","required":false,"description":"Page number, starting at 1.","schema":{"type":"string","example":"1"}},{"name":"pageSize","in":"query","required":false,"description":"Rows per page, 1–100. Default 50.","schema":{"type":"string","example":"50"}}]}},"/api/v1/sms/sent":{"get":{"operationId":"sent","summary":"Sent SMS","description":"Outbound messages for the token's company, 50 per page by default (max 100). status is our word, such as delivered. dlrStatus is the raw carrier code, such as DELIVRD. senderName is the API token when a token sent the message. createdByName is the person who created that token. Access: Any token.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Sent SMS","content":{"application/json":{"example":{"ok":true,"messages":[{"id":"00000000-0000-0000-0000-000000000003","to":"+27821234567","body":"Hello","status":"delivered","statusLabel":"Delivered","dlrStatus":"DELIVRD","dlrLabel":"Delivered","createdAt":"2026-10-09T12:00:00.000Z","threadId":"00000000-0000-0000-0000-000000000003","senderName":"Billing","createdByName":"Ada"}]}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"parameters":[{"name":"page","in":"query","required":false,"description":"Page number, starting at 1.","schema":{"type":"string","example":"1"}},{"name":"pageSize","in":"query","required":false,"description":"Rows per page, 1–100. Default 50.","schema":{"type":"string","example":"50"}}]}},"/api/v1/sms/inbox":{"get":{"operationId":"inbox","summary":"Inbox","description":"Inbound messages for the token's company, 50 per page by default (max 100). Replies are not billed. unread=1 keeps messages that have not been opened. optOut=1 keeps opt-out replies. Access: Any token.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Inbox","content":{"application/json":{"example":{"ok":true,"messages":[{"id":"00000000-0000-0000-0000-000000000004","from":"+27821234567","body":"Thanks","status":"received","createdAt":"2026-10-09T12:05:00.000Z","threadId":"00000000-0000-0000-0000-000000000003","optOut":false,"unread":true}]}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"parameters":[{"name":"page","in":"query","required":false,"description":"Page number, starting at 1.","schema":{"type":"string","example":"1"}},{"name":"pageSize","in":"query","required":false,"description":"Rows per page, 1–100. Default 50.","schema":{"type":"string","example":"50"}},{"name":"unread","in":"query","required":false,"description":"1 to only include unread replies.","schema":{"type":"string","example":"1"}},{"name":"optOut","in":"query","required":false,"description":"1 to only include opt-out replies.","schema":{"type":"string","example":"1"}}]}},"/api/v1/sms":{"post":{"operationId":"send","summary":"Send one SMS","description":"Sends one message to one number. to is E.164 (+2782…) or a South African local number (082…). Optional senderId uses a registered SMSPortal sender; omit it for the account default. The response uses senderId and leaves from empty rather than naming the upstream provider. Optional clientReference is your own id, stored on the message and returned as clientReference. Optional sendAt is an ISO time, at least 15 seconds ahead and at most 30 days, to send later. The credit is taken when the message is actually sent, still one credit per message rather than per segment. Send Idempotency-Key to make a retry return the first result instead of sending twice. A View Only token receives 403. An empty wallet receives 402 and the provider is not called. An opted-out number receives 409 opted_out. GSM-7 is 160 characters (153 if concatenated). Unicode, including emoji, is UCS-2: 70 characters (67 if concatenated). Maximum 10 segments. Access: Normal, Admin, or Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Send one SMS","content":{"application/json":{"example":{"ok":true,"id":"00000000-0000-0000-0000-000000000005","to":"+27821234567","status":"sent","statusLabel":"Sent to the network","dlrStatus":null,"dlrLabel":null,"encoding":"GSM-7","segments":1,"credits":1,"clientReference":"order-19","senderId":"ACME","walletBalance":119}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"requestBody":{"required":true,"content":{"application/json":{"example":{"to":"+27821234567","body":"Hello from SendSMS","senderId":"ACME","clientReference":"order-19"}}}}}},"/api/v1/sms/{id}":{"get":{"operationId":"sms-get","summary":"One message","description":"Fetch one message in this company by id, including status, the raw carrier code, and your clientReference. 404 if it is not in the token's company. Access: Any token.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"One message","content":{"application/json":{"example":{"ok":true,"message":{"id":"00000000-0000-0000-0000-000000000005","status":"delivered","statusLabel":"Delivered","dlrStatus":"DELIVRD","dlrLabel":"Delivered","clientReference":"order-19","senderId":"ACME","senderName":"Billing","createdByName":"Ada","from":null}}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}}}},"/api/v1/sms/bulk":{"post":{"operationId":"bulk","summary":"Send the same SMS to several numbers","description":"Same body to 1–100 numbers. One credit per accepted number, taken when that number is sent. Opted-out numbers are skipped. Optional sendAt schedules every number in the batch. Access: Normal, Admin, or Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Send the same SMS to several numbers","content":{"application/json":{"example":{"ok":true,"sent":2,"encoding":"GSM-7","segments":1,"creditsEach":1,"results":[]}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"requestBody":{"required":true,"content":{"application/json":{"example":{"to":["+27821234567","+27827654321"],"body":"Hello from SendSMS","clientReference":"batch-1"}}}}}},"/api/v1/callback":{"get":{"operationId":"callback-get","summary":"Read the delivery callback","description":"The https URL that receives delivery reports and inbound replies for this company. The secret is not returned. Access: Normal, Admin, or Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Read the delivery callback","content":{"application/json":{"example":{"ok":true,"configured":true,"url":"https://hooks.example.com/sms"}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}}},"put":{"operationId":"callback-put","summary":"Set the delivery callback","description":"Save an https URL and a secret of 16–128 characters. SendSMS POSTs { event, message } when a delivery report or inbound reply arrives. event is delivery or inbound. message is the same camelCase object as GET /api/v1/sms/{id}. Header X-SendSMS-Signature is sha256= plus the HMAC-SHA256 of the raw body using the secret. Private and loopback addresses are rejected. A failed callback does not change the message. Access: Normal, Admin, or Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Set the delivery callback","content":{"application/json":{"example":{"ok":true,"configured":true,"url":"https://hooks.example.com/sms"}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"requestBody":{"required":true,"content":{"application/json":{"example":{"url":"https://hooks.example.com/sms","secret":"replace-with-a-long-secret"}}}}},"delete":{"operationId":"callback-delete","summary":"Remove the delivery callback","description":"Stop delivery and inbound callbacks for this company. Access: Normal, Admin, or Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Remove the delivery callback","content":{"application/json":{"example":{"ok":true,"configured":false}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}}}},"/api/v1/users":{"get":{"operationId":"users","summary":"Users","description":"Staff the token is allowed to see. A company admin sees one company. A super token sees every company. Other roles receive 403. Access: Admin or Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Users","content":{"application/json":{"example":{"ok":true,"users":[{"uid":"00000000-0000-0000-0000-000000000006","email":"ada@example.com","displayName":"Ada","role":"company_admin","status":"active","companyId":"00000000-0000-0000-0000-000000000000","companyName":"Acme"}]}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}}}},"/api/v1/audit":{"get":{"operationId":"audit","summary":"Audit log","description":"Company audit events, 50 per page. scope=platform is the platform-wide log and is Super only. Access: Any token; platform scope is Super.","tags":["SendSMS"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Audit log","content":{"application/json":{"example":{"ok":true,"events":[],"total":0,"page":1,"pageSize":50,"source":"neon"}}}},"401":{"description":"Missing or unknown token."},"403":{"description":"Token role cannot call this."}},"parameters":[{"name":"page","in":"query","required":false,"description":"Page number, starting at 1.","schema":{"type":"string","example":"1"}},{"name":"scope","in":"query","required":false,"description":"Omit for the token's company. platform is Super only.","schema":{"type":"string","example":"platform"}}]}}}}