Developer Documentation
Programmatic identity verification for your workforce. Create cases, track verification progress, and receive real-time webhook notifications.
Go to Settings → API Keys in the console and create a key. The full key is shown once - store it securely.
POST to /v1/cases/ with the subject's email and verification methods.
The response includes a verification_url. If email verification is enabled, the link is sent automatically. Otherwise, share it with the subject directly.
Set up a webhook endpoint to receive case.closed events.
All API requests require a Bearer token. Include your API key in the Authorization header:
Authorization: Bearer ad_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys start with ad_live_. Keep them secret - treat them like passwords. Revoke compromised keys immediately in the console.
curl -X POST https://api.authduty.com/v1/cases/ \
-H "Authorization: Bearer ad_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"subject_email": "[email protected]",
"verification_methods": {
"email": true,
"government_id": true
},
"notes": "New hire verification"
}'
| Method | Endpoint | Description |
|---|---|---|
| Cases | ||
| POST | /v1/cases/ | Create a verification case |
| GET | /v1/cases/ | List cases (cursor-paginated) |
| GET | /v1/cases/{id}/ | Get case detail |
| Account | ||
| GET | /v1/account/ | Team info |
| GET | /v1/account/usage/ | Current period usage |
| Webhooks | ||
| POST | /v1/webhooks/endpoints/ | Create a webhook endpoint |
| GET | /v1/webhooks/endpoints/ | List webhook endpoints |
| GET | /v1/webhooks/endpoints/{id}/ | Get endpoint detail |
| PATCH | /v1/webhooks/endpoints/{id}/ | Update endpoint |
| DELETE | /v1/webhooks/endpoints/{id}/ | Delete endpoint |
| POST | /v1/webhooks/endpoints/{id}/rotate-secret/ | Regenerate signing secret |
| POST | /v1/webhooks/endpoints/{id}/test/ | Send test ping |
| GET | /v1/webhooks/deliveries/ | List delivery attempts (cursor-paginated) |
| Utility | ||
| GET | /v1/ping | Health check (no auth required) |
Each case requires at least one verification method. Pass the desired methods in the verification_methods object when creating a case.
| Method | Key | Notes |
|---|---|---|
| Click-through link sent automatically to the subject's email at case creation | ||
| SMS | sms | Subject enters their phone number on the verification page and receives an OTP code |
| Government ID | government_id | Document scan via Stripe Identity. Automatically enables selfie |
| Selfie | selfie | Face match against government ID photo |
| Custom Question | custom_question | Requires custom_question_text and custom_question_answer |
| Manager | manager | Requires manager_name and manager_email. Manager receives a verification request |
Cases expire 48 hours after creation. The response includes expires_at (ISO 8601) and is_expired (boolean).
List endpoints use cursor-based pagination, returning 50 results per page ordered by newest first.
Applies to GET /v1/cases/ and GET /v1/webhooks/deliveries/.
{
"next": "https://api.authduty.com/v1/cases/?cursor=cD0yMDI2...",
"previous": null,
"results": [
{ "id": "550e8400-...", "status": "open", "..." : "..." }
]
}
Follow the next URL to fetch subsequent pages. When next is null, you've reached the end.
# Fetch the first page
curl -H "Authorization: Bearer $API_KEY" \
"https://api.authduty.com/v1/cases/"
# Follow the "next" URL for subsequent pages
curl -H "Authorization: Bearer $API_KEY" \
"https://api.authduty.com/v1/cases/?cursor=cD0yMDI2..."
List endpoints accept optional query parameters to filter results. All filters are combinable and preserved across paginated responses.
| Parameter | Type | Description |
|---|---|---|
| status | string | open, closed, or failed |
| subject_email | string | Exact match on subject email |
| created_after | datetime | ISO 8601 (e.g. 2026-01-01T00:00:00Z) |
| created_before | datetime | ISO 8601 |
curl -H "Authorization: Bearer $API_KEY" \
"https://api.authduty.com/v1/cases/?status=open&created_after=2026-01-01T00:00:00Z"
| Parameter | Type | Description |
|---|---|---|
| endpoint_id | UUID | Filter by webhook endpoint |
| status | string | pending, success, failed, or dead_letter |
| event_type | string | e.g. case.closed |
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"public_id": "a1b2c3d4",
"status": "open",
"subject_email": "[email protected]",
"subject_name": null,
"created_at": "2026-03-23T12:00:00Z",
"expires_at": "2026-03-25T12:00:00Z",
"is_expired": false,
"verification_url": "https://verify.authduty.com/v/a1b2c3d4",
"verification_methods": {
"email": { "requested": true, "verified": false },
"government_id": { "requested": true, "verified": false },
"selfie": { "requested": true, "verified": false }
},
"notes": "New hire verification"
}
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Acme Widgets Inc.",
"plan": "starter",
"subscription_status": "active",
"topup_balance_cents": 2500,
"created_at": "2025-11-01T09:00:00Z"
}
{
"billing_period_start": "2026-03-01T00:00:00Z",
"billing_period_end": "2026-04-01T00:00:00Z",
"usage": {
"email": {
"allowed": 100, "included_used": 12, "topup_used": 0,
"topup_cost_cents": 0, "total_used": 12, "percent_used": 12.0
},
"sms": {
"allowed": 50, "included_used": 3, "topup_used": 0,
"topup_cost_cents": 0, "total_used": 3, "percent_used": 6.0
}
}
}
All errors return a JSON body with error,
detail, and
code fields:
{
"error": "insufficient_allowance",
"detail": "SMS allowance exhausted and insufficient top-up balance.",
"code": "INSUFFICIENT_ALLOWANCE"
}
| HTTP Status | Code | Description |
|---|---|---|
| 401 | - | Missing or invalid API key |
| 400 | INVALID_IDEMPOTENCY_KEY | Idempotency key exceeds 64 characters |
| 404 | NOT_FOUND | Resource not found or belongs to another team |
| 409 | IDEMPOTENCY_KEY_EXPIRED | Idempotency key older than 24 hours |
| 422 | TRIAL_EXPIRED | Team's trial period has ended |
| 422 | INSUFFICIENT_ALLOWANCE | Monthly allowance exhausted, insufficient top-up balance |
| 422 | VALIDATION_ERROR | Invalid input (missing fields, bad values) |
| 422 | ENDPOINT_LIMIT_REACHED | Maximum 10 webhook endpoints per team |
| 422 | INVALID_URL | Webhook URL is not HTTPS or uses non-standard port |
| 422 | INVALID_EVENTS | Invalid or missing event types |
| 429 | - | Rate limited (check Retry-After header) |
AuthDuty sends webhook notifications to your HTTPS endpoints when events occur. Each delivery is signed with HMAC-SHA256 and retried with exponential backoff on failure.
Event types, payload format, delivery headers, retry schedule, signature verification, auto-disable behavior, and secret rotation.
View Webhook Docs →| Operation | Limit |
|---|---|
| Read endpoints (GET) | 120 requests/min |
| Write endpoints (POST, PATCH, DELETE) | 30 requests/min |
When rate limited, the response includes a Retry-After header with the number of seconds until the next allowed request.
All API paths are prefixed with /v1/.
Breaking changes will be introduced under a new version prefix. Non-breaking additions (new fields, new endpoints) may extend v1.