Documentation

Learn how to integrate Valid's SMS verification API into your application.

Introduction

Valid provides a simple, secure API for sending SMS verification codes to your users. Our API handles code generation, SMS delivery, and verification - so you can focus on building your application.

Base URL https://localhost:3000/api/v1

Authentication

All API requests require authentication using an API key. Include your API key in the X-API-Key header with every request.

Header
X-API-Key: vld_your_api_key_here

You can create and manage API keys from your dashboard.

Keep your API keys secure!

Never expose your API keys in client-side code or public repositories. Always make API calls from your backend server.

Quickstart

Get started with SMS verification in just two API calls:

Step 1: Send a verification code

Request POST
curl -X POST http://localhost:3000/api/v1/verification \
  -H "X-API-Key: vld_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+14155551234"
  }'
Response 201 Created
{
  "success": true,
  "data": {
    "verification_id": "550e8400-e29b-41d4-a716-446655440000",
    "phone_number": "+14155551234",
    "status": "pending",
    "expires_at": "2025-01-16T10:05:00Z",
    "created_at": "2025-01-16T10:00:00Z"
  }
}

Step 2: Verify the code

Request POST
curl -X POST http://localhost:3000/api/v1/verification/check \
  -H "X-API-Key: vld_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "verification_id": "550e8400-e29b-41d4-a716-446655440000",
    "code": "123456"
  }'
Response 200 OK
{
  "success": true,
  "data": {
    "verification_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "verified",
    "verified_at": "2025-01-16T10:02:30Z"
  }
}

API Reference

Send Verification

Send a verification code to a phone number via SMS.

POST /api/v1/verification

Request Body

Parameter Type Required Description
phone_number string Yes Phone number in E.164 format (e.g., +14155551234)
options.code_length integer No Length of the code (4-8). Default: 6
options.expiration_seconds integer No Code expiry time in seconds (60-600). Default: 300
options.locale string No Message locale (e.g., en-US, es-ES, fr-FR)
options.sender_id string No Custom sender ID (max 11 characters)
options.metadata object No Custom metadata to attach to the verification

Response

Field Type Description
verification_id string Unique identifier for this verification
phone_number string The phone number (E.164 format)
status string Current status: pending, delivered, verified, expired, failed
expires_at string ISO 8601 timestamp when the code expires
created_at string ISO 8601 timestamp when created

Check Code

Verify a code submitted by the user.

POST /api/v1/verification/check

Request Body

Parameter Type Required Description
verification_id string Yes* The verification ID from the send response
phone_number string Yes* Phone number (alternative to verification_id)
code string Yes The verification code entered by the user

* Either verification_id or phone_number is required.

Success Response

200 OK
{
  "success": true,
  "data": {
    "verification_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "verified",
    "verified_at": "2025-01-16T10:02:30Z"
  }
}

Invalid Code Response

200 OK
{
  "success": false,
  "error": {
    "code": "INVALID_CODE",
    "message": "The verification code is incorrect",
    "attempts_remaining": 2
  }
}

Get Verification Status

Retrieve the current status of a verification.

GET /api/v1/verification/:verification_id
Response 200 OK
{
  "success": true,
  "data": {
    "verification_id": "550e8400-e29b-41d4-a716-446655440000",
    "phone_number": "+14155551234",
    "status": "delivered",
    "delivery_status": "delivered",
    "attempts": 0,
    "max_attempts": 3,
    "expires_at": "2025-01-16T10:05:00Z",
    "created_at": "2025-01-16T10:00:00Z"
  }
}

Cancel Verification

Cancel an active verification request.

DELETE /api/v1/verification/:verification_id
Response 200 OK
{
  "success": true,
  "data": {
    "verification_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "cancelled"
  }
}

Delivery Status Webhook

Receive real-time delivery status updates via webhooks.

POST /webhooks/vonage/delivery

Configure your webhook URL in your SMS provider dashboard to receive delivery notifications.

Webhook Payload

{
  "message_uuid": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
  "to": "14155551234",
  "from": "Valid",
  "timestamp": "2025-01-16T10:00:01Z",
  "status": "delivered",
  "error": null
}

Status Values

Status Description
submitted Message submitted to carrier
delivered Message delivered to device
failed Delivery failed
rejected Message rejected by carrier

Error Handling

The API uses standard HTTP status codes and returns consistent error responses.

Error Response Format

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": []  // Optional validation errors
  }
}

Error Codes

Code HTTP Status Description
VALIDATION_ERROR 400 Invalid request parameters
MISSING_API_KEY 401 No API key provided
INVALID_API_KEY 401 API key not found or invalid
API_KEY_DISABLED 403 API key has been disabled
MAX_ATTEMPTS_EXCEEDED 403 Too many incorrect code attempts
NOT_FOUND 404 Verification not found
VERIFICATION_EXPIRED 410 Verification code has expired
RATE_LIMIT_EXCEEDED 429 Too many requests
INVALID_CODE 200 Incorrect verification code

Rate Limits

Rate limits protect the API from abuse and ensure fair usage for all customers.

Limit Type Default Description
Per phone number (minute) 1 request Prevents SMS flooding to a single number
Per phone number (hour) 5 requests Hourly limit per phone number
Per IP address (minute) 10 requests General API protection
Per API key (minute) 60 requests Configurable per API key

Rate limit headers are included in all responses:

RateLimit-Limit: 60
RateLimit-Remaining: 59
RateLimit-Reset: 1705402800

Best Practices

Security

  • Never expose your API key in client-side code
  • Always validate phone numbers before sending verification requests
  • Implement your own rate limiting on top of ours for additional protection
  • Use HTTPS for all API requests

User Experience

  • Show a countdown timer for code expiration
  • Display remaining attempts after an incorrect code
  • Allow users to request a new code (respecting rate limits)
  • Pre-format phone number input fields for E.164 format

Error Handling

  • Handle all error codes gracefully with user-friendly messages
  • Implement exponential backoff for rate limit errors
  • Log verification failures for fraud detection