KYC Submissions
Create and manage end-user KYC packages for your app. Flow: create → update details → upload documents → submit for review. All endpoints require authentication.
| Method | Path |
|---|---|
POST | /api/v1/kyc/submissions |
GET | /api/v1/kyc/submissions |
GET | /api/v1/kyc/submissions/:id |
PATCH | /api/v1/kyc/submissions/:id |
POST | /api/v1/kyc/submissions/:id/documents |
POST | /api/v1/kyc/submissions/:id/submit |
:id may be the submission UUID or the human-readable refId.
Submission object
| Field | Type | Description |
|---|---|---|
id | string | Submission UUID |
refId | string | Short public reference generated by Xellar |
appId | string | Your app UUID |
subId | string | null | Optional link to your account subID |
fullName | string | Applicant name |
email | string | Applicant email |
country | string | Country (free text / ISO as you collect) |
status | string | See Statuses |
lastStage | string | Workflow stage: personal_details, id_face_scan, proof_of_address, aml_details |
rejectReason | string | null | Set when status is rejected |
documents | object | omitted | Map of document type → { s3Key, contentType, uploadedAt } (internal storage keys) |
personalDetails | object | omitted | Arbitrary JSON you supply (AML extras, etc.) |
submittedAt | string | null | RFC3339 when submitted for review |
createdAt | string | RFC3339 |
updatedAt | string | RFC3339 |
Statuses
| Status | Meaning |
|---|---|
draft | Created; not yet collecting documents |
awaiting_documents | Editable; upload required files |
submitted | Locked; awaiting Xellar / partner review |
approved | KYC approved |
rejected | Rejected (rejectReason may be set) |
transmission_failed | Could not deliver to upstream KYC provider (retry via support) |
Only draft and awaiting_documents submissions can be updated or receive new uploads.
Create Submission
POST /api/v1/kyc/submissions
| Field | Type | Required | Description |
|---|---|---|---|
fullName | string | Yes | Applicant legal name |
email | string | Yes | Applicant email |
country | string | Yes | Country |
subId | string | No | Optional link to Account subID |
personalDetails | object | No | Extra JSON stored on the submission |
Response 201
{ "data": { /* submission object, status draft */ } }List Submissions
GET /api/v1/kyc/submissions
| Query | Default | Description |
|---|---|---|
page | 1 | Page number |
limit | 20 | Page size (max 100) |
status | — | Filter by status |
search | — | Search refId, name, or email |
Response 200
{
"data": {
"items": [ /* submission objects */ ],
"total": 1,
"page": 1,
"limit": 20
}
}Get Submission
GET /api/v1/kyc/submissions/:id → { "data": { /* submission */ } }
| Code | Meaning |
|---|---|
| 404 | Not found |
Update Submission
PATCH /api/v1/kyc/submissions/:id
Only while status is draft or awaiting_documents.
| Field | Type | Description |
|---|---|---|
fullName | string | Replace name |
email | string | Replace email |
country | string | Replace country |
personalDetails | object | Replace personal details JSON |
lastStage | string | Advance stage (personal_details, id_face_scan, proof_of_address, aml_details) |
Upload Document
POST /api/v1/kyc/submissions/:id/documents
multipart/form-data (not JSON-signed body for the file part — sign the empty body or the exact bytes your client sends; typical clients use multipart with an empty signed body).
| Form field | Required | Description |
|---|---|---|
documentType | Yes | One of: idFront, idBack, selfie, proofOfAddress |
file | Yes | Image or PDF (max 10 MiB) |
Response 200
Returns updated submission object in data.
| Code | Meaning |
|---|---|
| 400 | Invalid document type or missing file |
| 404 | Submission not found |
| 503 | Document storage not configured |
Submit for Review
POST /api/v1/kyc/submissions/:id/submit (no body)
Requires all four document types uploaded. Sets status to submitted.
| Code | Meaning |
|---|---|
| 400 | Missing documents or not editable |
| 404 | Not found |