{"openapi":"3.0.3","info":{"title":"Sakura SMS API","version":"1.0.0","description":"Send SMS, check delivery, manage contacts, send one-time passcodes and WhatsApp template messages. Authenticate with a Bearer API key from your Sakura SMS portal."},"servers":[{"url":"https://sakurasms.com"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your API key, starting sk_live_"}}},"paths":{"/api/v1/messages":{"post":{"operationId":"send-message","tags":["Messages"],"summary":"Send an SMS","description":"Send one message to one or many recipients. Numbers may be 255XXXXXXXXX or 07XXXXXXXX. Recipients who opted out are skipped and reported. Add scheduled_at to send later. Requires the sms:send scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to","message"],"properties":{"to":{"description":"One number or an array of numbers.","type":"array"},"message":{"description":"The text. Long messages are split into parts; see Message length and cost.","type":"string"},"sender":{"description":"One of your approved Sender IDs. If omitted, your default Sender ID is used.","type":"string"},"idempotency_key":{"description":"Your own unique key. Sending the same key again returns the first result and does not send twice.","type":"string"},"scheduled_at":{"description":"A future time. The message is sent then. Must be in the future.","type":"string"},"test":{"description":"true runs the request in sandbox mode: nothing is sent and nothing is charged. You can also use ?test=true.","type":"boolean"}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"id":"clx1a2b3c4d5e6f7","status":"sent","accepted":1,"rejected":0,"results":[{"to":"255712345678","status":"accepted"}],"to":["255712345678"],"from":"ACMELTD","cost":1,"segments":1,"statusUrl":"/api/v1/messages/clx1a2b3c4d5e6f7"}}}},"401":{"description":"Missing, invalid, disabled or expired key."},"402":{"description":"Not enough credits."},"403":{"description":"The key lacks sms:send, or the account is not yet approved (it may only send to its own verified number)."},"422":{"description":"Missing to or message, no valid Tanzanian number, a past scheduled_at, or every recipient has opted out."},"429":{"description":"Rate limit or plan limit reached. See the Retry-After header."}}},"get":{"operationId":"list-messages","tags":["Messages"],"summary":"List your messages","description":"Newest first. Page through results with next_cursor.","parameters":[{"name":"limit","in":"query","required":false,"description":"Results per page. Default 20, maximum 100.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The next_cursor from the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"data":[{"id":"clx1a2b3c4d5e6f7","status":"sent"}],"next_cursor":null}}}}}}},"/api/v1/sms/send":{"post":{"operationId":"send-sms-legacy","tags":["Messages"],"summary":"Send an SMS (alternative form)","description":"The same job as POST /api/v1/messages, kept for existing integrations. It names the Sender ID field sender_id. New integrations should use POST /api/v1/messages. Requires the sms:send scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to","message"],"properties":{"to":{"description":"One number or an array of numbers.","type":"array"},"message":{"description":"The text.","type":"string"},"sender_id":{"description":"One of your approved Sender IDs.","type":"string"},"idempotency_key":{"description":"Prevents a duplicate send.","type":"string"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"success":true,"messageId":"clx1a2b3c4d5e6f7","status":"sent","accepted":1,"rejected":0,"results":[{"to":"255712345678","status":"accepted"}],"to":"255712345678","recipients":1,"segments":1,"creditsUsed":1,"statusUrl":"/api/v1/messages/clx1a2b3c4d5e6f7"}}}}}}},"/api/v1/messages/{id}":{"get":{"operationId":"get-message","tags":["Messages"],"summary":"Get one message and its delivery summary","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"id":"clx1a2b3c4d5e6f7","status":"sent","from":"ACMELTD","message":"Your order #1234 has shipped","recipients":1,"cost":1,"segments":1,"scheduled_at":null,"created_at":"2026-10-06T10:00:00.000Z","delivery":{"delivered":1},"results":[{"to":"255712345678","status":"delivered"}]}}}},"404":{"description":"No message with that id on your account."}}}},"/api/v1/messages/{id}/deliveries":{"get":{"operationId":"message-deliveries","tags":["Messages"],"summary":"Per-recipient delivery results","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Results per page. Default 100, maximum 500.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"The next_cursor from the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"data":[{"id":"d_1","recipient":"255712345678","status":"delivered","error_code":null,"delivered_at":"2026-10-06T10:00:03.000Z","updated_at":"2026-10-06T10:00:03.000Z"}],"next_cursor":null}}}},"404":{"description":"No message with that id on your account."}}}},"/api/v1/balance":{"get":{"operationId":"balance","tags":["Account"],"summary":"Check your credit balance","responses":{"200":{"description":"Success","content":{"application/json":{"example":{"balance":4200,"reserved":0,"used":800}}}}}}},"/api/v1/status":{"get":{"operationId":"status","tags":["Account"],"summary":"Service status","description":"No key needed. Useful for a quick health check from your own monitoring.","responses":{"200":{"description":"Success","content":{"application/json":{"example":{"status":"operational","timestamp":"2026-10-06T10:00:00.000Z","gateways":{"sms":true,"whatsapp":true,"ai":true}}}}}},"security":[]}},"/api/v1/senderids":{"get":{"operationId":"list-senderids","tags":["Sender IDs"],"summary":"List your Sender IDs","description":"Only an ACTIVE Sender ID can be used to send. Register new Sender IDs from the Sender IDs page of your portal, where you upload your business documents. Each brand you send for needs its own approved Sender ID, and you choose which one per message with the sender field. Requires the sms:send scope.","parameters":[{"name":"all","in":"query","required":false,"description":"Include Sender IDs that are not yet active.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":[{"id":"sid_1","label":"ACMELTD","status":"ACTIVE","isDefault":true}]}}}}}},"/api/v1/contacts":{"get":{"operationId":"list-contacts","tags":["Contacts"],"summary":"List contacts","description":"Requires the contacts:read scope.","parameters":[{"name":"page","in":"query","required":false,"description":"Page number, starting at 1.","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"Results per page.","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search by name or number.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"data":[{"id":"c_1","firstName":"Asha","lastName":"Mushi","mobile":"255712345678"}],"metadata":{"total":1,"page":1,"totalPages":1}}}}}}},"post":{"operationId":"create-contact","tags":["Contacts"],"summary":"Create a contact","description":"Requires the contacts:write scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["firstName","mobile"],"properties":{"firstName":{"description":"First name.","type":"string"},"lastName":{"description":"Last name.","type":"string"},"mobile":{"description":"Mobile number.","type":"string"},"customFields":{"description":"Your own fields, for message personalisation.","type":"object"}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"id":"c_1","firstName":"Asha","lastName":"Mushi","mobile":"255712345678"}}}}}}},"/api/v1/contacts/{id}":{"patch":{"operationId":"update-contact","tags":["Contacts"],"summary":"Update a contact","description":"Requires the contacts:write scope.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":[],"properties":{"firstName":{"description":"First name.","type":"string"},"lastName":{"description":"Last name.","type":"string"},"customFields":{"description":"Your own fields.","type":"object"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"id":"c_1","firstName":"Asha","lastName":"Mushi","mobile":"255712345678"}}}}}},"delete":{"operationId":"delete-contact","tags":["Contacts"],"summary":"Delete a contact","description":"Requires the contacts:write scope.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"success":true}}}}}}},"/api/v1/contacts/import":{"post":{"operationId":"import-contacts","tags":["Contacts"],"summary":"Import many contacts at once","description":"Requires the contacts:manage scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contacts"],"properties":{"contacts":{"description":"Each item has firstName, lastName and mobile.","type":"array"},"groupName":{"description":"Add every imported contact to this group (created if new).","type":"string"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"success":true,"count":250}}}}}}},"/api/v1/audience/groups":{"get":{"operationId":"list-groups","tags":["Contacts"],"summary":"List contact groups","description":"Requires the contacts:manage scope.","responses":{"200":{"description":"Success","content":{"application/json":{"example":[{"id":"g_1","name":"VIP customers"}]}}}}},"post":{"operationId":"create-group","tags":["Contacts"],"summary":"Create a contact group","description":"Requires the contacts:manage scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"description":"Group name.","type":"string"},"description":{"description":"Optional description.","type":"string"}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"id":"g_1","name":"VIP customers"}}}}}}},"/api/v1/audience/groups/{id}/contacts":{"get":{"operationId":"group-contacts","tags":["Contacts"],"summary":"List the contacts in a group","description":"Requires the contacts:manage scope.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":[{"id":"c_1","firstName":"Asha","mobile":"255712345678"}]}}}}}},"/api/v1/templates":{"get":{"operationId":"list-templates","tags":["Templates"],"summary":"List saved message templates","description":"Requires the contacts:manage scope.","responses":{"200":{"description":"Success","content":{"application/json":{"example":[{"id":"t_1","title":"Order shipped","content":"Hi {{firstName}}, your order has shipped."}]}}}}},"post":{"operationId":"create-template","tags":["Templates"],"summary":"Save a message template","description":"Requires the contacts:manage scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","content"],"properties":{"title":{"description":"A name for the template.","type":"string"},"content":{"description":"The message text.","type":"string"}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"example":{"id":"t_1","title":"Order shipped","content":"Hi {{firstName}}, your order has shipped."}}}}}}},"/api/v1/verify/request":{"post":{"operationId":"verify-request","tags":["One-time passcodes"],"summary":"Send a one-time passcode","description":"Sends a code to the number and returns a request_id. The code itself is never shown to you. Check what the user types with the next call. Requires the sms:send scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phone"],"properties":{"phone":{"description":"A Tanzanian number, for example +255758309999.","type":"string"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"request_id":"req_8f2c1d","status":"pending"}}}},"422":{"description":"Not a valid Tanzanian number."}}}},"/api/v1/verify/check":{"post":{"operationId":"verify-check","tags":["One-time passcodes"],"summary":"Check a one-time passcode","description":"Requires the sms:send scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["request_id","code"],"properties":{"request_id":{"description":"From the request call.","type":"string"},"code":{"description":"What the user entered.","type":"string"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"status":"approved"}}}},"400":{"description":"request_id or code missing."}}}},"/api/v1/whatsapp/send":{"post":{"operationId":"whatsapp-send","tags":["WhatsApp"],"summary":"Send an approved WhatsApp template message","description":"Business-started WhatsApp messages must use a template that is already approved. Your account needs a connected WhatsApp number. Requires the whatsapp:send scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to","template"],"properties":{"to":{"description":"Recipient number.","type":"string"},"template":{"description":"The approved template name.","type":"string"},"language":{"description":"Template language code, for example en or sw.","type":"string"},"components":{"description":"Template variables, in WhatsApp's components format.","type":"array"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"success":true,"messageId":"wamid.HBgM...","to":"255712345678","template":"order_shipped"}}}},"502":{"description":"WhatsApp could not send the message."}}}}}}