POST/v1/otp/send
Send a one-time password
Generates a code, sends it to one number from this device, and returns an otpId to verify it with.
AuthenticationDevice token
Request
curl -X POST https://api.sapa.tokoaplikasi.id/v1/otp/send \
-H "Authorization: Bearer $WA_TOKEN"
Body
| Field | Type | Description |
|---|
torequired | string | OTP-01 — the single phone number to verify. Unlike POST /v1/send this takes exactly one recipient: no comma-separated list, and no |-separated template variables. A number starting with 0 is expanded using countryCode. |
template | string | The message to send, containing the placeholder {code} exactly once — that is where the generated code is substituted. Omit it to use the gateway default. Keep your wording distinct from other senders: a template shared by everyone is a ban signal. |
countryCode | string = 62 | SEND-02 — the country code that replaces a leading 0 in to, without the +. Defaults to 62 (Indonesia). Pass "0" to disable expansion, which requires to to already be fully qualified. |
Response
200 — Accepted. The code is on its way; `200` means queued, not delivered — follow `messageId` if you need to tell "never arrived" from "typed wrong".
{
"status": true,
"otpId": "",
"expiresAt": "2026-09-04T09:12:03Z",
"messageId": ""
}| Field | Type | Description |
|---|
status | true | Always true on a successful request. |
otpId | string | The id of this one-time password. Pass it back to POST /v1/otp/verify — verification is by id, never by phone number. |
expiresAt | string | When the code stops being accepted, ISO 8601. A resend moves this forward. |
messageId | string | The message carrying the code. Follow it with GET /v1/messages/{id} or the message.status webhook to tell "never delivered" apart from "typed wrong". |
Failure modes
Every failure answers with the same envelope: { "status": false, "reason": "…" }. Match on reason, never on the status alone — the full vocabulary is on the Errors page.
| Field | Type | Description |
|---|
400 | error | The request could not be understood, the number does not normalize, the device is not connected, or the monthly quota is spent. |
401 | error | The token is missing, malformed or revoked. |
403 | error | An account token was used; sending needs the device token. |
404 | error | The token's device no longer exists. |
429 | error | Too many requests for this token, or too many codes to this number in the last hour. Wait the seconds in retryAfter. |