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.
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.
X-API-Key: vld_your_api_key_here
You can create and manage API keys from your dashboard.
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
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"
}'
{
"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
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"
}'
{
"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.
/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.
/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
{
"success": true,
"data": {
"verification_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "verified",
"verified_at": "2025-01-16T10:02:30Z"
}
}
Invalid Code Response
{
"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.
/api/v1/verification/:verification_id
{
"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.
/api/v1/verification/:verification_id
{
"success": true,
"data": {
"verification_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "cancelled"
}
}
Delivery Status Webhook
Receive real-time delivery status updates via webhooks.
/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