Use this guide when your automation needs to return large files that exceed the 4.5 MB request body limit enforced at our API edge. The direct-upload flow keeps the callback payload lightweight while preserving the same fields your existing integrations expect.
POST /api/orders/callback/prepare to get signed upload URL(s) and object_key. This reserves the upload slots and returns signed URLs.PUT <signed_upload_url> with the file bytes. This performs the actual file uploads to secure storage.POST /api/orders/callback with your normal payload, referencing each object_key. After all uploads succeed, this sends the callback to complete the order.For smaller payloads you can keep using base64 or hosted URLs exactly as before—those paths are unchanged.
The callback schema is the same one documented in the standard guide. For large uploads, add object_key inside each files entry (alongside filename and mime_type) so the platform can fetch the binary you uploaded.
x-callback-secret from the Connect step.Use this flow when you need to upload one large file that exceeds 4.5 MB.
Call the prepare endpoint before uploading. Include your callback secret and file descriptor.
Endpoint: POST /api/orders/callback/prepare
Headers: Content-Type: application/json, x-callback-secret: YOUR_SECRET
{
"order_id": "order-uuid",
"filename": "final-video.mp4",
"mime_type": "video/mp4",
"file_size": 9328475
}The response returns everything you need to upload:
{
"ok": true,
"order_id": "order-uuid",
"is_test_mode": false,
"filename": "20241109-ab12cd-final-video.mp4",
"object_key": "orders/order-uuid/20241109-ab12cd-final-video.mp4",
"upload_url": "https://SIGNED_UPLOAD_URL",
"requires_headers": {
"Content-Type": "video/mp4"
},
"expires_in": 3600,
"max_bytes": 157286400
}Perform an HTTP PUT directly to the signed upload_url. Send the raw bytes of the file as the body and include any required headers (at minimum Content-Type).
PUT https://SIGNED_UPLOAD_URL
Content-Type: video/mp4
Content-Length: 9328475
<binary file content>On success you will receive a 200 response from our secure storage layer. If the upload fails, retry the PUT (you do not need to call prepare again unless the signed URL expires).
Once the upload succeeds, send your normal callback payload and reference the uploaded file using theobject_key. This keeps output types consistent with legacy behaviour.
⚠️ Important: These are template examples. Replace all placeholders with real values:
• order-uuid → Use the actual order_id from your webhook payload
• object_key → Use the exact object_key returned by the prepare endpoint
• Include the x-callback-secret header in your request (see cURL example below)
Video file:
{
"ok": true,
"order_id": "order-uuid",
"output_type": "video",
"files": [
{
"object_key": "orders/order-uuid/20241109-ab12cd-final-video.mp4",
"filename": "final-video.mp4",
"mime_type": "video/mp4"
}
]
}PDF document:
{
"ok": true,
"order_id": "order-uuid",
"output_type": "file",
"files": [
{
"object_key": "orders/order-uuid/20241109-ab12cd-report.pdf",
"filename": "report.pdf",
"mime_type": "application/pdf"
}
]
}Image file:
{
"ok": true,
"order_id": "order-uuid",
"output_type": "file",
"files": [
{
"object_key": "orders/order-uuid/20241109-ab12cd-chart.png",
"filename": "chart.png",
"mime_type": "image/png"
}
]
}Excel spreadsheet:
{
"ok": true,
"order_id": "order-uuid",
"output_type": "xlsx",
"files": [
{
"object_key": "orders/order-uuid/20241109-ab12cd-data.xlsx",
"filename": "data.xlsx",
"mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}
]
}Audio file:
{
"ok": true,
"order_id": "order-uuid",
"output_type": "file",
"files": [
{
"object_key": "orders/order-uuid/20241109-ab12cd-audio.mp3",
"filename": "audio.mp3",
"mime_type": "audio/mpeg"
}
]
}curl -X POST "https://api.example.com/api/orders/callback" \
-H "Content-Type: application/json" \
-H "x-callback-secret: your-callback-secret" \
-d '{
"ok": true,
"order_id": "test-order-uuid",
"output_type": "video",
"files": [
{
"object_key": "orders/test-order-uuid/20241109-ab12cd-final-video.mp4",
"filename": "final-video.mp4",
"mime_type": "video/mp4"
}
]
}'ok: Must be true for successorder_id: UUID from the original webhook payloadoutput_type: One of text, csv, html, json, file, url, xlsx, videofiles: Array with at least one file objectobject_key: Required. The identifier returned by the prepare endpointfilename: Required. The display name for the filemime_type: Required. The MIME type of the file (e.g., video/mp4, application/pdf)Complete list of supported MIME types for callback files:
Always set output_type to the value you want the buyer to see (for example video, file, xlsx). The platform now preserves your original type even when ingesting files from secure storage.
max_bytes.object_key matches the one returned by prepare. The platform validates file size automatically after downloading the file.ok: true and an object_key.200.Using polling instead of callbacks? The same object_key fields work there too—just include them in your polling response. For the full schema and examples, see Polling (Integration guide).