Quick Start

1

Get Your API Key

Navigate to the API Keys section in your console and create a new key. You'll receive a key starting with otp_live_ for production or otp_test_ for sandbox mode.

2

Send Your First OTP

Make a POST request to send an OTP to your user's phone number.

curl -X POST https://api.flowauxi.com/v1/otp/send \
  -H "Authorization: Bearer otp_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919876543210",
    "purpose": "login",
    "channel": "whatsapp"
  }'
3

Verify the OTP

After your user enters the OTP, verify it using the request_id from the send response.

curl -X POST https://api.flowauxi.com/v1/otp/verify \
  -H "Authorization: Bearer otp_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "otp_req_abc123",
    "otp": "123456"
  }'

Authentication

Bearer Token Authentication

All API requests must include your API key in the Authorization header. API keys are project-specific and can be managed from your console.

Authorization: Bearer otp_live_YOUR_API_KEY

API Key Types

PrefixEnvironmentDescription
otp_live_ProductionLive API key for production use. OTPs are actually delivered.
otp_test_SandboxTest API key for development. OTPs are returned in response but not delivered.

Rate Limits

Rate limits protect against abuse and ensure fair usage. Limits are applied per API key and per phone number.

Limit TypeDefaultDescription
Per API Key60/minuteTotal requests per minute across all phone numbers
Per Phone Number5/minuteOTP send requests to the same phone number
Per Phone (Hourly)10/hourMaximum OTPs to same number per hour
Verification Attempts5 per OTPMaximum wrong attempts before OTP is invalidated

Send OTP

POST/v1/otp/sendGenerate and send an OTP

Request Headers

HeaderRequiredDescription
AuthorizationRequiredBearer token with your API key
Idempotency-KeyOptionalUUID to prevent duplicate requests

Request Body

ParameterTypeRequiredDescription
tostringRequiredPhone number in E.164 format (e.g., +919876543210)
purposestringRequiredOne of: login, signup, password_reset, transaction
channelstringOptionalDelivery channel: whatsapp (default) or sms
otp_lengthintegerOptionalOTP length: 4-8 digits (default: 6)
ttlintegerOptionalTime to live in seconds: 60-600 (default: 300)
metadataobjectOptionalCustom metadata to store with the OTP request

Example Request

{
  "to": "+919876543210",
  "purpose": "login",
  "channel": "whatsapp",
  "otp_length": 6,
  "ttl": 300,
  "metadata": {
    "user_id": "usr_123",
    "session_id": "sess_456"
  }
}

Success Response (200)

{
  "success": true,
  "request_id": "otp_req_abc123def456",
  "expires_in": 300
}

Sandbox Response (200)

{
  "success": true,
  "request_id": "otp_req_abc123def456",
  "expires_in": 300,
  "sandbox": true,
  "otp": "123456"
}

Verify OTP

POST/v1/otp/verifyVerify a user-submitted OTP

Request Body

ParameterTypeRequiredDescription
request_idstringRequiredThe request_id from the send response
otpstringRequiredThe OTP code entered by the user

Success Response (200)

{
  "success": true,
  "verified": true
}

Failed Response (400)

{
  "success": false,
  "verified": false,
  "error": "INVALID_OTP",
  "message": "The OTP entered is incorrect",
  "attempts_remaining": 4
}

Resend OTP

POST/v1/otp/resendResend an OTP with channel escalation

Request Body

ParameterTypeRequiredDescription
request_idstringRequiredThe request_id from the original send
channelstringOptionalForce specific channel (whatsapp or sms)

Success Response (200)

{
  "success": true,
  "request_id": "otp_req_abc123def456",
  "expires_in": 300,
  "channel": "sms",
  "resend_count": 1
}

Check Status

GET/v1/otp/status/:request_idGet OTP request status

Path Parameters

ParameterDescription
request_idThe request_id from the send response

Success Response (200)

{
  "success": true,
  "request_id": "otp_req_abc123def456",
  "status": "pending",
  "delivery_status": "delivered",
  "expires_at": "2024-01-01T12:05:00Z",
  "attempts": 0,
  "resend_count": 0
}

Status Values

StatusDescription
pendingOTP sent, waiting for verification
verifiedOTP successfully verified
expiredOTP has expired
failedMax attempts exceeded

Error Codes

INVALID_PHONE400

The phone number format is invalid. Use E.164 format.

INVALID_PURPOSE400

Purpose must be: login, signup, password_reset, or transaction.

INVALID_CHANNEL400

Channel must be whatsapp or sms.

INVALID_OTP400

The OTP entered is incorrect.

MISSING_REQUEST_ID400

request_id is required for verification.

INVALID_API_KEY401

The API key is invalid or expired.

PHONE_BLOCKED403

This phone number has been blocked due to suspicious activity.

REQUEST_NOT_FOUND404

No OTP request found with this request_id.

ALREADY_VERIFIED409

This OTP has already been verified.

OTP_EXPIRED410

The OTP has expired. Request a new one.

RATE_LIMITED429

Too many requests. Check retry_after for when to retry.

MAX_ATTEMPTS_EXCEEDED429

Maximum verification attempts reached.

INTERNAL_ERROR500

An internal error occurred. Please try again.

Webhooks

Delivery Status Webhooks

Configure webhooks in your project settings to receive real-time delivery status updates. Webhooks are sent as POST requests with HMAC-SHA256 signature verification.

Webhook Payload

{
  "event": "otp.delivered",
  "request_id": "otp_req_abc123def456",
  "phone": "+919876543210",
  "channel": "whatsapp",
  "status": "delivered",
  "timestamp": "2024-01-01T12:00:00Z"
}

Event Types

EventDescription
otp.sentOTP has been sent to the delivery channel
otp.deliveredOTP successfully delivered to recipient
otp.failedOTP delivery failed
otp.verifiedOTP has been verified successfully
otp.expiredOTP has expired without verification

Sandbox Mode

Testing Without Real Deliveries

Use test API keys (otp_test_) to test your integration without sending real OTP messages. In sandbox mode, the OTP is returned directly in the API response.

Sandbox Features

  • OTPs are returned in the response (not delivered)
  • No charges for sandbox requests
  • Same rate limits as production
  • Full webhook support