Installation

clawhub install rosasalberto/didit-phone-verification

Summary

Two-step phone verification via one-time code:

SKILL.md

Didit Phone Verification API

Overview

Two-step phone verification via one-time code:

  1. Send a verification code to a phone number
  2. Check the code the user provides

Key constraints:

  • Code expires after 5 minutes
  • Maximum 3 verification attempts per code (then must resend)
  • Maximum 2 resend requests within 24 hours
  • Rate limit: 4 sends per hour per phone number
  • Phone must be in E.164 format (e.g. +14155552671)
  • You must call Send before Check

Delivery channels: SMS (default fallback), WhatsApp, Telegram, voice call. Falls back to SMS if preferred channel unavailable.

Capabilities: Detects disposable/temporary numbers, VoIP numbers, carrier info, and duplicate numbers. Supports fraud signals for risk scoring.

API Reference: Send Code | Check Code Feature Guide: https://docs.didit.me/core-technology/phone-verification/overview


Authentication

All requests require an API key via the x-api-key header.

How to obtain: Didit Business Console → API & Webhooks → Copy API key, or via programmatic registration (see below).

text
x-api-key: your_api_key_here

Getting Started (No Account Yet?)

If you don't have a Didit API key, create one in 2 API calls:

  1. Register: POST https://apx.didit.me/auth/v2/programmatic/register/ with {"email": "you@gmail.com", "password": "MyStr0ng!Pass"}
  2. Check email for a 6-character OTP code
  3. Verify: POST https://apx.didit.me/auth/v2/programmatic/verify-email/ with {"email": "you@gmail.com", "code": "A3K9F2"} → response includes api_key

To add credits: GET /v3/billing/balance/ to check, POST /v3/billing/top-up/ with {"amount_in_dollars": 50} for a Stripe checkout link.

See the didit-verification-management skill for full platform management (workflows, sessions, users, billing).


Step 1: Send Phone Code

Request

text
POST https://verification.didit.me/v3/phone/send/

Headers

HeaderValueRequired
x-api-keyYour API keyYes
Content-Typeapplication/jsonYes

Body (JSON)

ParameterTypeRequiredDefaultConstraintsDescription
phone_numberstringYesE.164 formatPhone number (e.g. +14155552671)
options.code_sizeintegerNo6Min: 4, Max: 8Code length
options.localestringNoMax 5 charsLocale for message. e.g. en-US
options.preferred_channelstringNo"whatsapp"See channels"sms", "whatsapp", "telegram", "voice"
signals.ipstringNoIPv4/IPv6User's IP for fraud detection
signals.device_idstringNoMax 255 charsUnique device identifier
signals.device_platformstringNoEnum"android", "ios", "ipados", "tvos", "web"
signals.device_modelstringNoMax 255 charse.g. iPhone17,2
signals.os_versionstringNoMax 64 charse.g. 18.0.1
signals.app_versionstringNoMax 64 charse.g. 1.2.34
signals.user_agentstringNoMax 512 charsBrowser user agent
vendor_datastringNoYour identifier for session tracking

Example

python
import requests

response = requests.post(
    "https://verification.didit.me/v3/phone/send/",
    headers={"x-api-key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={
        "phone_number": "+14155552671",
        "options": {"preferred_channel": "sms", "code_size": 6},
        "vendor_data": "session-abc-123",
    },
)
typescript
const response = await fetch("https://verification.didit.me/v3/phone/send/", {
  method: "POST",
  headers: { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    phone_number: "+14155552671",
    options: { preferred_channel: "sms", code_size: 6 },
  }),
});

Status Values & Handling

StatusMeaningAction
"Success"Code sentWait for user to provide code, then call Check
"Retry"Temporary issueWait a few seconds and retry (max 2 retries)
"Undeliverable"Number cannot receive messagesInform user. Try a different number
"Blocked"Number blocked (spam)Use a different number

Error Responses

CodeMeaningAction
400Invalid request bodyCheck phone format (E.164) and parameters
401Invalid or missing API keyVerify x-api-key header
403Insufficient credits/permissionsCheck credits in Business Console
429Rate limited (4/hour/number)Wait for cooldown period

Step 2: Check Phone Code

Must be called after a successful Send. Optionally auto-declines risky numbers.

Request

text
POST https://verification.didit.me/v3/phone/check/

Body (JSON)

ParameterTypeRequiredDefaultValuesDescription
phone_numberstringYesE.164Same phone used in Step 1
codestringYes4-8 charsThe code the user received
duplicated_phone_number_actionstringNo"NO_ACTION""NO_ACTION" / "DECLINE"Decline if already verified by another user
disposable_number_actionstringNo"NO_ACTION""NO_ACTION" / "DECLINE"Decline disposable/temporary numbers
voip_number_actionstringNo"NO_ACTION""NO_ACTION" / "DECLINE"Decline VoIP numbers

Example

python
response = requests.post(
    "https://verification.didit.me/v3/phone/check/",
    headers={"x-api-key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={
        "phone_number": "+14155552671",
        "code": "123456",
        "disposable_number_action": "DECLINE",
        "voip_number_action": "DECLINE",
    },
)

Response (200 OK)

json
{
  "request_id": "e39cb057-...",
  "status": "Approved",
  "message": "The verification code is correct.",
  "phone": {
    "status": "Approved",
    "phone_number_prefix": "+1",
    "phone_number": "4155552671",
    "full_number": "+14155552671",
    "country_code": "US",
    "country_name": "United States",
    "carrier": {"name": "ATT", "type": "mobile"},
    "is_disposable": false,
    "is_virtual": false,
    "verification_method": "sms",
    "verification_attempts": 1,
    "verified_at": "2025-08-24T09:12:39.662232Z",
    "warnings": [],
    "lifecycle": [...]
  }
}

Status Values & Handling

StatusMeaningAction
"Approved"Code correct, no policy violationsPhone verified — proceed
"Failed"Code incorrectAsk user to retry (up to 3 attempts)
"Declined"Code correct but policy violationCheck phone.warnings for reason
"Expired or Not Found"No pending codeResend via Step 1

Response Field Reference

phone Object

FieldTypeDescription
statusstring"Approved", "Failed", "Declined"
phone_number_prefixstringCountry prefix (e.g. +1)
full_numberstringFull E.164 number
country_codestringISO 3166-1 alpha-2
carrier.namestringCarrier name
carrier.typestring"mobile", "landline", "voip", "unknown"
is_disposablebooleanDisposable/temporary number
is_virtualbooleanVoIP number
verification_methodstring"sms", "whatsapp", "telegram", "voice"
verification_attemptsintegerCheck attempts made (max 3)
warningsarray{risk, log_type, short_description, long_description}

Warning Tags

TagDescriptionAuto-Decline
VERIFICATION_CODE_ATTEMPTS_EXCEEDEDMax code attempts exceededYes
PHONE_NUMBER_IN_BLOCKLISTPhone is in blocklistYes
HIGH_RISK_PHONE_NUMBERIdentified as high riskYes
DISPOSABLE_NUMBER_DETECTEDTemporary/disposable numberConfigurable
VOIP_NUMBER_DETECTEDVoIP number detectedConfigurable
DUPLICATED_PHONE_NUMBERAlready verified by another userConfigurable

Common Workflows

Basic Phone Verification

text
1. POST /v3/phone/send/   → {"phone_number": "+14155552671"}
2. Wait for user to provide the code
3. POST /v3/phone/check/  → {"phone_number": "+14155552671", "code": "123456"}
4. If "Approved"            → phone is verified
   If "Failed"              → retry (up to 3 attempts)
   If "Expired or Not Found"→ resend (step 1)

Strict Security Verification

text
1. POST /v3/phone/send/   → include signals.ip, signals.device_platform, channel: "sms"
2. POST /v3/phone/check/  → set disposable_number_action + voip_number_action to "DECLINE"
3. If "Declined" → check phone.warnings, block or warn user

Utility Scripts

bash
export DIDIT_API_KEY="your_api_key"

python scripts/verify_phone.py send +14155552671 --channel sms
python scripts/verify_phone.py check +14155552671 123456 --decline-voip

Recommended skills

Browse all →