Verify

Every request sends x-api-key. New here? Start with the quickstart, or read API keys.

OperationSDK callEndpoint
Send a verification codeverify.startPOST /v1/verify/start
Check a verification codeverify.checkPOST /v1/verify/check

Send a verification code

Send a verification code to a phone number using this account's approved WhatsApp authentication template. Returns a verificationId to pass to /check. ttlSeconds and codeLength may be overridden per call; everything else comes from the account's Verify configuration. A test key runs the whole flow without sending a message and returns the generated code so the path is exercisable.

await msg.verify.start({
  phone: "+919812345678",
  ttlSeconds: 300,
  codeLength: 6,
});

Body

FieldTypeRequiredDescription
phonestringyesThe recipient's phone number in E.164 format, including the country code.
channelwhatsappnoDelivery channel. WhatsApp is the only value today.
ttlSecondsintegernoHow long the code stays valid. Defaults to the account's Verify setting.
codeLengthintegernoHow many digits the code has. Defaults to the account's Verify setting.

Response 200

Example response
{
  "verificationId": "vrf_9f2c8d1e4b7a4c3f9e0d2a5b6c7d8e9f",
  "status": "pending",
  "channel": "whatsapp",
  "code": "483920"
}
FieldTypeDescription
verificationIdstringPass this to /v1/verify/check.
statuspending | approved | invalid | expired | max_attemptsAlways pending here. The other values come back from /check.
expiresAtstring (ISO 8601)After this, the code is rejected and you must start again.
channelwhatsappThe channel the code was sent over.
testModebooleanPresent and true on a test key. Nothing was sent.
codestringThe generated code. Returned on a test key only, so the flow is exercisable without a phone.

Errors

Returns 401, 403, 409, 429, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.

Check a verification code

Check a code against a verification. Always a 200 carrying the resulting statusapproved, invalid, expired or max_attempts — rather than an error status, so a client branches on one field. Re-checking a verification that already reached a terminal status returns that status unchanged and costs no attempt, which makes a retried check safe inside the TTL.

await msg.verify.check({
  verificationId: "vrf_9f2c8d1e4b7a4c3f9e0d2a5b6c7d8e9f",
  code: "483920",
});

Body

FieldTypeRequiredDescription
verificationIdstringyesThe id returned by /v1/verify/start. The vrf_ prefix is optional.
codestringyesThe code the user entered. Digits only.

Response 200

Example response
{
  "status": "pending",
  "remainingAttempts": 4
}
FieldTypeDescription
statuspending | approved | invalid | expired | max_attemptsapproved means verified. invalid is a wrong code, not an error. expired and max_attempts are terminal — start a new verification.
remainingAttemptsintegerHow many tries are left. Present only while another attempt could still approve.

Errors

Returns 401, 403, 404, 409, 429, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.