Documents
Certivant documents API reference — multipart upload of passports, government IDs, selfies, and proof-of-address files to a KYC request, fetch signed download URLs, and view supported document types and status values.
Documents are attached to a request, not to an applicant directly. Every upload moves the parent request closer to "ready for submission" — once pendingDocTypes is empty, you can submit the request for processing.
Upload a document
POST /api/v1/kyc/requests/:requestId/documents Scope: kyc:write
Multipart upload. Pass documentType (and side if applicable) as query parameters, and the file in a file form field.
Query parameters
| Param | Type | Required | Notes |
|---|---|---|---|
documentType | enum | yes | See list below |
side | enum | conditional | front or back. Required for GOVERNMENT_ID |
Form body
| Field | Type | Notes |
|---|---|---|
file | binary | The document file. Max 10 MB. MIME types: image/jpeg, image/png, image/webp, application/pdf |
Document types
| Value | Description | Two-sided? |
|---|---|---|
GOVERNMENT_ID | National ID card, driver's license, residence permit | Yes |
PASSPORT | Passport biodata page | No |
SELFIE | Live photo of the applicant for face match + liveness | No |
PROOF_OF_ADDRESS | Utility bill, bank statement, government letter (≤ 3 months old) | No |
CERTIFICATE_OF_INCORPORATION | KYB — proof the company exists | No |
COMPANY_OWNERSHIP_STRUCTURE | KYB — org chart or shareholder ledger | No |
BANK_STATEMENT | Account statement for source-of-funds checks | No |
OTHER | Anything not listed — use sparingly; checks won't run on OTHER documents | No |
Always upload the highest-resolution version you have. The OCR and authenticity checks degrade fast below 1024px on the long edge. JPEG at quality 80+ is fine; avoid pre-compressing to "save bandwidth."
Example
# Upload the front of a driver's license
curl -X POST "https://app.certivant.com/api/v1/kyc/requests/req_01J.../documents?documentType=GOVERNMENT_ID&side=front" \
-H "Authorization: Bearer ck_live_..." \
-F "file=@/path/to/license-front.jpg"
Response (201)
{
"id": "doc_01J...",
"documentType": "GOVERNMENT_ID",
"side": "front",
"status": "pending",
"fileSize": 412938,
"mimeType": "image/jpeg",
"requestStatus": "PENDING_UPLOAD",
"pendingDocTypes": ["GOVERNMENT_ID", "SELFIE"],
"message": "Document uploaded. Front of GOVERNMENT_ID received; back of GOVERNMENT_ID still required."
}
The response always tells you what's still missing via pendingDocTypes. When that array is empty, your next call should be POST /requests/:id/submit.
Document status values
pending— uploaded, not yet processed (only happens before request submission).verified— passed all authenticity checks after the request was submitted.failed— failed an authenticity check. Look at the linked check records onGET /requests/:idfor the specific reason.corrupted— file could not be decoded. Re-upload.
Errors
400 BAD_REQUEST:- File exceeds 10 MB.
- Unsupported MIME type.
sidemissing forGOVERNMENT_ID.documentTypenot allowed by the org's KYC settings.
404 NOT_FOUND— the parent request doesn't exist in this organization.409 CONFLICT— request is not inPENDING_UPLOAD. You cannot add documents to a request that has already been submitted.
Get a download URL
GET /api/v1/kyc/requests/:requestId/documents/:docId/url Scope: kyc:read
Documents are stored in private object storage. To view or download one, fetch a short-lived signed URL.
Response
{
"url": "https://storage.certivant.com/kyc/org_.../req_.../doc_....jpg?X-Amz-Signature=...",
"expiresIn": 900
}
expiresIn is in seconds — the URL is valid for 15 minutes. Generate a fresh one whenever you need to display a document; do not cache them.
The returned url is a presigned storage URL (S3 / Azure Blob / GCS). It opens directly in a browser tab and renders with no Authorization header:
- Images (
image/jpeg,image/png,image/webp) →<img src="{url}" /> - PDFs (
application/pdf) →<iframe src="{url}" />or<object data="{url}" type="application/pdf" />
Check each document's mimeType (from GET /requests/:id) to decide which to render.
Signed URLs are unauthenticated by definition — anyone with the URL can view the document until it expires. Never log them, never include them in emails, never expose them client-side without an authorization check on your side.
Download the raw bytes
GET /api/v1/kyc/requests/:requestId/documents/:docId/download Scope: kyc:read
Streams the document file bytes back directly, with the stored Content-Type (image/jpeg, image/png, image/webp, or application/pdf) and Content-Disposition: inline. No signed URL, no redirect.
curl -L "https://app.certivant.com/api/v1/kyc/requests/req_01J.../documents/doc_01J.../download" \
-H "Authorization: Bearer ck_live_..." \
-o government_id_front.jpg
Prefer this over the signed-URL route when you render documents inside your own dashboard:
- It works for every storage backend, including local disk — whose signed
/uploads/…URL is only reachable from inside the Certivant host and will 404 from another origin. - Proxy it through your backend and serve it same-origin (
<img src="/your-proxy/doc">for images,<iframe>for PDFs). TheAuthorization: Bearerkey stays server-side and never reaches the browser. - No storage URL is ever exposed, so there's nothing to leak or expire.
Which one do I use? Use /url when you're fine sending the browser a
short-lived public storage link (cloud storage, e.g. S3/Azure). Use
/download when you want to keep everything behind your own auth, or when
Certivant is running on local-disk storage. The /download route is the
safe default for a partner console.
Replacing documents
You cannot edit a document in place. If the applicant uploaded a blurry photo and you want a retake:
- The request must be in
PENDING_UPLOAD(or you must resubmit a rejected request first to clear the prior documents). - Upload a new document with the same
documentTypeandside. The previous one is superseded — only the latest version is used for processing.
This rule exists for audit integrity: an immutable history of every upload survives in the audit log, even when the active document changes.
Listing documents on a request
There is no separate documents-list endpoint. The full list is included in the response from GET /api/v1/kyc/requests/:id:
{
"id": "req_...",
"documents": [
{ "id": "doc_a", "documentType": "GOVERNMENT_ID", "side": "front", "status": "verified", ... },
{ "id": "doc_b", "documentType": "GOVERNMENT_ID", "side": "back", "status": "verified", ... },
{ "id": "doc_c", "documentType": "SELFIE", "status": "verified", ... }
]
}
Iterate over documents and call /download (to proxy the bytes) or /url (for a signed link) on any specific document you want to display.
Related
- KYC requests — the parent endpoint your documents attach to.
- Hosted sessions — let Certivant collect documents from the applicant directly.
- Schemas — full enumeration of
documentType,status, and related values.
KYB requests
Certivant KYB API reference — attach company details, directors, and ultimate beneficial owners to a BUSINESS request, trigger registry lookups, and manage per-officer KYC sub-requests.
Hosted sessions
Generate a short-lived URL where the applicant completes document capture, liveness, and identity steps.