Uploading Documents via API
This integration pattern guides you through the process of uploading documents to Kompliant and optionally linking them to workflow requirements.
Overview
A document upload workflow in Kompliant involves the following steps:
- Create a document record and receive an upload URL
- Upload the file using the URL
- Link the document to workflow requirements (optional)
This guide walks you through the sequence of API calls needed to complete these steps.
Step 1: Create the Document Record
The first step is to create a document record using the document.create endpoint. This will generate an upload URL that you'll use to upload the actual file.
POST https://api.kompliant.com/document.create
Request Body:
{
"subject_record_id": "sr_1rQYvnUQdcatd4TcZQu0l8",
"file_name": "passport.pdf",
"file_size_in_bytes": 1048576
}
Note
The
file_nameshould include the file extension such as.jpg, or.png). The system validates that the file type against the DOCUMENT_FILE_TYPES.
Response:
{
"document": {
"document_id": "d_1rQYvnUQdcatd4TcZQu0l8",
"upload_url": "https://dev-kompliant-document-management-20250212155721984000000001.s3.us-east-1.amazonaws.com",
"presign_values": {
"Content-Type": "application/pdf",
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
"X-Amz-Credential": "ASIAQHNPJKZEMJ42PUB3/20251003/us-east-1/s3/aws4_request",
"X-Amz-Date": "20251003T220920Z",
"X-Amz-Security-Token": "AMZ_SECURITY_TOKEN",
"X-Amz-Signature": "AMX_SIGNATURE",
"key": "sr_1rQYvnUQdcatd4TcZQu0l8/d_1rQYvnUQdcatd4TcZQu0l8.pdf",
"policy": "AMZ_POLICY_JWT",
"x-amz-meta-document-id": "d_1rQYvnUQdcatd4TcZQu0l8"
}
}
Save the document_id from the response - you'll need it if you want to link this document to workflow requirements in Step 3.
For more details on this API, see document.create.
Step 2: Upload the File
Using the upload_url and presign_values from the previous step, perform a multipart/form-data POST request to upload your file.
Important
The presigned URL has an expiration time of five (5) minutes. Make sure to upload the file promptly after creating the document record.
2.1 Examples
POST / HTTP/1.1
Host: kompliant-document-management.s3.us-east-1.amazonaws.com
Content-Length: 4067
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="Content-Type"
application/pdf
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="key"
sr_1rQYvnUQdcatd4TcZQu0l8/d_1rQYvnUQdcatd4TcZQu0l8.pdf
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="policy"
AMZ_POLICY_BASE64_ENCODED_STRING
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="X-Amz-Algorithm"
AWS4-HMAC-SHA256
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="X-Amz-Credential"
AMZ_ACCESS_KEY_ID/20251003/us-east-1/s3/aws4_request
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="X-Amz-Date"
20251003T220920Z
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="X-Amz-Security-Token"
AMZ_SECURITY_TOKEN
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="X-Amz-Signature"
AMZ_SIGNATURE
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="x-amz-meta-document-id"
d_1rQYvnUQdcatd4TcZQu0l8
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="passport.pdf"
Content-Type: application/pdf
(binary data)
------WebKitFormBoundary7MA4YWxkTrZu0gW--
curl -X POST "https://kompliant-document-management.s3.us-east-1.amazonaws.com" \
-F "Content-Type=application/pdf" \
-F "key=sr_1rQYvnUQdcatd4TcZQu0l8/d_1rQYvnUQdcatd4TcZQu0l8.pdf" \
-F "policy=AMZ_POLICY_BASE64_ENCODED_STRING" \
-F "X-Amz-Algorithm=AWS4-HMAC-SHA256" \
-F "X-Amz-Credential=AMZ_ACCESS_KEY_ID/20251003/us-east-1/s3/aws4_request" \
-F "X-Amz-Date=20251003T220920Z" \
-F "X-Amz-Security-Token=AMZ_SECURITY_TOKEN" \
-F "X-Amz-Signature=AMZ_SIGNATURE" \
-F "x-amz-meta-document-id=d_1rQYvnUQdcatd4TcZQu0l8" \
-F "file=@/path/to/passport.pdf"
// Assume you have the response from document.create stored in 'createResponse'
const { upload_url, presign_values, document_id } = createResponse.data.document;
// Create FormData with presign values
const formData = new FormData();
// Add all presign_values as form fields (ORDER MATTERS - add these first)
formData.append("Content-Type", presign_values["Content-Type"]);
formData.append("key", presign_values["key"]);
formData.append("policy", presign_values["policy"]);
formData.append("X-Amz-Algorithm", presign_values["X-Amz-Algorithm"]);
formData.append("X-Amz-Credential", presign_values["X-Amz-Credential"]);
formData.append("X-Amz-Date", presign_values["X-Amz-Date"]);
formData.append("X-Amz-Security-Token", presign_values["X-Amz-Security-Token"]);
formData.append("X-Amz-Signature", presign_values["X-Amz-Signature"]);
formData.append("x-amz-meta-document-id", presign_values["x-amz-meta-document-id"]);
// Add the file as the LAST field
formData.append("file", fileInput.files[0]);
// Upload file
const requestOptions = {
method: "POST",
body: formData,
redirect: "follow"
};
fetch(upload_url, requestOptions)
.then((response) => {
if (response.ok) {
console.log("File uploaded successfully!");
console.log("Document ID:", document_id);
// Proceed to Step 3 if you want to link to workflow requirements
} else {
console.error("Upload failed:", response.status);
}
})
.catch((error) => console.error("Upload error:", error));
import requests
# Assume you have the response from document.create
upload_url = response_data["data"]["document"]["upload_url"]
presign_values = response_data["data"]["document"]["presign_values"]
document_id = response_data["data"]["document"]["document_id"]
# Open the file
with open("passport.pdf", "rb") as file:
# Create multipart form data with presign values
files = {
"Content-Type": (None, presign_values["Content-Type"]),
"key": (None, presign_values["key"]),
"policy": (None, presign_values["policy"]),
"X-Amz-Algorithm": (None, presign_values["X-Amz-Algorithm"]),
"X-Amz-Credential": (None, presign_values["X-Amz-Credential"]),
"X-Amz-Date": (None, presign_values["X-Amz-Date"]),
"X-Amz-Security-Token": (None, presign_values["X-Amz-Security-Token"]),
"X-Amz-Signature": (None, presign_values["X-Amz-Signature"]),
"x-amz-meta-document-id": (None, presign_values["x-amz-meta-document-id"]),
"file": file
}
# Upload file
response = requests.post(upload_url, files=files)
if response.status_code == 204:
print(f"File uploaded successfully! Document ID: {document_id}")
# Proceed to Step 3 if you want to link to workflow requirements
else:
print(f"Upload failed: {response.status_code}")
Upload Success
A successful upload returns an HTTP status code
204 No Content. The document record in Kompliant will be automatically updated with the upload completion status.
Step 3: Link Document to Workflow Requirements (Optional)
After uploading a document, you can link it to one or more Required Documents in a workflow by creating Fulfillments. This step is optional but commonly used when documents are being collected as part of an BUSINESS_APPLICATION, BUSINESS_UNDERWRITING or ACCOUNT_PROVISIONING workflow.
Use Cases
Link documents to workflow requirements when:
- Uploading documents that fulfill specific workflow document requirements
- The same document satisfies multiple document requirements (e.g., a bank statement that serves as both proof of address and proof of account)
- Building an application where users upload documents to complete their workflow
3.1 Retrieve Required Documents for Workflow
First, get the list of Required Documents for your workflow to find the required_document_id values you need:
POST https://api.kompliant.com/workflow.requiredDocument.list
Request Body:
{
"workflow_id": "w_LKQpQvG7r6BWXBzrvFvI5"
}
Response:
"required_documents": [
{
"required_document_id": "rd_9K3mPxQvN2jL7hR5TcWfY8",
"document_type_code": "PASSPORT",
"name": "Passport Document",
"category": "REQUIREMENT",
"requirement_text": "Valid passport required",
"required_document_status": "INACTIVE",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
},
{
"required_document_id": "rd_7P2nQwRxM8kN4jS6UdXgZ9",
"document_type_code": "BANK_STATEMENT",
"name": "Bank Statement",
"category": "REQUIREMENT",
"requirement_text": "Most recent 3 months",
"required_document_status": "INACTIVE",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
]
For more details on this API, see workflow.requiredDocument.list.
3.2 Create Fulfillments to Link Documents
Use the workflow.requiredDocument.fulfillment.batchAdd endpoint to link your uploaded document to one or more Required Documents:
POST https://api.kompliant.com/workflow.requiredDocument.fulfillment.batchAdd
Request Body:
{
"workflow_id": "w_LKQpQvG7r6BWXBzrvFvI5",
"fulfillments": [
{
"required_document_id": "rd_9K3mPxQvN2jL7hR5TcWfY8",
"document_id": "d_1rQYvnUQdcatd4TcZQu0l8"
}
]
}
Multiple Fulfillments
You can link the same document to multiple Required Documents by adding multiple objects to the
fulfillmentsarray. This is useful when a single document satisfies multiple requirements such as a driver's license serving as both ID verification and proof of address.
Example - One Document for Multiple Requirements:
{
"workflow_id": "w_LKQpQvG7r6BWXBzrvFvI5",
"fulfillments": [
{
"required_document_id": "rd_9K3mPxQvN2jL7hR5TcWfY8",
"document_id": "d_1rQYvnUQdcatd4TcZQu0l8"
},
{
"required_document_id": "rd_7P2nQwRxM8kN4jS6UdXgZ9",
"document_id": "d_1rQYvnUQdcatd4TcZQu0l8"
}
]
}
Response:
"fulfillments": [
{
"fulfillment_id": "f_1rQYvnUQdcatd4TcZQu0l8",
"required_document_id": "rd_9K3mPxQvN2jL7hR5TcWfY8",
"document_id": "d_1rQYvnUQdcatd4TcZQu0l8",
"decision_status": "PENDING",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
]
For more details on this API, see workflow.requiredDocument.fulfillment.batchAdd.
Complete Integration Flow
Below is a flowchart of the complete integration pattern:
document.create
↓
Receive document_id, upload_url, and presign_values
↓
Upload file using presign_values
↓
[Optional] workflow.requiredDocument.list
↓
[Optional] workflow.requiredDocument.fulfillment.batchAdd
Best Practices
-
Error Handling: Implement proper error handling for each step:
- Check for validation errors in
document.create(invalid file types, missing fields) - Monitor upload response (204 = success)
- Handle fulfillment creation errors (invalid IDs, workflow already completed)
- Check for validation errors in
-
File Validation: Before calling
document.create, validate:- File extension is in the allowed list
- File size matches the
file_size_in_bytesparameter - File name is correctly formatted
-
Upload URL Expiration: The upload URL typically expires after 5 minutes. If you need to retry the upload:
- Call
document.createagain to get a new upload URL - You will need to use the newly created document record
- Call
-
ID Management: Maintain a mapping of IDs created during the workflow:
subject_record_idfrom workflow creationdocument_idfrom document.createrequired_document_idfrom workflow.requiredDocument.listfulfillment_idfrom fulfillment creation
-
One Document, Multiple Fulfillments: When a single document satisfies multiple requirements:
- Upload the document once using
document.createand upload URL - Create multiple fulfillment entries in the
fulfillmentsarray - This maintains storage efficiency while properly tracking requirement fulfillment
- Upload the document once using
-
Upload Verification: After file upload, you can verify the document was properly uploaded by:
- Checking for HTTP 204 response from POST call
- Using
document.getto retrieve document details and verifyupload_status - Using
workflow.requiredDocument.fulfillment.listto verify fulfillments were created
-
Content-Type Enforcement: The upload URL enforces content-type matching:
- Ensure the file being uploaded matches the content type derived from
file_name - The upload will fail if there's a mismatch between the file extension and actual file type
- Ensure the file being uploaded matches the content type derived from
Updated 7 months ago