Skip to main content
POST
Upload Files

Upload Files

Use this 3-step handshake to upload files from browsers, scripts, CI jobs, or the Dcycle CLI without streaming file bytes through the API server.
1

Create presigned upload URLs

Call POST /v1/files/presigned-urls. The backend creates pending file rows and returns one presigned S3 URL per file.
2

Upload file bytes to S3

PUT the raw file bytes to each presigned URL using the same Content-Type you sent in step 1.
3

Confirm the upload

Call PATCH /v1/files/batch-update with status=uploaded. This marks the file as uploaded and emits CLASSIFY_DOCUMENT.

Step 1: Create Presigned URLs

Headers

string
required
Your API key for authenticationExample: sk_live_1234567890abcdef
string
required
Your organization UUIDExample: a8315ef3-dd50-43f8-b7ce-d839e68d51fa

Body

Send an array so one request can prepare multiple uploads.
string
required
File name without the extension.
string
required
File extension such as pdf, csv, xlsx, jpg, or png.
string
required
MIME type for the uploaded file.
integer
required
File size in kilobytes.
string
Optional folder UUID. Omit for root-level uploads.

Example

Response Fields

string
File UUID stored in PostgreSQL.
string
Starts as pending.
string
Final S3-backed file URL stored on the File record.
string
Temporary S3 PUT URL used for the direct upload.

Successful Response

Step 2: Upload to S3

Upload the raw file bytes to the presigned_url returned in step 1.

Step 3: Confirm the Upload

PATCH /v1/files/batch-update is the step that flips the file from pending to uploaded and triggers document classification.

Body

string[]
required
File IDs returned by step 1.
string
required
Use uploaded after a successful S3 upload, or error if the upload failed.
string
Optional project UUID. When present, the backend also creates file_project links.

Example

Event Trigger

When status=uploaded, the backend emits CLASSIFY_DOCUMENT with:

Common Errors

401 Unauthorized

Cause: Missing or invalid API key

403 Forbidden

Cause: The authenticated user is not a member of the organization

422 Unprocessable Entity

Cause: Missing required fields (name, extension, mime_type, size_kb)

Legacy Alternative

If you do not need the direct-to-S3 flow, POST /v1/files/upload still accepts a standard multipart upload through the backend.

List File Readings

Retrieve extracted readings after processing

Retry Processing

Re-queue a file for processing

Update Reading

Edit extracted content before creating records

Create Records

Convert readings into invoices or wastes