KYC and compliance
All routes require x-api-key; none requires an API-key permission flag. KYC routes additionally require a bearer session. Compliance routes accept a valid session, x-profile-id plus x-team-id, or a team/profile-scoped API key.
For business teams, an admin profile uses the team KYB workflow for session creation and status. Every other profile uses the user’s KYC workflow.
Endpoints#
| Method | Path | Context | Success |
|---|---|---|---|
POST | /v1/kyc/session | Session | 201 |
GET | /v1/kyc/status | Session | 200 |
GET | /v1/kyc/verifications | Session | 200 |
POST | /v1/compliance/checkout | Session, headers, or scoped key | 200 |
POST | /v1/compliance/pay-via-request | Session, headers, or scoped key | 200 |
API-key failures return 403, rate limits return 429, and required-session failures return 401.
POST /v1/kyc/session#
Creates a hosted identity-verification session for the current profile.
Headers: x-api-key, Authorization: Bearer <session>, and Content-Type: application/json.
| Field | Type | Required | Constraints |
|---|---|---|---|
email | string | Yes | Valid email. |
metadata | object | No | String keys and arbitrary JSON values; defaults to {}. |
{
"success": true,
"data": {
"sessionUrl": "https://verify.example/session/abc123",
"verificationId": "verification-session-id",
"status": "not started"
}
}The provider status is lowercased in the normal workflow. Staging environments can return an immediately approved demo session instead of a live provider session.
| Status | Code | Message |
|---|---|---|
400 | APP_V1_KYC_SESSION_ROUTE_01 | Missing profile context |
400 | body parser code | Invalid request body |
404 | APP_V1_KYC_SESSION_ROUTE_04 | Profile not found |
404 | propagated | Profile lookup failed |
500 | propagated | Provider session or verification-record creation failed |
GET /v1/kyc/status#
Returns the latest applicable verification status: team KYB for a business-team admin, otherwise user KYC.
Headers: x-api-key and Authorization: Bearer <session>.
When a verification exists:
{
"success": true,
"data": {
"isVerified": true,
"status": "approved",
"verification": {
"id": "verification-uuid",
"verificationId": "provider-session-id",
"status": "approved",
"verficationProvider": "didit",
"createdAt": "2026-07-28T17:00:00.000Z",
"data": {}
}
}
}When no user KYC verification exists, isVerified is false, status is none, and verification is null. verficationProvider is the response field’s current spelling.
| Status | Code | Message |
|---|---|---|
400 | APP_V1_KYC_STATUS_ROUTE_01 | Missing profile context |
404 | APP_V1_KYC_STATUS_ROUTE_02 | Profile not found |
404 or 500 | propagated | Profile or verification lookup failed |
GET /v1/kyc/verifications#
Lists all user KYC verification records newest first. This route does not switch to team KYB for business admins.
Headers: x-api-key and Authorization: Bearer <session>.
{
"success": true,
"data": [
{
"id": "verification-uuid",
"verificationId": "provider-session-id",
"status": "approved",
"verficationProvider": "didit",
"createdAt": "2026-07-28T17:00:00.000Z",
"data": {}
}
]
}verficationProvider is intentionally spelled as returned by the API.
| Status | Code | Message |
|---|---|---|
400 | APP_V1_KYC_VERIFICATIONS_ROUTE_01 | Missing profile context |
404 | APP_V1_KYC_VERIFICATIONS_ROUTE_04 | Profile not found |
404 | propagated | Profile lookup failed |
500 | propagated | Verification lookup failed |
Compliance context#
Compliance routes use the first valid context source:
- A valid bearer session’s current profile/team.
x-profile-idandx-team-id, validated as a membership.- The API key’s own team/profile scope.
For header context, send both headers. An invalid or unavailable context returns 401 from context resolution or 400 from the route. These routes do not require an admin role.
POST /v1/compliance/checkout#
Creates a hosted yearly compliance-fee subscription checkout.
Headers: x-api-key (required); one compliance context source; Content-Type: application/json when sending a body.
The body may be omitted or be {}.
| Field | Type | Required | Constraints |
|---|---|---|---|
successUrl | string | No | Valid URL. Overrides the configured success redirect. |
cancelUrl | string | No | Valid URL. Overrides the configured cancel redirect. |
If either field is omitted, the route uses its configured default. Both resolved URLs must exist.
{
"success": true,
"data": {
"checkoutUrl": "https://checkout.example/session/abc123",
"sessionId": "checkout-session-id",
"mode": "subscription"
}
}checkoutUrl can be null if the payment provider creates a session without a URL.
| Status | Code | Message |
|---|---|---|
400 | APP_V1_COMPLIANCE_CHECKOUT_ROUTE_01 | Missing profile context |
404 | APP_V1_COMPLIANCE_CHECKOUT_ROUTE_02 | Profile not found |
400 | APP_V1_COMPLIANCE_CHECKOUT_ROUTE_03 | Missing checkout redirect URLs |
500 | APP_V1_COMPLIANCE_CHECKOUT_ROUTE_04 | Failed to create Stripe checkout session |
500 | APP_V1_COMPLIANCE_CHECKOUT_ROUTE_05 | Vudy channel not found |
400 | APP_V1_COMPLIANCE_CHECKOUT_ROUTE_06 | Invalid JSON body / Invalid body |
500 | propagated | Profile, configuration, channel, or payment-provider lookup failed |
POST /v1/compliance/pay-via-request#
Gets or creates an on-chain compliance-fee payment request for the active team.
Headers: x-api-key (required) plus one compliance context source. There is no request body.
When a pending request already exists:
{
"success": true,
"data": {
"amountUsd": 100,
"customId": "compliance-fee-team-uuid",
"id": "request-uuid",
"url": "/request/request-id",
"embedUrl": "/request/embed/request-id"
}
}When a request is created, data always contains amountUsd and customId plus the public fields returned by the request-creation operation. That operation is not narrowed to a route-specific response schema in the implementation.
| Status | Code | Message |
|---|---|---|
400 | APP_V1_COMPLIANCE_PAY_VIA_REQUEST_ROUTE_01 | Missing profile context |
404 | APP_V1_COMPLIANCE_PAY_VIA_REQUEST_ROUTE_02 | Payer profile not found |
500 | APP_V1_COMPLIANCE_PAY_VIA_REQUEST_ROUTE_03 | COMPLIANCE_FEE_MAKER_PROFILE_ID is required |
404 | APP_V1_COMPLIANCE_PAY_VIA_REQUEST_ROUTE_04 | Maker profile not found |
500 | APP_V1_COMPLIANCE_PAY_VIA_REQUEST_ROUTE_05 | Vudy channel not found |
500 | propagated | Profile, pending-request, channel, or request creation failed |