API Documentation
VerifiedFast provides a unified REST API for verifying professional licenses and registrations across 15 professions. One endpoint, one API key, one response format. New verifications run asynchronously with a polling model for reliable results.
Base URL: https://api.verified.fast/v1
Authentication
All API requests require authentication via a Bearer token in the Authorization header.
Authorization: Bearer rk_your_api_keyYou can also use the X-API-Key header as an alternative.
API keys follow the format rk_<random>. Get your key from the pricing page.
Verify Endpoint
/v1/verifyAsync by default: For new (non-cached) verifications, this endpoint returns 202 Accepted with a job_id. Poll the status endpoint to get the final result. Cached results still return 200 instantly.
Parameters
| Param | Required | Description |
|---|---|---|
type | No | Profession type. Default: lawyer. See all 15 types below. |
name | Yes | Full professional name (or entity name for company/facility) |
state | Varies | 2-letter state code. Required for most types, optional for pilot. |
license_number | No | License, registration, or certificate number for exact matching |
bar_number | No | Bar number (lawyer type only) |
npi | No | NPI number (doctor type only) |
city | No | City for disambiguation |
organization | No | Employer or practice name for disambiguation |
firm | No | Firm name (lawyer type only) |
attorney_id | No | Internal attorney ID (lawyer type only, alternative to name) |
force | No | Set to 1 to bypass the 90-day cache |
Async Polling
New verifications (cache misses) are processed asynchronously. The API immediately returns a 202 with a job ID. Poll the status endpoint every 15-20 seconds until the result is ready.
Flow
/v1/verify/status/{jobId}Status Endpoint
Poll this endpoint with the job_id from the initial 202 response.
| Status | HTTP Code | Response |
|---|---|---|
processing | 200 | Job still running. Keep polling. |
complete | 200 | Verification data included in response. |
failed | 500 | Error details included. |
{
"status": "processing",
"job_id": "cm4x7abc123def456",
"poll_url": "/v1/verify/status/cm4x7abc123def456",
"message": "Verification in progress. Poll the poll_url for results."
}{
"status": "complete",
"job_id": "cm4x7abc123def456",
"elapsed_ms": 18430,
"source": "live",
"type": "doctor",
"data": {
"verified": true,
"match_confidence": 0.94,
"full_name": "Dr. Sarah Johnson",
"license_status": "Active",
...
}
}Profession Types
Pass one of these values as the type parameter.
| Type Value | Profession | Extra Params | Sources |
|---|---|---|---|
| lawyer | Lawyer | bar_number, firm | state bar directory, state disciplinary commission, court attorney roll |
| doctor | Physician | npi, license_number | NPI registry, state medical board, hospital profiles, physician directories |
| nurse | Nurse | license_number | state nursing board, Nursys verification |
| dentist | Dentist | license_number | state dental board, dental licensing authority |
| pharmacist | Pharmacist | license_number | state pharmacy board, pharmacy licensing authority |
| architect | Architect | license_number | state architecture board, NCARB registry |
| engineer | Engineer | license_number | state engineering board, NCEES verification |
| contractor | Contractor | license_number | state contractor licensing board, construction licensing authority |
| real-estate | Real Estate Agent | license_number | state real estate commission, real estate licensing board |
| insurance | Insurance Agent | license_number | state insurance department, insurance licensing authority |
| financial-advisor | Financial Advisor | license_number | FINRA BrokerCheck, SEC adviser database |
| lobbyist | Lobbyist | license_number | state lobbyist registry, federal lobbying disclosure database |
| pilot | Pilot | license_number | FAA airman registry |
| company | Business Entity | license_number | secretary of state registry |
| healthcare-facility | Healthcare Facility | license_number | state health department, CMS registry |
Response Format
The API returns different responses depending on whether the result is cached or requires a new verification.
Cache Hit
200 + data
New Verification
202 + job_id
Job Complete
200 + data
status"complete", "processing", or "failed"
source"cache" or "live"
job_idJob ID (only on 202 and status responses)
typeProfession type that was verified
data.verifiedWhether the professional was confirmed
data.match_confidence0.0 to 1.0 confidence score
data.full_nameVerified full name
data.professionProfession type
data.license_numberLicense or registration number
data.license_statusActive, Inactive, Suspended, etc.
data.issuing_authorityBoard or agency name
data.disciplinary_actionsDisciplinary actions on record
data.organizationEmployer or practice name
data.cityCity
data.stateState
data.sourcesURLs of sources consulted
{
"source": "cache",
"type": "doctor",
"data": {
"verified": true,
"match_confidence": 0.94,
"full_name": "Dr. Sarah Johnson",
"license_status": "Active",
"license_number": "MD-2019-43521",
"issuing_authority": "Illinois Medical Board",
...
}
}{
"status": "processing",
"job_id": "cm4x7abc123def456",
"poll_url": "/v1/verify/status/cm4x7abc123def456",
"message": "Verification in progress. Poll the poll_url for results."
}Lawyer type note: When type=lawyer (default), the response uses the legacy attorney schema with fields like bar_number, bar_status, bar_admissions, law_school, etc. for backward compatibility.
ID Verification (Hosted Link)
Create a secure hosted link for identity verification. The subject uploads a government-issued ID and selfie. gpt-5.6-luna vision analysis performs face matching and OCR extraction. Each completed verification costs 3 credits.
Flow: Create session (POST) → Send hosted URL to user → User uploads ID + selfie → Retrieve result (GET) or receive webhook callback.
/api/verified/id-verify3 creditsCreate Verification Session
Creates a new ID verification session and returns a hosted URL to send to the person being verified.
| Body Param | Required | Description |
|---|---|---|
reference_id | No | Your internal reference (e.g. user ID, order ID) |
callback_url | No | Webhook URL — receives POST when verification completes |
expires_in | No | Session expiry in seconds (default: 86400 = 24h, max: 604800 = 7d) |
curl -X POST \
-H "Authorization: Bearer vf_your_key" \
-H "Content-Type: application/json" \
-d '{
"reference_id": "user-123",
"callback_url": "https://example.com/webhook",
"expires_in": 3600
}' \
https://verified.fast/api/verified/id-verify{
"session_id": "a1b2c3d4-e5f6-...",
"verify_url": "https://verified.fast/verify/a1b2c3d4-e5f6-...",
"expires_at": "2026-03-04T16:00:00.000Z",
"status": "pending",
"reference_id": "user-123"
}/api/verified/id-verify/{sessionId}Retrieve Verification Result
Returns the current status and results of a verification session. Only the API key that created the session can retrieve it.
Session Statuses
| Status | Description |
|---|---|
pending | Waiting for user to upload ID and selfie |
processing | Images received, vision analysis in progress |
completed | Verification finished — results available |
expired | Session expired before user completed verification |
failed | Analysis failed (e.g. unreadable ID) |
{
"session_id": "a1b2c3d4-e5f6-...",
"status": "completed",
"reference_id": "user-123",
"face_match": true,
"face_confidence": 0.95,
"id_type": "drivers_license",
"id_data": {
"full_name": "John Michael Smith",
"date_of_birth": "1985-03-15",
"address": "123 Main St, Springfield, IL 62701",
"id_number": "S123-4567-8901",
"expiry_date": "2028-06-01",
"issuing_state": "IL",
"issuing_country": "US",
"is_valid_id": true,
"flags": []
},
"completed_at": "2026-03-04T15:30:00Z",
"created_at": "2026-03-04T15:25:00Z"
}/api/verified/id-verifyList Sessions
Returns your recent verification sessions. Supports filtering by status and pagination.
| Query Param | Description |
|---|---|
status | Filter by status (pending, completed, expired, etc.) |
limit | Number of results (default 20, max 100) |
offset | Pagination offset |
/api/verified/id-verify/{sessionId}Cancel Session
Cancel a pending verification session. Only works on sessions with status "pending". No credits are charged for cancelled sessions.
If you provide a callback_url when creating a session, we'll POST the result to that URL when the verification completes.
{
"event": "id_verification.completed",
"session_id": "a1b2c3d4-e5f6-...",
"face_match": true,
"face_confidence": 0.95,
"id_type": "drivers_license",
"id_data": {
"full_name": "John Michael Smith",
"date_of_birth": "1985-03-15",
"address": "123 Main St, Springfield, IL 62701",
"id_number": "S123-4567-8901",
"expiry_date": "2028-06-01",
"issuing_state": "IL"
},
"completed_at": "2026-03-04T15:30:00Z"
}Integration Examples
import requests
API = "https://verified.fast/api/verified"
HEADERS = {"Authorization": "Bearer vf_your_key"}
# Create session
session = requests.post(f"{API}/id-verify",
headers=HEADERS,
json={
"reference_id": "user-123",
"callback_url": "https://example.com/hook"
}
).json()
print(f"Send this link: {session['verify_url']}")
# Later: check result
result = requests.get(
f"{API}/id-verify/{session['session_id']}",
headers=HEADERS
).json()
if result["status"] == "completed":
print(f"Match: {result['face_match']}")
print(f"Name: {result['id_data']['full_name']}")const API = "https://verified.fast/api/verified";
const headers = {
"Authorization": "Bearer vf_your_key",
"Content-Type": "application/json"
};
// Create session
const session = await fetch(`${API}/id-verify`, {
method: "POST",
headers,
body: JSON.stringify({
reference_id: "user-123",
callback_url: "https://example.com/hook"
})
}).then(r => r.json());
console.log("Send link:", session.verify_url);
// Later: check result
const result = await fetch(
`${API}/id-verify/${session.session_id}`,
{ headers }
).then(r => r.json());
if (result.status === "completed") {
console.log("Match:", result.face_match);
console.log("Name:", result.id_data.full_name);
}SMS Phone Verification
Verify phone numbers by sending a 6-digit OTP code via SMS. The user enters the code in your application and you confirm it through the API. Each successful verification costs 10 credits.
Flow: Send code (POST /v1/sms/send) → User receives SMS → Verify code (POST /v1/sms/verify/{session_id}) → Credits deducted on success.
/v1/sms/sendSend Verification Code
Sends a 6-digit verification code to the specified phone number via SMS from (888) 374-3977.
| Body Param | Required | Description |
|---|---|---|
phone | Yes | US phone number (any format: 555-123-4567, (555) 123-4567, +15551234567) |
reference_id | No | Your internal reference for this verification (e.g. user ID) |
expires_in | No | Code expiry in seconds (default: 600 = 10min, max: 1800 = 30min) |
curl -X POST \
-H "Authorization: Bearer rk_your_key" \
-H "Content-Type: application/json" \
-d '{"phone": "(555) 123-4567", "reference_id": "user-456"}' \
https://api.verified.fast/v1/sms/send{
"session_id": "a1b2c3d4-e5f6-...",
"phone": "+1***4567",
"expires_at": "2026-03-04T12:10:00Z",
"status": "pending",
"reference_id": "user-456"
}/v1/sms/verify/{session_id}10 creditsVerify Code
Submit the 6-digit code entered by the user. 10 credits are deducted on successful verification only.
| Body Param | Required | Description |
|---|---|---|
code | Yes | The 6-digit code from the SMS |
curl -X POST \
-H "Authorization: Bearer rk_your_key" \
-H "Content-Type: application/json" \
-d '{"code": "482916"}' \
https://api.verified.fast/v1/sms/verify/a1b2c3d4-e5f6-...{
"verified": true,
"session_id": "a1b2c3d4-e5f6-...",
"phone": "+1***4567",
"reference_id": "user-456",
"verified_at": "2026-03-04T12:03:42Z"
}{
"verified": false,
"error": "Invalid code",
"attempts_remaining": 3
}/v1/sms/verify/{session_id}/resendResend Code
Generates a new 6-digit code and sends it to the same phone number. Resets the attempt counter. Maximum 3 resends per session.
{
"session_id": "a1b2c3d4-e5f6-...",
"resent": true,
"resend_count": 1,
"max_resends": 3
}/v1/sms/verify/{session_id}Check Status
Returns current session status, attempt count, and timestamps without submitting a code.
/v1/sms/verify/{session_id}Cancel Session
Cancel a pending SMS verification session. No credits are charged.
Session Statuses
| Status | Description |
|---|---|
pending | Code sent, waiting for user to submit it |
verified | Code matched — phone verified (10 credits deducted) |
expired | Session expired before code was submitted |
failed | Maximum attempts exceeded (5 wrong codes) |
cancelled | Session cancelled via DELETE |
Security
- • OTP codes are SHA-256 hashed before storage — never stored in plaintext
- • Maximum 5 verification attempts per session
- • Maximum 3 code resends per session
- • Rate limit: 10 SMS per phone number per hour
- • Configurable expiry: 1–30 minutes (default 10 min)
- • Phone numbers masked in API responses (+1***4567)
Integration Examples
import requests
API = "https://api.verified.fast/v1"
HEADERS = {"Authorization": "Bearer rk_your_key"}
# Send code
resp = requests.post(f"{API}/sms/send",
headers=HEADERS,
json={"phone": "555-123-4567", "reference_id": "user-456"}
).json()
session_id = resp["session_id"]
print(f"Code sent to {resp['phone']}")
# User enters code in your app...
user_code = input("Enter code: ")
# Verify
result = requests.post(
f"{API}/sms/verify/{session_id}",
headers=HEADERS,
json={"code": user_code}
).json()
if result.get("verified"):
print("Phone verified!")
else:
print(f"Failed: {result.get('error')}")const API = "https://api.verified.fast/v1";
const headers = {
"Authorization": "Bearer rk_your_key",
"Content-Type": "application/json"
};
// Send code
const { session_id, phone } = await fetch(
`${API}/sms/send`, {
method: "POST",
headers,
body: JSON.stringify({
phone: "555-123-4567",
reference_id: "user-456"
})
}
).then(r => r.json());
console.log(`Code sent to ${phone}`);
// After user enters code in your UI...
const result = await fetch(
`${API}/sms/verify/${session_id}`, {
method: "POST",
headers,
body: JSON.stringify({ code: userInput })
}
).then(r => r.json());
if (result.verified) {
console.log("Phone verified!");
}Caching
Verification results are cached for 90 days. Cached results return instantly with a 200 status. Cache misses start an async job and return 202.
| Scenario | HTTP Status | Latency | Behavior |
|---|---|---|---|
cache hit | 200 | 10-20ms | Data returned immediately |
cache miss | 202 | < 100ms | Returns job_id, poll for result (15-60s) |
To force a fresh verification (bypass cache), pass force=1 as a query parameter.
Error Codes
| Status | Meaning | Response Body |
|---|---|---|
200 | Success (cached result or completed job) | { "source": "...", "data": {...} } |
202 | Accepted — verification started, poll for result | { "status": "processing", "job_id": "...", "poll_url": "..." } |
400 | Bad request (missing params or invalid type) | { "error": "..." } |
401 | Unauthorized (missing or invalid API key) | { "error": "..." } |
402 | Insufficient credits | { "error": "Insufficient credits", "purchase_url": "https://verified.fast/dashboard" } |
500 | Server error / verification failed | { "error": "...", "details": "..." } |
Code Examples
# Step 1: Start a verification (returns 202 with job_id for new lookups)
curl -s -H "Authorization: Bearer rk_your_key" \
"https://api.verified.fast/v1/verify?type=doctor&name=Sarah+Johnson&state=IL"
# Response: {"status":"processing","job_id":"cm4x7abc...","poll_url":"/v1/verify/status/cm4x7abc..."}
# Step 2: Poll for results (every 15-20 seconds)
curl -s -H "Authorization: Bearer rk_your_key" \
"https://api.verified.fast/v1/verify/status/cm4x7abc..."
# When complete: {"status":"complete","data":{"verified":true,...}}
# Note: Cached results return 200 with data immediately (no polling needed)import requests, time
API = "https://api.verified.fast/v1"
HEADERS = {"Authorization": "Bearer rk_your_key"}
# Start verification
r = requests.get(f"{API}/verify", params={
"type": "doctor",
"name": "Sarah Johnson",
"state": "IL"
}, headers=HEADERS)
result = r.json()
# If cached, data is already here
if r.status_code == 200:
print(result["data"])
# If async, poll for result
elif r.status_code == 202:
job_id = result["job_id"]
for _ in range(15):
time.sleep(20)
r = requests.get(
f"{API}/verify/status/{job_id}",
headers=HEADERS
)
result = r.json()
if result["status"] == "complete":
print(result["data"])
break
if result["status"] == "failed":
print("Error:", result["error"])
breakconst API = "https://api.verified.fast/v1";
const headers = {
Authorization: "Bearer rk_your_key"
};
async function verify(type, name, state) {
const url = `${API}/verify?type=${type}`
+ `&name=${encodeURIComponent(name)}`
+ `&state=${state}`;
const res = await fetch(url, { headers });
const json = await res.json();
// Cached — return immediately
if (res.status === 200) return json.data;
// Async — poll for result
if (res.status === 202) {
const jobId = json.job_id;
for (let i = 0; i < 15; i++) {
await new Promise(r => setTimeout(r, 20000));
const poll = await fetch(
`${API}/verify/status/${jobId}`,
{ headers }
);
const status = await poll.json();
if (status.status === "complete")
return status.data;
if (status.status === "failed")
throw new Error(status.error);
}
throw new Error("Timed out");
}
}
const data = await verify("doctor", "Sarah Johnson", "IL");
console.log(data.verified, data.license_status);package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
)
const apiBase = "https://api.verified.fast/v1"
func main() {
params := url.Values{
"type": {"doctor"},
"name": {"Sarah Johnson"},
"state": {"IL"},
}
req, _ := http.NewRequest("GET",
apiBase+"/verify?"+params.Encode(), nil)
req.Header.Set("Authorization", "Bearer rk_your_key")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var initial map[string]interface{}
json.NewDecoder(resp.Body).Decode(&initial)
if resp.StatusCode == 200 {
fmt.Println("Cached:", initial["data"])
return
}
// Poll for async result
jobId := initial["job_id"].(string)
for i := 0; i < 15; i++ {
time.Sleep(20 * time.Second)
req, _ := http.NewRequest("GET",
apiBase+"/verify/status/"+jobId, nil)
req.Header.Set("Authorization", "Bearer rk_your_key")
resp, _ := http.DefaultClient.Do(req)
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
resp.Body.Close()
if result["status"] == "complete" {
fmt.Println("Result:", result["data"])
return
}
}
}Credits & Pricing
VerifiedFast uses a prepaid credit system. Purchase credits from the dashboard and each API call deducts from your balance. Credits never expire.
| API Call | Credit Cost | Dollar Cost | Description |
|---|---|---|---|
| Verify / Lookup | 1 | $0.33 | License verification for any profession |
| ID Verification | 3 | $0.99 | Photo ID + selfie face match |
| SMS Verification | 10 | $3.30 | OTP code sent and verified |
Credits are purchased at $0.33 each with a $100 minimum ($100 = 303 credits). When your balance reaches zero, the API returns 402 Insufficient credits. Purchase more credits instantly from the dashboard.