Skip to main content

Upload a Business Document

A business document goes from your client straight to storage, never through the API, in three steps:

  1. Presign: say what you are about to upload. The answer is a document_id, a url and a set of form fields.
  2. Upload: POST the file to url as multipart/form-data, with every entry of fields as is, then the file last, as a part named file. Storage refuses a file over the size limit, or of a content type other than the one presigned.
  3. Complete: tell the API the upload is done. Only completed documents (state: ready) count when you request verification, which needs at least one.

No particular document type is required, and each type holds one file. Presigning a type that already has a file replaces it: the answer carries the same document_id, and the document is pending again until you complete the new upload.

Takes a workspace-scoped API key or a dashboard session. An account-scoped key is refused with 401.

Replaces POST /api/v2/kyb/banking-verification/business/upload-document.

Authorization:

Every request is signed with your API key: a short-lived JWT, signed with your private key, sent in one header on /v3/* and /api/v2/* alike.

Headers:
Authorization: APIKey {SIGNED_JWT}

How to build and sign the JWT: Authentication.

1. Presign​

Endpoint

POST

/v3/customers/{customer_id}/kyb/documents/presign

Path parameters​

ParameterTypeDescription
customer_idstring (cst_…)Required. The business customer. Its record must be open.

Request Body Sample​

{
"slot": "certificate_of_incorporation",
"content_type": "application/pdf",
"size_bytes": 524288,
"file_name": "certificate-of-incorporation.pdf"
}

Request Body Schema​

FieldTypeDescription
slotstringRequired. The document type: certificate_of_incorporation, articles_of_incorporation, organization_chart, proof_of_address, ein_confirmation, formation, dba or other.
content_typestringRequired. application/pdf, image/jpeg or image/png. The upload must carry exactly this type.
size_bytesintegerRequired. The file's size in bytes, at most max_document_bytes (see List Business Documents). The real size is read from storage when you complete.
file_namestringThe file's name on the uploader's machine, shown back in listings. Display only.

Response Sample​

{
"document_id": "doc_01m24s2q00fqrbpn5wwx8akzr5",
"url": "https://uploads.example.com/kyb-documents",
"fields": {
"key": "kyb/01a088ec-9080-7dfb-83fc-bdcda39a6ef4/01a08991-5c00-7df0-bb54-bce750a9ff05.pdf",
"policy": "eyJleHBpcmF0aW9uIjoiMjAyNi0wOS0wOVQxNDo1MDowMFoi…",
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
"X-Amz-Credential": "ASIA…/20260909/us-east-1/s3/aws4_request",
"X-Amz-Date": "20260909T143500Z",
"X-Amz-Security-Token": "IQoJb3JpZ2luX2Vj…",
"X-Amz-Signature": "5b2f0c…",
"Content-Type": "application/pdf"
}
}

Response Schema​

FieldTypeDescription
document_idstring (doc_…)The document. Use it to complete or delete it.
urlstringWhere to POST the upload.
fieldsobjectForm fields to send with the upload, verbatim and before the file. They carry the upload policy and its signature: treat them as opaque, and presign again if the policy has expired.

Uploading​

No Authorization header: the signature travels in the fields.

curl -X POST "https://uploads.example.com/kyb-documents" \
-F "key=kyb/01a088ec-9080-7dfb-83fc-bdcda39a6ef4/01a08991-5c00-7df0-bb54-bce750a9ff05.pdf" \
-F "policy=eyJleHBpcmF0aW9uIjoiMjAyNi0wOS0wOVQxNDo1MDowMFoi…" \
-F "X-Amz-Algorithm=AWS4-HMAC-SHA256" \
-F "X-Amz-Credential=ASIA…/20260909/us-east-1/s3/aws4_request" \
-F "X-Amz-Date=20260909T143500Z" \
-F "X-Amz-Security-Token=IQoJb3JpZ2luX2Vj…" \
-F "X-Amz-Signature=5b2f0c…" \
-F "Content-Type=application/pdf" \
-F "file=@certificate-of-incorporation.pdf"

Errors​

StatusmessageWhen
400failed to parse requestThe body is not valid JSON, slot is not one of the document types, or customer_id is not a cst_… TypeID.
400unsupported_document_content_typecontent_type is not PDF, JPEG or PNG.
400document_too_largesize_bytes is over max_document_bytes, or negative.
401unauthorizedMissing or invalid signature, or an account-scoped key or customer session.
403forbiddenA dashboard member whose role does not allow this. A workspace-scoped key always may.
404customer_not_foundNo such customer in the workspace.
404kyb_not_foundThis customer has no record. Open it first.
409kyb_verification_in_flightThe record is in_review: documents are locked.
409kyb_already_approvedThe record is approved.
409kyb_rejectedThe record is rejected.
422Validation failedslot, content_type or size_bytes is missing, or size_bytes is 0; details names it.

2. Complete​

Endpoint

POST

/v3/customers/{customer_id}/kyb/documents/{document_id}/complete

Call it once the upload succeeded. It reads the file's real size and type from storage and marks the document ready.

Path parameters​

ParameterTypeDescription
customer_idstring (cst_…)Required. The business customer.
document_idstring (doc_…)Required. The document_id the presign answered.

No request body.

Response​

204 No Content, with no body.

Errors​

StatusmessageWhen
400failed to parse requestcustomer_id or document_id is not a TypeID of its kind.
401unauthorizedMissing or invalid signature, or an account-scoped key or customer session.
403forbiddenA dashboard member whose role does not allow this. A workspace-scoped key always may.
404customer_not_foundNo such customer in the workspace.
404kyb_not_foundThis customer has no record.
404document_not_foundNo such document on this record.
409document_not_uploadedNothing arrived in storage for this document. Upload it, or presign again.

Coming from v2​

v2 (POST /api/v2/kyb/banking-verification/business/upload-document)v3
the file goes through the API in one multipart/form-data callpresign, upload straight to storage, complete
accountId, documentType (form fields)customer_id (path), slot (body)
any file typePDF, JPEG or PNG, up to max_document_bytes
answers message, documentType, sizepresign answers document_id, url, fields; complete answers 204

Support and Resources​

If you need assistance or have any questions, our support team is here to help. You can contact our support team at support@blockwyre.com.

Stay Updated​

Stay up-to-date with the latest news, updates, and features from BlockWyre by following us on social media:

We are excited to have you on board and look forward to seeing how you leverage BlockWyre's powerful tools to enhance your financial operations. Happy integrating!