Skip to main content
Version: 1.0

REST API Endpoints

Copy for AI agents

Copy a complete REST API integration brief (all endpoints, headers, bodies, flows, and error codes) and paste it into ChatGPT, Cursor, Claude, or any coding agent to start implementation.

~6k characters
Preview copied content
# VerifySpeed REST API — Backend Integration Spec

Use this specification to implement a complete VerifySpeed phone verification integration on the server side.

## Overview

- Base URL: `https://api.verifyspeed.com/v1/`
- Protocol: REST, JSON request/response bodies
- Authentication: `server-key` header (from VerifySpeed dashboard). Never expose the server key in mobile or browser clients.
- Postman collection: https://documenter.getpostman.com/view/17365198/2sBXikpBjZ

## HTTP status codes

- **400** — Missing or invalid input
- **401** — Missing or invalid `server-key`
- **403** — Authorization failure
- **404** — Resource not found (e.g. unknown method name)

Non-success responses (outside 2xx) use [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem details.

## Integration flows

### Message-based flow (WhatsApp Message, Telegram Message)

1. `GET /verifications/initialize` — list available methods for the client IP
2. `POST /verifications/create` — start verification; return `verificationKey` and `deepLink` to the client app
3. User completes verification via deep link / client SDK; client receives encrypted `token`
4. Backend decrypts `token` locally (recommended) OR calls `GET /verifications/result`

### OTP flow (WhatsApp OTP, Telegram OTP, SMS OTP)

1. `GET /verifications/initialize`
2. `POST /verifications/create` with `phoneNumber` (E.164, required for OTP methods)
3. User receives OTP and enters the code in your app
4. **Validate OTP** — choose ONE approach per session:
   - **Client SDK (Android / iOS / Flutter / Web):** App calls SDK validateOTP/validateOtp; on success SDK returns `token`; app sends `token` to your backend. Does NOT use `POST /verifications/validate-otp`.
   - **Backend REST:** App sends code to your server → `POST /verifications/validate-otp` with `code`, `verificationKey`, and `server-key` (backend only).
5. Backend decrypts `token` (recommended) or calls `GET /verifications/result` for `methodName`, `dateOfVerification`, `phoneNumber`, `verificationKey`

---

## Endpoints

### 1. Initialize verification

`GET https://api.verifyspeed.com/v1/verifications/initialize`

**Headers (required):**
- `server-key`: YOUR_SERVER_KEY

**Response 200:**
```json
{
  "availableMethods": [
    { "methodName": "string", "displayName": "string" }
  ]
}
```

---

### 2. Create verification

`POST https://api.verifyspeed.com/v1/verifications/create`

**Headers (required):**
- `server-key`: YOUR_SERVER_KEY
- `Content-Type`: application/json

**Body:**
| Field | Required | Description |
|---|---|---|
| methodName | Yes | e.g. whatsapp-message, telegram-message, whatsapp-otp, telegram-otp, sms-otp |
| language | No | en (default), ar, ckb |
| phoneNumber | For OTP methods | E.164 e.g. +14255552673. Required for whatsapp-otp, telegram-otp, sms-otp |

**Response 200:**
```json
{
  "methodName": "string",
  "verificationKey": "string",
  "deepLink": "string | null"
}
```

- `deepLink`: URL for message-based methods; `null` for OTP methods.

**OTP create example body:**
```json
{
  "methodName": "whatsapp-otp",
  "language": "en",
  "phoneNumber": "+14255552673"
}
```

---

### 3. Validate OTP (backend REST — alternative to client SDK)

`POST https://api.verifyspeed.com/v1/verifications/validate-otp`

Use this when your backend validates the OTP. Alternatively, use client SDK validateOTP on Android/iOS/Flutter/Web to obtain the token without this endpoint, then send the token to your backend for decryption.

Backend-only. Do NOT call from clients with an exposed server key.

**Headers (required):**
- `server-key`: YOUR_SERVER_KEY (invalid/missing → 401)
- `Content-Type`: application/json

**Body:**
| Field | Required | Description |
|---|---|---|
| code | Yes | User OTP, max 5 characters |
| verificationKey | Yes | From create verification response |

**Response 200 (success):**
```json
{
  "succeed": true,
  "token": "string",
  "phoneNumber": "+14255552673",
  "errorMessage": null,
  "errorCode": null
}
```

**Response 200 (failure examples):**
```json
{ "succeed": false, "token": null, "phoneNumber": null, "errorMessage": "OTP verification has been expired", "errorCode": "OTP_EXPIRED" }
{ "succeed": false, "token": null, "phoneNumber": null, "errorMessage": "Invalid OTP code provided", "errorCode": "OTP_INVALID" }
{ "succeed": false, "token": null, "phoneNumber": null, "errorMessage": "OTP verification has already been verified", "errorCode": "OTP_ALREADY_VERIFIED" }
```

**Additional fields from token:** Decrypt `token` with server key (recommended) or call GET /verifications/result to obtain `methodName`, `dateOfVerification`, `verificationKey`.

---

### 4. Verification result (alternative to local decryption)

`GET https://api.verifyspeed.com/v1/verifications/result`

**Headers (required):**
- `server-key`: YOUR_SERVER_KEY
- `token`: Verification token from client SDK or validate-otp

**Response 200:**
```json
{
  "methodName": "string",
  "verificationKey": "string",
  "dateOfVerification": "2024-06-24T14:51:02.877Z",
  "phoneNumber": "+12223334455",
  "firstTimeVerified": true
}
```

- `firstTimeVerified`: Helps detect token reuse (API-only; not available with local decryption alone).

**Recommended:** Decrypt token on your server with official SDKs / EncryptionTool (see verification-result docs). Tokens expire after 5 minutes.

---

## Implementation checklist

- [ ] Store `server-key` in server environment only
- [ ] Proxy endpoint: initialize (return methods to client)
- [ ] Proxy endpoint: create (pass client IP, method, optional phone/language)
- [ ] OTP: validate via client SDK (token to backend) OR backend validate-otp endpoint — not both per session
- [ ] Message-based: return verificationKey + deepLink to client
- [ ] Verify token: local decrypt OR GET result before trusting phone number
- [ ] Handle OTP error codes: OTP_EXPIRED, OTP_INVALID, OTP_ALREADY_VERIFIED
- [ ] Use E.164 for all phone numbers

## Official SDKs (optional)

- PHP: composer require verifyspeed/vs-php (^2.1.0)
- C#: VerifySpeed.VSCSharp (^1.0.27)
- See docs for Node, Go, and client mobile SDKs

---
Generated from VerifySpeed REST API documentation. Implement server-side integration following this spec.

Postman collection

Browse and try every VerifySpeed endpoint in Postman. Includes sample requests, headers, and bodies for initialize, create, validate OTP, and verification result.

Open Postman docsOpens in a new tab

Requests and Responses

  • Our API is a REST API.
  • We use json for all request and response bodies.
  • Rate limit applied to all inbound requests. (Soon the detail will be provided)

HTTP Response Codes

When calling VerifySpeed endpoints and facing HTTP errors, the following HTTP response codes may be returned based on errors during request processing:

  • 400: Missing or invalid input data.

    • Example: Requesting for creating verification with an inactive method.
  • 401: Authentication failure.

    • Example: Missing or invalid server-key in the HTTP request.
  • 403: Authorization failure.

    • Example: Attempting to access another user's data. Do not try this one.
  • 404: Resource not found.

    • Example: Using a non-existent method name.

For non-success HTTP responses (e. g., status codes outside 200-299), the response body follows the format defined by RFC 9457.

Possible Error Responses:

When provided server key is invalid server key
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Application not found",
"status": 404,
"errors": [
"server-key": ["Invalid server key"]
]
}
When something goes wrong during verification process
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Invalid request, please contact support. (error code: VF0001)",
"status": 400,
"errors": []
}

Creating Phone Number Verification

Initialization

Endpoint: GET https://api.verifyspeed.com/v1/verifications/initialize

Request Headers:

  • server-key: Server key obtained from the [dashboard].
curl -X GET "https://api.verifyspeed.com/v1/verifications/initialize" \
-H "server-key: YOUR_SERVER_KEY"

Response (200 OK):

{
"availableMethods": [
{
"methodName": "string",
"displayName": "string"
}
]
}
  • availableMethods: A list of available verification methods for the client. (See Verification Methods for more details)
    • methodName: Identifier for the verification method (e.g., whatsapp-messege).
    • displayName: Display name of the method (e.g., WhatsApp Message).

Creating the Verification

Endpoint: Post https://api.verifyspeed.com/v1/verifications/create

Request Headers:

  • server-key: Server key obtained from the [dashboard].
curl -X POST "https://api.verifyspeed.com/v1/verifications/create" \
-H "server-key: YOUR_SERVER_KEY" \
-H "Content-Type: application/json" \
-d '{
"methodName": "whatsapp-message",
"language": "en"
}'
  • methodName: The selected verification method (required) (e.g., whatsapp-message, whatsapp-otp). (See Verification Methods for more details)
  • language: The language to be used (optional) (e.g., en).
  • phoneNumber: The user's phone number in E.164 format (e.g., +14255552673). Required when methodName is an OTP method (whatsapp-otp, telegram-otp, or sms-otp). Omit for message-based methods (whatsapp-message, telegram-message).

Notes:

  • Supported languages for now:
    • en for English (Default)
    • ar for Arabic
    • ckb for Central Kurdish
  • OTP methods: When you create a verification with an OTP method, you must include phoneNumber in the request body. VerifySpeed sends a one-time password to that number via the selected channel (WhatsApp, Telegram, or SMS). Your client app collects the code from the user, then validates it either on the client (SDK) or on your backend (Validating OTP REST endpoint).

Response

Response (200 OK)
{
"methodName": "string",
"verificationKey": "string",
"deepLink": "string"
}
  • methodName: Method name of the used verification method.
  • verificationKey: The key that identifies the verification.
  • deepLink (nullable): URL to complete verification by deep linking. Returned for message-based methods (whatsapp-message, telegram-message). null for OTP methods (whatsapp-otp, telegram-otp, sms-otp).

OTP method example

When creating an OTP verification, include phoneNumber in the request body. VerifySpeed delivers the OTP to that number; your app prompts the user to enter the code.

curl -X POST "https://api.verifyspeed.com/v1/verifications/create" \
-H "server-key: YOUR_SERVER_KEY" \
-H "Content-Type: application/json" \
-d '{
"methodName": "whatsapp-otp",
"language": "en",
"phoneNumber": "+14255552673"
}'

Validating OTP

After creating an OTP verification, you can complete OTP validation in two ways. Both return a verification token on success that your backend decrypts (or resolves via the result API) to obtain full verification details.

ApproachWhere OTP is validatedHow you get the token
Client SDK (recommended for mobile/web apps)Android, iOS, Flutter, or Web client SDKSDK validateOTP / validateOtp returns the token in an success callback; the app sends the token to your backend.
Backend REST API (this section)Your server calls VerifySpeedPOST /v1/verifications/validate-otp with server-key; response includes token and phoneNumber.

Use one approach per verification session—not both. Client SDK docs: Android OTP, iOS OTP, Flutter OTP, Web OTP.

Backend REST API: validate-otp

Call this from your backend when the user's app sends the OTP code to your server (instead of validating via the client SDK). Requests must include your server-key—do not call this endpoint from mobile or web clients with the server key exposed. On success, the response includes a verification token and phoneNumber.

Endpoint: POST https://api.verifyspeed.com/v1/verifications/validate-otp

Request Headers:

  • server-key (required): Server key obtained from the [dashboard]. Requests without a valid server key receive 401.
curl -X POST "https://api.verifyspeed.com/v1/verifications/validate-otp" \
-H "server-key: YOUR_SERVER_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "12345",
"verificationKey": "YOUR_VERIFICATION_KEY"
}'

Request Body:

  • code (required): The OTP code entered by the user (max 5 characters).
  • verificationKey (required): The verificationKey returned from Creating the Verification for the same OTP session.

Response (200 OK):

Success
{
"succeed": true,
"token": "string",
"phoneNumber": "+14255552673",
"errorMessage": null,
"errorCode": null
}
OTP expired
{
"succeed": false,
"token": null,
"phoneNumber": null,
"errorMessage": "OTP verification has been expired",
"errorCode": "OTP_EXPIRED"
}
Invalid OTP code
{
"succeed": false,
"token": null,
"phoneNumber": null,
"errorMessage": "Invalid OTP code provided",
"errorCode": "OTP_INVALID"
}
OTP already verified
{
"succeed": false,
"token": null,
"phoneNumber": null,
"errorMessage": "OTP verification has already been verified",
"errorCode": "OTP_ALREADY_VERIFIED"
}

Response Fields:

  • succeed: true when the code is valid for the given verificationKey; otherwise false.
  • token (nullable): Verification token returned when succeed is true. Decrypt it or pass it to the verification result endpoint to read full verification details (see below).
  • phoneNumber (nullable): Verified phone number in E.164 format (e.g., +14255552673). Returned when succeed is true.
  • errorMessage (nullable): Human-readable error description when succeed is false.
  • errorCode (nullable): Machine-readable error code when succeed is false. Known values:
    • OTP_EXPIRED: The OTP session has expired.
    • OTP_INVALID: The provided code does not match.
    • OTP_ALREADY_VERIFIED: This verification was already completed; validate again only if you started a new OTP session.

Additional verification details from the token

The validate-otp response gives you phoneNumber immediately on success. For other fields—such as the verification method used (methodName), when the user was verified (dateOfVerification), and verificationKey—decrypt the returned token on your server or call the result API. Both approaches are documented under Verification Result:

  1. Local token decryption (recommended) — Decrypt the token with your server key on your backend. No extra VerifySpeed API call. See Verification Result Documentation for package and language examples.
  2. Verification result API — Send the token to GET /v1/verifications/result with your server-key. Returns the same data plus firstTimeVerified for reuse detection. See Alternative: API Endpoint below.

Example fields available after decrypting the token or calling the result endpoint:

FieldDescription
phoneNumberVerified number in E.164 format.
dateOfVerificationUTC timestamp when verification completed.
methodNameVerification method used (e.g., whatsapp-otp, sms-otp).
verificationKeyKey that identifies this verification session.

Verification Result

Recommended Approach: Client-side Token Decryption

Instead of calling the verification result endpoint, we recommend that your server decrypts the verification token directly using your server key. This approach is more efficient, secure, and eliminates the need for an additional API call.

How It Works:

  1. Client receives encrypted token after completing verification
  2. Client sends token to your server (not to VerifySpeed)
  3. Your server decrypts the token using your server key
  4. Extract verification details directly from the decrypted token

Benefits:

  • Faster: No additional API calls to VerifySpeed
  • More Secure: Token decryption happens on your server
  • Cost Effective: Reduces API usage
  • Real-time: Immediate access to verification data

Implementation:

For detailed implementation examples, see Verification Result Documentation which includes:

  • Official Packages: Ready-to-use decryption tools for each language
  • Manual Implementation: Complete code examples for custom implementations
  • Security Best Practices: Token expiry validation and error handling
  • Multi-language Support: C#, Node.js, PHP, Python, and Go examples

Alternative: API Endpoint

If you still need to use the API endpoint, here's the implementation:

Endpoint: GET https://api.verifyspeed.com/v1/verifications/result

Request Headers:

  • server-key: Server key obtained from the [dashboard].
  • token: The verification token received from the client.
curl -X GET "https://api.verifyspeed.com/v1/verifications/result" \
-H "server-key: YOUR_SERVER_KEY" \
-H "token: YOUR_VERIFICATION_TOKEN"

Response (200 OK):

{
"methodName": "string",
"verificationKey": "string",
"dateOfVerification": "2024-06-24T14:51:02.877Z",
"phoneNumber": "+12223334455",
"firstTimeVerified": true
}

Response Fields:

  • methodName: The method name (e.g., whatsapp-messege) of the verification method used to verify the phone number.
  • verificationKey: The key that identifies the verification.
  • dateOfVerification: The date and time (in UTC) when the phone number was verified.
  • phoneNumber: The verified phone number in E.164 format (e.g. +14255552673 (1 is country code)).
  • firstTimeVerified: Indicates whether this token has been verified for the first time or not by VerifySpeed API. Can be used for security reasons to prevent token reuse.