OTP API reference

Complete reference for the Zend OTP endpoints — sending, checking status, verifying, and analytics. All requests use the base URL https://api.tryzend.com and authenticate with your API key in the x-api-key header. For a guided walkthrough, see the OTP overview.

Send OTP

POST/otp/send

Generate a one-time password and deliver it to a phone number.

curl -X POST https://api.tryzend.com/otp/send \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+233201234567",
    "app": "my_ecommerce_app",
    "channel": "sms",
    "expiry": 10,
    "length": 6
  }'

Request fields

phone_numberstringrequired
Phone number in international format, e.g. +233201234567.
appstringrequired
Application identifier used to categorize and track OTPs.
channelstringrequired
Delivery channel. One of sms or whatsapp.
expirynumber
Expiry time in minutes. Defaults to 10.
lengthnumber
Number of digits in the code. Defaults to 6.

Response

{
  "id": "otp_64f8a1b2c3d4e5f6",
  "phone_number": "+233201234567",
  "app": "my_ecommerce_app",
  "channel": "sms",
  "expiry_minutes": 10,
  "length": 6,
  "status": "sent",
  "created_at": "2024-01-15T10:20:00Z",
  "expires_at": "2024-01-15T10:30:00Z"
}

Get OTP status

GET/otp/{id}/status

Check the current status, attempt counts, and lifecycle timestamps of an OTP.

curl https://api.tryzend.com/otp/otp_64f8a1b2c3d4e5f6/status \
  -H "x-api-key: YOUR_API_KEY"

Response

{
  "id": "otp_64f8a1b2c3d4e5f6",
  "phone_number": "+233201234567",
  "app": "my_ecommerce_app",
  "channel": "sms",
  "status": "pending",
  "attempts": 0,
  "max_attempts": 3,
  "created_at": "2024-01-15T10:20:00Z",
  "expires_at": "2024-01-15T10:30:00Z",
  "verified_at": null
}

Response fields

statusstring
Current lifecycle state. See status values.
attemptsnumber
Number of verification attempts made so far.
max_attemptsnumber
Maximum verification attempts allowed before the OTP fails.
verified_atstring | null
Timestamp of successful verification, or null if not yet verified.

Verify OTP

POST/otp/{id}/verify

Verify a code against the OTP created in the send step.

curl -X POST https://api.tryzend.com/otp/otp_64f8a1b2c3d4e5f6/verify \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "code": "123456" }'

Request fields

codestringrequired
The one-time password code the user entered.

Response

{
  "success": true,
  "message": "OTP verified successfully",
  "verified_at": "2024-01-15T10:25:00Z",
  "attempts_remaining": 2
}

Response fields

successboolean
true if the code was correct, false otherwise.
messagestring
Human-readable result message.
verified_atstring
Timestamp of successful verification. Present on success.
attempts_remainingnumber
Verification attempts left before the OTP fails.

Get analytics

GET/otp/analytics

Retrieve OTP analytics and statistics, optionally scoped to an application and time window.

curl "https://api.tryzend.com/otp/analytics?app=my_ecommerce_app&days=30" \
  -H "x-api-key: YOUR_API_KEY"

Query parameters

appstring
Filter analytics to a single application.
daysnumber
Number of days to analyze. Defaults to 30.

Status values

StatusDescription
sentOTP sent successfully
pendingWaiting for verification
verifiedSuccessfully verified
expiredOTP expired
failedVerification failed

Error responses

A failed verification returns success: false along with the number of attempts left:

{
  "success": false,
  "message": "Invalid OTP code",
  "attempts_remaining": 2
}

Note

When attempts_remaining reaches 0, the OTP moves to a failed state and can no longer be verified. Send a new OTP to retry.