Didit Users API
The Users API from Didit — 6 operation(s) for users.
The Users API from Didit — 6 operation(s) for users.
openapi: 3.0.0
info:
version: 3.0.0
title: Didit Verification Billing Users API
description: Identity verification API. Authenticate with x-api-key header.
servers:
- url: https://verification.didit.me
tags:
- name: Users
paths:
/v3/users/:
get:
summary: List users
description: List [users](/entities/users) Didit assembles from KYC sessions sharing the same `vendor_data` (free-form string, NOT a UUID), plus users created via the API. Paginated, ordered by `last_session_at` desc. This endpoint does not support filtering or search parameters — fetch pages and filter client-side.
operationId: list_users
tags:
- Users
parameters:
- name: limit
in: query
schema:
type: integer
default: 50
minimum: 1
description: Page size. Defaults to 50 when omitted. There is no enforced maximum, but keep pages small for latency.
- name: offset
in: query
schema:
type: integer
default: 0
minimum: 0
description: Zero-based offset of the first record to return. Prefer following the `next` URL from the previous page over computing this by hand.
x-codeSamples:
- lang: curl
label: curl
source: "curl -X GET 'https://verification.didit.me/v3/users/?limit=50' \\\n -H 'x-api-key: YOUR_API_KEY'"
- lang: python
label: Python
source: "import requests\n\nresp = requests.get(\n 'https://verification.didit.me/v3/users/',\n headers={'x-api-key': 'YOUR_API_KEY'},\n params={'limit': 50},\n)\nresp.raise_for_status()\npage = resp.json()\nfor user in page['results']:\n print(user['vendor_data'], user['status'])"
- lang: javascript
label: JavaScript
source: "const url = new URL('https://verification.didit.me/v3/users/');\nurl.searchParams.set('limit', '50');\n\nconst page = await fetch(url, {\n headers: { 'x-api-key': process.env.DIDIT_API_KEY },\n}).then((r) => r.json());\n\nconsole.log(page.count, page.results.length);"
responses:
'200':
description: Paginated list of users with verification status, session counts, and feature breakdown.
content:
application/json:
schema:
type: object
properties:
count:
type: integer
description: Number of matching rows — exact up to 100, capped at 100 beyond that for performance. Do not use it to detect the last page; rely on `next` being `null` instead.
next:
type: string
nullable: true
description: Absolute URL of the next page, or `null` on the last page.
previous:
type: string
nullable: true
description: Absolute URL of the previous page, or `null` on the first page.
results:
type: array
items:
$ref: '#/components/schemas/UserListItem'
examples:
Example:
value:
count: 2
next: null
previous: null
results:
- didit_internal_id: f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418
vendor_data: user-abc-123
display_name: null
full_name: John Michael Doe
date_of_birth: '1990-05-15'
effective_name: John Michael Doe
status: ACTIVE
portrait_image_url: https://<media-host>/...
session_count: 3
approved_count: 2
declined_count: 0
in_review_count: 1
issuing_states:
- USA
approved_emails:
- john@example.com
approved_phones:
- '+14155551234'
features:
ID_VERIFICATION: Approved
LIVENESS: Approved
FACE_MATCH: Approved
AML: Approved
features_list:
- feature: ID_VERIFICATION
status: Approved
- feature: LIVENESS
status: Approved
- feature: FACE_MATCH
status: Approved
- feature: AML
status: Approved
last_session_at: '2025-06-15T10:30:00Z'
last_activity_at: '2025-06-15T10:30:00Z'
first_session_at: '2025-06-01T08:00:00Z'
tags:
- uuid: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
name: VIP
color: '#2567FF'
created_at: '2025-06-01T08:00:00Z'
- didit_internal_id: 6ed99d53-e8f5-4cf8-9ac1-4a506cb40f6b
vendor_data: null
display_name: Jane S.
full_name: Jane Elizabeth Smith
date_of_birth: '1985-11-22'
effective_name: Jane S.
status: FLAGGED
portrait_image_url: null
session_count: 1
approved_count: 0
declined_count: 0
in_review_count: 1
issuing_states: []
approved_emails: []
approved_phones: []
features:
ID_VERIFICATION: In Review
features_list:
- feature: ID_VERIFICATION
status: In Review
last_session_at: '2025-06-20T14:00:00Z'
last_activity_at: '2025-06-20T14:05:00Z'
first_session_at: '2025-06-20T14:00:00Z'
tags: []
created_at: '2025-06-20T14:00:00Z'
'401':
description: 'No credentials supplied. Requests to `/v3/users/*` paths without an `x-api-key` header (or `Authorization: Bearer` token) are rejected by the authentication middleware before reaching the API.'
content:
application/json:
examples:
Missing credentials:
value:
detail: You must be authenticated with a valid access token to access this endpoint.
'403':
description: 'Invalid or revoked API key, or the key cannot list users for this application. Note: on this endpoint an *invalid* key returns `403` (not `401`).'
content:
application/json:
examples:
Forbidden:
value:
detail: You do not have permission to perform this action.
'429':
description: Rate limit exceeded; back off and retry after the interval indicated in `Retry-After`.
content:
application/json:
examples:
Rate limited:
value:
detail: Request was throttled. Expected available in 30 seconds.
security:
- ApiKeyAuth: []
/v3/users/{vendor_data}/:
get:
summary: Get user
description: Fetch one [user](/entities/users) by `vendor_data` (exact match). Adds `metadata`, `comments`, and `updated_at` to the list view, and switches `tags` to the detailed tag-link shape. Returns soft-deleted users too.
operationId: get_user
tags:
- Users
parameters:
- name: vendor_data
in: path
required: true
schema:
type: string
description: Your unique identifier for the user — a free-form string (NOT a UUID). This is the same value you passed as `vendor_data` when creating the session that first introduced this user, matched exactly as sent.
example: user-abc-123
x-codeSamples:
- lang: curl
label: curl
source: "curl -X GET 'https://verification.didit.me/v3/users/user-abc-123/' \\\n -H 'x-api-key: YOUR_API_KEY'"
- lang: python
label: Python
source: "import requests\n\nresp = requests.get(\n 'https://verification.didit.me/v3/users/user-abc-123/',\n headers={'x-api-key': 'YOUR_API_KEY'},\n)\nresp.raise_for_status()\nuser = resp.json()\nprint(user['didit_internal_id'], user['status'], user['session_count'])"
- lang: javascript
label: JavaScript
source: "const vendorData = encodeURIComponent('user-abc-123');\nconst user = await fetch(\n `https://verification.didit.me/v3/users/${vendorData}/`,\n { headers: { 'x-api-key': process.env.DIDIT_API_KEY } },\n).then((r) => r.json());\n\nconsole.log(user.didit_internal_id, user.status);"
responses:
'200':
description: Full user detail including metadata, comments/activity log, and aggregated session data.
content:
application/json:
schema:
$ref: '#/components/schemas/UserDetailItem'
examples:
Active user:
value:
didit_internal_id: f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418
vendor_data: user-abc-123
display_name: null
full_name: John Michael Doe
date_of_birth: '1990-05-15'
effective_name: John Michael Doe
status: ACTIVE
metadata:
tier: premium
source: website
portrait_image_url: https://<media-host>/...
session_count: 3
approved_count: 2
declined_count: 0
in_review_count: 1
issuing_states:
- USA
approved_emails:
- john@example.com
approved_phones:
- '+14155551234'
features:
ID_VERIFICATION: Approved
LIVENESS: Approved
FACE_MATCH: Approved
AML: Approved
features_list:
- feature: ID_VERIFICATION
status: Approved
- feature: LIVENESS
status: Approved
- feature: FACE_MATCH
status: Approved
- feature: AML
status: Approved
last_session_at: '2025-06-15T10:30:00Z'
last_activity_at: '2025-06-15T10:30:00Z'
first_session_at: '2025-06-01T08:00:00Z'
tags:
- uuid: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
tag:
uuid: e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b
name: VIP
color: '#2567FF'
description: null
source: custom
created_at: '2025-05-01T09:00:00Z'
updated_at: '2025-05-01T09:00:00Z'
added_by_email: analyst@acme.com
added_by_name: Jane Analyst
created_at: '2025-06-02T11:00:00Z'
comments:
- uuid: c1111111-2222-4333-8444-555555555555
comment_type: STATUS_CHANGED
comment: null
actor_email: analyst@acme.com
actor_name: Jane Analyst
previous_status: FLAGGED
new_status: ACTIVE
previous_value: null
new_value: null
changed_fields: []
metadata: null
mentioned_emails: []
created_at: '2025-06-01T10:30:00Z'
created_at: '2025-06-01T08:00:00Z'
updated_at: '2025-06-15T10:30:00Z'
'401':
description: 'No credentials supplied. Requests to `/v3/users/*` paths without an `x-api-key` header (or `Authorization: Bearer` token) are rejected by the authentication middleware before reaching the API.'
content:
application/json:
examples:
Missing credentials:
value:
detail: You must be authenticated with a valid access token to access this endpoint.
'403':
description: 'Invalid or revoked API key, or the key cannot read this application''s users. Note: on this endpoint an *invalid* key returns `403` (not `401`).'
content:
application/json:
examples:
Forbidden:
value:
detail: You do not have permission to perform this action.
'404':
description: No user with the supplied `vendor_data` exists for this application.
content:
application/json:
examples:
Not found:
value:
detail: Not found.
'429':
description: Rate limit exceeded; back off and retry after the interval indicated in `Retry-After`.
content:
application/json:
examples:
Rate limited:
value:
detail: Request was throttled. Expected available in 30 seconds.
security:
- ApiKeyAuth: []
patch:
summary: Update user
description: 'Partial update of a user: `display_name`, `full_name`, `date_of_birth`, `status`, `metadata`, `approved_emails`/`approved_phones`/`issuing_states`. `metadata` fully replaces. **Note:** unlike [Update User Status](#patch-/v3/users/-vendor_data-/update-status/), changing `status` here does NOT record a status-change activity and does NOT sync the system blocklist — use the dedicated update-status endpoint for `BLOCKED`/unblock flows.'
operationId: update_user
tags:
- Users
parameters:
- name: vendor_data
in: path
required: true
schema:
type: string
description: Your unique identifier for the user (free-form string, NOT a UUID).
example: user-abc-123
x-codeSamples:
- lang: curl
label: curl
source: "curl -X PATCH 'https://verification.didit.me/v3/users/user-abc-123/' \\\n -H 'x-api-key: YOUR_API_KEY' \\\n -H 'Content-Type: application/json' \\\n -d '{\"display_name\": \"Jane S.\", \"status\": \"FLAGGED\"}'"
- lang: python
label: Python
source: "import requests\n\nresp = requests.patch(\n 'https://verification.didit.me/v3/users/user-abc-123/',\n headers={'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json'},\n json={'display_name': 'Jane S.', 'status': 'FLAGGED'},\n)\nresp.raise_for_status()\nprint(resp.json()['status'])"
- lang: javascript
label: JavaScript
source: "const resp = await fetch('https://verification.didit.me/v3/users/user-abc-123/', {\n method: 'PATCH',\n headers: { 'x-api-key': process.env.DIDIT_API_KEY, 'Content-Type': 'application/json' },\n body: JSON.stringify({ display_name: 'Jane S.', status: 'FLAGGED' }),\n});\nconst user = await resp.json();\nconsole.log(user.status);"
responses:
'200':
description: User updated. The full updated user record (same shape as Get User) is returned.
content:
application/json:
schema:
$ref: '#/components/schemas/UserDetailItem'
examples:
Updated:
value:
didit_internal_id: f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418
vendor_data: user-abc-123
display_name: Jane S.
full_name: Jane Elizabeth Smith
date_of_birth: '1985-11-22'
effective_name: Jane S.
status: FLAGGED
metadata:
tier: premium
portrait_image_url: https://<media-host>/...
session_count: 3
approved_count: 2
declined_count: 0
in_review_count: 1
issuing_states:
- USA
approved_emails:
- john@example.com
approved_phones:
- '+14155551234'
features:
ID_VERIFICATION: Approved
LIVENESS: Approved
FACE_MATCH: Approved
AML: Approved
features_list:
- feature: ID_VERIFICATION
status: Approved
- feature: LIVENESS
status: Approved
- feature: FACE_MATCH
status: Approved
- feature: AML
status: Approved
last_session_at: '2025-06-15T10:30:00Z'
last_activity_at: '2025-06-15T10:30:00Z'
first_session_at: '2025-06-01T08:00:00Z'
tags:
- uuid: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
tag:
uuid: e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b
name: VIP
color: '#2567FF'
description: null
source: custom
created_at: '2025-05-01T09:00:00Z'
updated_at: '2025-05-01T09:00:00Z'
added_by_email: analyst@acme.com
added_by_name: Jane Analyst
created_at: '2025-06-02T11:00:00Z'
comments: []
created_at: '2025-06-01T08:00:00Z'
updated_at: '2025-06-15T10:30:00Z'
'400':
description: Invalid body — typically an unknown `status` or a `date_of_birth` not in `YYYY-MM-DD`.
content:
application/json:
examples:
Bad status:
value:
status:
- '"INVALID" is not a valid choice.'
Bad date_of_birth:
value:
date_of_birth:
- 'Date has wrong format. Use one of these formats instead: YYYY-MM-DD.'
'401':
description: 'No credentials supplied. Requests to `/v3/users/*` paths without an `x-api-key` header (or `Authorization: Bearer` token) are rejected by the authentication middleware before reaching the API.'
content:
application/json:
examples:
Missing credentials:
value:
detail: You must be authenticated with a valid access token to access this endpoint.
'403':
description: 'Invalid or revoked API key, or the key cannot update users for this application. Note: on this endpoint an *invalid* key returns `403` (not `401`).'
content:
application/json:
examples:
Forbidden:
value:
detail: You do not have permission to perform this action.
'404':
description: No user with the supplied `vendor_data` exists for this application.
content:
application/json:
examples:
Not found:
value:
detail: Not found.
'429':
description: Rate limit exceeded; back off and retry after the interval indicated in `Retry-After`.
content:
application/json:
examples:
Rate limited:
value:
detail: Request was throttled. Expected available in 30 seconds.
security:
- ApiKeyAuth: []
requestBody:
content:
application/json:
schema:
type: object
properties:
full_name:
type: string
nullable: true
maxLength: 512
description: Full name of the user
display_name:
type: string
nullable: true
description: Custom display name for this user
date_of_birth:
type: string
format: date
nullable: true
description: Date of birth in YYYY-MM-DD format
status:
type: string
enum:
- ACTIVE
- FLAGGED
- BLOCKED
description: User lifecycle status. Changing it via this generic PATCH does NOT sync the system blocklist or record a status-change activity; prefer the update-status endpoint.
metadata:
type: object
nullable: true
description: Arbitrary JSON object you attach to the user. **Fully replaces** the existing metadata on update — merge client-side if you only want to add keys.
approved_emails:
type: array
items:
type: string
description: Verified email addresses for this user, e.g. `["john@example.com"]`. Fully replaces the stored list.
approved_phones:
type: array
items:
type: string
description: Verified phone numbers for this user. Fully replaces the stored list.
issuing_states:
type: array
items:
type: string
description: Issuing countries (ISO 3166-1 alpha-3), e.g. `["USA"]`. Fully replaces the stored list.
examples:
Rename:
summary: Set display name
value:
display_name: Jane S.
Override status:
summary: Flag the user for review
value:
status: FLAGGED
Add metadata:
summary: Replace metadata JSON
value:
metadata:
tier: premium
risk_level: low
Fix extracted DOB:
summary: Correct extracted profile fields
value:
full_name: Jane Elizabeth Smith
date_of_birth: '1985-11-22'
/v3/users/delete/:
post:
summary: Batch delete users
description: '**Hard delete** users — rows are removed permanently (including previously soft-deleted records). For everyday blocking prefer [Update User Status](#patch-/v3/users/-vendor_data-/update-status/) with `BLOCKED`. Unlike the businesses endpoint, this endpoint only accepts `vendor_data_list` or `delete_all` (no `didit_internal_id_list`).'
operationId: batch_delete_users
tags:
- Users
requestBody:
required: true
content:
application/json:
schema:
type: object
description: 'Provide `vendor_data_list` or `delete_all: true`. When `delete_all` is `true` it takes precedence and `vendor_data_list` is ignored.'
properties:
vendor_data_list:
type: array
items:
type: string
description: Your own identifiers to delete, matched exactly as sent.
delete_all:
type: boolean
default: false
description: If `true`, deletes every user in the application.
examples:
Specific users:
summary: Delete users by vendor_data
value:
vendor_data_list:
- user-123
- user-456
All users:
summary: Wipe every user in this application
value:
delete_all: true
x-codeSamples:
- lang: curl
label: curl
source: "curl -X POST 'https://verification.didit.me/v3/users/delete/' \\\n -H 'x-api-key: YOUR_API_KEY' \\\n -H 'Content-Type: application/json' \\\n -d '{\"vendor_data_list\": [\"user-123\", \"user-456\"]}'"
- lang: python
label: Python
source: "import requests\n\nresp = requests.post(\n 'https://verification.didit.me/v3/users/delete/',\n headers={'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json'},\n json={'vendor_data_list': ['user-123', 'user-456']},\n)\nresp.raise_for_status()\nprint('deleted', resp.json()['deleted'])"
- lang: javascript
label: JavaScript
source: "const resp = await fetch('https://verification.didit.me/v3/users/delete/', {\n method: 'POST',\n headers: { 'x-api-key': process.env.DIDIT_API_KEY, 'Content-Type': 'application/json' },\n body: JSON.stringify({ vendor_data_list: ['user-123', 'user-456'] }),\n});\nconst body = await resp.json();\nconsole.log('deleted', body.deleted);"
responses:
'200':
description: Users deleted. Returns the number of rows actually removed.
content:
application/json:
schema:
type: object
properties:
deleted:
type: integer
description: Number of users deleted (excludes vendor_data values that didn't match anything).
examples:
Deleted some:
value:
deleted: 2
Nothing matched:
value:
deleted: 0
'400':
description: No selector supplied (`vendor_data_list` missing/empty and `delete_all` not `true`). The error body is a JSON array.
content:
application/json:
examples:
Missing selector:
value:
- Provide vendor_data_list or set delete_all=true.
'401':
description: 'No credentials supplied. Requests to `/v3/users/*` paths without an `x-api-key` header (or `Authorization: Bearer` token) are rejected by the authentication middleware before reaching the API.'
content:
application/json:
examples:
Missing credentials:
value:
detail: You must be authenticated with a valid access token to access this endpoint.
'403':
description: 'Invalid or revoked API key, or the key cannot delete users for this application. Note: on this endpoint an *invalid* key returns `403` (not `401`).'
content:
application/json:
examples:
Forbidden:
value:
detail: You do not have permission to perform this action.
'429':
description: Rate limit exceeded; back off and retry after the interval indicated in `Retry-After`.
content:
application/json:
examples:
Rate limited:
value:
detail: Request was throttled. Expected available in 30 seconds.
security:
- ApiKeyAuth: []
/v3/users/{vendor_data}/update-status/:
patch:
summary: Update user status
description: Flip only the lifecycle `status` of a user — `ACTIVE`/`FLAGGED`/`BLOCKED` (NOT session statuses). `BLOCKED` adds the `vendor_data` to the system blocklist; moving away from `BLOCKED` removes that entry. Each change is recorded as a `STATUS_CHANGED` activity on the user.
operationId: update_user_status
tags:
- Users
parameters:
- name: vendor_data
in: path
required: true
schema:
type: string
description: Your unique identifier for the user.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- status
properties:
status:
type: string
enum:
- ACTIVE
- FLAGGED
- BLOCKED
description: New lifecycle status. `BLOCKED` also adds the `vendor_data` to the system blocklist.
examples:
Activate:
summary: Reactivate the user
value:
status: ACTIVE
Flag:
summary: Flag the user for review
value:
status: FLAGGED
Block:
summary: Block the user (adds to system blocklist)
value:
status: BLOCKED
x-codeSamples:
- lang: curl
label: curl
source: "curl -X PATCH 'https://verification.didit.me/v3/users/user-abc-123/update-status/' \\\n -H 'x-api-key: YOUR_API_KEY' \\\n -H 'Content-Type: application/json' \\\n -d '{\"status\": \"BLOCKED\"}'"
- lang: python
label: Python
source: "import requests\n\nresp = requests.patch(\n 'https://verification.didit.me/v3/users/user-abc-123/update-status/',\n headers={'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json'},\n json={'status': 'BLOCKED'},\n)\nresp.raise_for_status()\nprint(resp.json()['status'])"
- lang: javascript
label: JavaScript
source: "const resp = await fetch('https://verification.didit.me/v3/users/user-abc-123/update-status/', {\n method: 'PATCH',\n headers: { 'x-api-key': process.env.DIDIT_API_KEY, 'Content-Type': 'application/json' },\n body: JSON.stringify({ status: 'BLOCKED' }),\n});\nconst user = await resp.json();\nconsole.log(user.status);"
responses:
'200':
description: User status updated. Full user record returned.
content:
application/json:
schema:
$ref: '#/components/schemas/UserDetailItem'
examples:
Blocked:
value:
didit_internal_id: f4e5e1f2-94a9-4f86-8c16-2b7d9b4db418
vendor_data: user-abc-123
display_name: null
full_name: John Michael Doe
date_of_birth: '1990-05-15'
effective_name: John Michael Doe
status: BLOCKED
metadata:
tier: premium
source: website
portrait_image_url: https://<media-host>/...
session_count: 3
approved_count: 2
declined_count: 0
in_review_count: 1
issuing_states:
- USA
approved_emails:
- john@example.com
approved_phones:
- '+14155551234'
features:
ID_VERIFICATION: Approved
LIVENESS: Approved
FACE_MATCH: Approved
AML: Approved
features_list:
- feature: ID_VERIFICATION
status: Approved
- feature: LIVENESS
status: Approved
- feature: FACE_MATCH
status: Approved
- feature: AML
status: Approved
last_session_at: '2025-06-15T10:30:00Z'
last_activity_at: '2025-06-15T10:30:00Z'
first_session_at: '2025-06-01T08:00:00Z'
tags:
- uuid: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
tag:
uuid: e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b
name: VIP
color:
# --- truncated at 32 KB (58 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/didit/refs/heads/main/openapi/didit-users-api-openapi.yml