File Uploads
CarvOS provides a two-step file workflow: upload files first, then reference them by carv_file_id in your webhook payloads. CarvOS handles promotion to long-term storage automatically when it processes the webhook. See the API Reference for the full upload endpoint schema.
How It Works¶
- Upload -- Send the file to
POST /uploadsand receive acarv_file_idandexpires_atdeadline - Reference -- Include the
carv_file_idin your webhook payload (e.g., a candidate's resume) - Automatic promotion -- CarvOS promotes the file to long-term storage when processing the webhook
One file, one webhook
Each carv_file_id can only be used in one webhook. Once a webhook
references a file, that file is exclusively bound to it. To attach the
same document to multiple webhooks (e.g., a candidate and an application),
upload the file once per webhook to get separate carv_file_id values.
Tip
Files expire after the expires_at deadline if not referenced in a webhook. Upload files shortly before sending the referencing webhook.
Prerequisites¶
- A valid API key (
X-API-Key) - A client identifier (
X-ATS-Client-ID) with a configured workspace mapping
Step 1: Upload a File¶
-
Send the file
Make a
POST /uploadsrequest with the file asmultipart/form-data:curl -X POST "https://api.carvos.io/uploads" \ -H "X-API-Key: your-api-key" \ -H "X-ATS-Client-ID: your-client-id" \ -F "file=@resume.pdf"Python and JavaScript examples
-
Store the reference ID
The response includes the
carv_file_idyou'll use in webhook payloads:{ "carv_file_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "file_name": "resume.pdf", "content_type": "application/pdf", "file_size": 245760, "uploaded_at": "2026-03-12T10:30:00Z", "expires_at": "2026-03-15T10:30:00Z" }The returned
content_typeis the MIME type detected from the file's content via magic bytes -- one ofapplication/pdf,application/msword, orapplication/vnd.openxmlformats-officedocument.wordprocessingml.document. TheContent-Typeheader on the multipart file part is not used.Warning
The file will be automatically deleted at
expires_atif not referenced. Send the webhook that uses this file before then.
Step 2: Reference in a Webhook Payload¶
Include the carv_file_id in the files object of your webhook payload. Each file slot accepts a FileReference with the carv_file_id:
{
"client_id": "your-client-id",
"user_id": "user-123",
"data": {
"first_name": "Jane",
"last_name": "Doe",
"email": "jane.doe@example.com"
},
"files": {
"resume": {
"carv_file_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
}
Supported File Slots¶
| Slot | Description | Used In |
|---|---|---|
resume |
Candidate resume / CV | Candidate, Application webhooks |
cover_letter |
Cover letter | Application webhooks |
Info
File references are optional. Webhooks without files work normally -- omit the files object entirely if no files are attached.
Step 3: Automatic Promotion¶
When CarvOS processes a webhook containing a carv_file_id, the referenced file is automatically promoted from staging to long-term storage. No action is required from your side.
If a referenced file has expired (past expires_at), the webhook processing will return an error indicating the file is no longer available. Upload a new file and retry the webhook.
Error Handling¶
Upload Validation Errors¶
| Status | Cause | Example |
|---|---|---|
422 |
Invalid extension | File extension '.exe' is not allowed. Allowed extensions: .doc, .docx, .pdf |
422 |
File too large | File size exceeds maximum of 52428800 bytes (50MB) |
422 |
Content mismatch | File content does not match extension '.pdf': detected 'image/png' |
Webhook Processing Errors¶
| Scenario | Cause | Resolution |
|---|---|---|
| File expired | Webhook sent after expires_at |
Upload a new file and retry |
| File not found | Invalid carv_file_id |
Verify the ID from the upload response |
| File already consumed | carv_file_id was already used in another webhook |
Upload the file again to get a new carv_file_id |
Next Steps¶
-
Send Webhooks
Webhook integration guide
-
Authentication
API key and header reference