KYC document uploads
Upload, confirm, list, download, and delete KYC documents through the DALP API, SDK, and CLI.
Attach KYC documents to a draft KYC version when an investor or operator needs to provide identity, address, or other review evidence. DAPI accepts base64-encoded file bytes, validates the metadata and content, encrypts the file, stores an encrypted envelope, and then creates the document record.
The document record belongs to a KYC version, not directly to the user profile. Submit the version only after the required profile fields and supporting files are in place.
Prerequisites
Before uploading, create or select a draft KYC version for the investor. A submitted or under-review version cannot receive new files. If the latest version is no longer draft, create a new draft and upload the replacement files there.
The caller must also be allowed to manage documents for that KYC version. Document download URLs are private access URLs. The document owner can open the file. A non-owner needs a KYC document read role, such as identity manager or claim issuer, before DALP returns a download URL or private file response.
Supported document inputs
A document upload through user.kyc.documents.confirmUpload requires these
fields:
versionId: draft KYC version ID.documentType:passport,drivers_license,national_id,proof_of_address, orother.fileName: original file name, up to 255 characters.fileSize: raw byte size, greater than zero and up to 25 MiB.mimeType:application/pdf,image/jpeg,image/png, orimage/webp.fileData: base64-encoded raw file bytes.
DALP checks the decoded byte length against fileSize. It also checks that the
file signature matches the declared MIME type. Send the raw byte length before
base64 encoding, not the length of the encoded string.
Quickstart
Call user.kyc.documents.confirmUpload with the KYC version ID and the
base64-encoded file bytes. DALP creates the document record only after the
payload is validated, encrypted, and stored.
The SDK method names mirror the KYC document operations: confirm upload, list,
get download URL, and delete. Direct HTTP integrations use these routes:
- Upload evidence:
POST /api/v2/kyc-profile-versions/{versionId}/documents. - List evidence:
GET /api/v2/kyc-profile-versions/{versionId}/documents. - Create a download URL:
POST /api/v2/kyc-profile-versions/{versionId}/documents/{documentId}/downloads. - Delete evidence:
DELETE /api/v2/kyc-profile-versions/{versionId}/documents/{documentId}.
import { readFile } from "node:fs/promises";
const passportBytes = await readFile("./northwind-passport.pdf");
const document = await client.user.kyc.documents.confirmUpload({
params: { versionId: "kycv_01hzt7n4passportdraft" },
body: {
documentType: "passport",
fileData: Buffer.from(passportBytes).toString("base64"),
fileName: "northwind-passport.pdf",
fileSize: passportBytes.byteLength,
mimeType: "application/pdf",
},
});The response contains the document record you can show in a review screen:
{
"data": {
"id": "kycdoc_01hzt7n4passport001",
"versionId": "kycv_01hzt7n4passportdraft",
"documentType": "passport",
"fileName": "northwind-passport.pdf",
"fileSize": 204800,
"mimeType": "application/pdf",
"uploadedAt": "2026-05-24T10:23:17.628Z",
"uploadedBy": "usr_01hzt7n4reviewer001"
}
}Do not use the legacy presigned upload flow for new KYC integrations. The current KYC document path sends file bytes through DAPI so DALP can validate and encrypt the document before object storage receives it.
List documents
Use user.kyc.documents.list to read documents attached to a KYC version.
Filters can narrow the result set, for example to one document type.
const documents = await client.user.kyc.documents.list({
params: { versionId: "kycv_01hzt7n4passportdraft" },
query: {
filters: [{ id: "documentType", operator: "eq", value: "passport" }],
},
});The response includes paginated document records and metadata, so integrations can build review screens without fetching every document at once.
Download a document
Use user.kyc.documents.getDownloadUrl with the KYC version and document ID.
DALP returns a private download URL plus document metadata such as the file name
and MIME type.
const download = await client.user.kyc.documents.getDownloadUrl({
params: {
versionId: "kycv_01hzt7n4passportdraft",
documentId: document.data.id,
},
});Use an authenticated fetch against the returned URL to retrieve the file bytes. The private file response uses no-store cache headers. Do not persist the URL as a permanent file reference. Request a fresh download URL when an operator needs to view or process the document.
Delete a document
Use user.kyc.documents.delete when an uploaded document was attached to the
wrong version, has the wrong type, or needs to be replaced before submission.
await client.user.kyc.documents.delete({
params: {
versionId: "kycv_01hzt7n4passportdraft",
documentId: document.data.id,
},
});Deleting a document removes the DALP document record from that KYC version. It does not approve, reject, or submit the KYC version.
CLI equivalents
The DALP CLI exposes the same KYC document flow for operator scripts. Use these commands when a back-office job is easier to run outside the SDK:
| Task | CLI command |
|---|---|
| Upload evidence | kyc document-confirm-upload |
| List evidence | kyc documents |
| Create download URL | kyc document-download-url |
| Delete evidence | kyc document-delete |
For uploads, pass a local filePath, versionId, documentType, fileName,
and mimeType. The CLI reads the local file, checks the 25 MiB limit before the
request, base64-encodes the file bytes, and sends them to the same DAPI endpoint
used by the SDK. If you pass fileSize, it must still match the decoded file
bytes.
Use CLI commands for back-office scripts and SDK calls for application integrations. Both paths follow the same model: send the file bytes through DAPI, let DALP validate and encrypt the document, then manage the document record on the KYC version.
Validation and error handling
Treat KYC document upload errors as terminal request errors unless the API response says otherwise. Fix the document payload or KYC version state before retrying the same upload. Store and share the request ID from the API response or HTTP headers when you escalate a repeated platform error.
| Error | What DALP observed | State change and caller response |
|---|---|---|
DALP-0610 | fileData is not valid base64 document data. | No document record is created. Encode the raw file bytes as base64 and retry. |
DALP-0611 | fileSize does not match the decoded byte length. | No document record is created. Send the raw file byte length, not the base64 length. |
DALP-0612 | The declared MIME type does not match the file signature. | No document record is created. Upload a PDF, JPEG, PNG, or WebP file with matching bytes. |
DALP-0609 | DALP could not verify or decrypt a stored document envelope. | The stored record remains private. Request the document again and escalate if it repeats. |
Security and storage model
KYC document bytes are private compliance evidence. DALP validates and encrypts the file before object storage receives it, then stores an encrypted envelope rather than the plaintext file. The public document record stores metadata such as document type, file name, file size, MIME type, upload time, and uploader.
KYC documents and review evidence remain part of the verifier or operator workflow. The on-chain identity and claims model records verification results and references, not the uploaded document bytes.