Custodian
KYC

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.

MethodPath
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

FieldTypeDescription
idstringSubmission UUID
refIdstringShort public reference generated by Xellar
appIdstringYour app UUID
subIdstring | nullOptional link to your account subID
fullNamestringApplicant name
emailstringApplicant email
countrystringCountry (free text / ISO as you collect)
statusstringSee Statuses
lastStagestringWorkflow stage: personal_details, id_face_scan, proof_of_address, aml_details
rejectReasonstring | nullSet when status is rejected
documentsobject | omittedMap of document type → { s3Key, contentType, uploadedAt } (internal storage keys)
personalDetailsobject | omittedArbitrary JSON you supply (AML extras, etc.)
submittedAtstring | nullRFC3339 when submitted for review
createdAtstringRFC3339
updatedAtstringRFC3339

Statuses

StatusMeaning
draftCreated; not yet collecting documents
awaiting_documentsEditable; upload required files
submittedLocked; awaiting Xellar / partner review
approvedKYC approved
rejectedRejected (rejectReason may be set)
transmission_failedCould 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

FieldTypeRequiredDescription
fullNamestringYesApplicant legal name
emailstringYesApplicant email
countrystringYesCountry
subIdstringNoOptional link to Account subID
personalDetailsobjectNoExtra JSON stored on the submission

Response 201

{ "data": { /* submission object, status draft */ } }

List Submissions

GET /api/v1/kyc/submissions

QueryDefaultDescription
page1Page number
limit20Page 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 */ } }

CodeMeaning
404Not found

Update Submission

PATCH /api/v1/kyc/submissions/:id

Only while status is draft or awaiting_documents.

FieldTypeDescription
fullNamestringReplace name
emailstringReplace email
countrystringReplace country
personalDetailsobjectReplace personal details JSON
lastStagestringAdvance 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 fieldRequiredDescription
documentTypeYesOne of: idFront, idBack, selfie, proofOfAddress
fileYesImage or PDF (max 10 MiB)

Response 200

Returns updated submission object in data.

CodeMeaning
400Invalid document type or missing file
404Submission not found
503Document 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.

CodeMeaning
400Missing documents or not editable
404Not found