API reference
Confirm upload
Verify stored object metadata and queue the document for processing. Uploading bytes alone never starts processing. File inspection and final billing admission happen asynchronously before extraction.
On this page
POST/v1/documents/{document_id}/upload-complete
Path parameters
document_idstringRequired
The doc_… ID that create document returned.
Request body
None. The call inspects the stored object server-side; it never downloads or parses the invoice through the public API.
The SDK handles confirmation inside submit() and process(). The TypeScript example shows the complete SDK flow; use the cURL example for this individual HTTP operation. Calling wait() alone does not confirm an upload.
Responses
A confirmation replay. It returns the existing queued, processing or terminal document; no second processing run is created. Poll the document while it is pending, or handle its terminal result; do not upload again.
The uploaded file passed its checks and the document is queued. Processing runs in the background.
Both return the document resource.
Errors
Every error uses the typed error envelope.
| Error | Meaning | Retryable |
|---|---|---|
400 invalid_request | The request body, headers, query parameters or path did not validate. What to do | No |
401 invalid_api_key | The API key was not accepted. What to do | No |
402 billing_required | No active plan or allowance covers processing. A rejected upload-complete can be retried after you fix billing; a document that has already failed with this code cannot. What to do | No |
404 document_not_found | The document does not exist in this account or was deleted. Never treat this as a successful DELETE. What to do | No |
409 upload_not_complete | The file is not in storage. You may upload the complete file while the upload URL is still valid. What to do | No |
410 upload_expired | The upload window for this document is closed. This is more than an expired signed URL. What to do | No |
410 document_expired | The document passed its deadline: its retained result expired, or its upload window closed without a confirmed upload. It cannot be retrieved again. What to do | No |
413 document_too_large | The declared or uploaded file is larger than 20 MiB. What to do | No |
415 unsupported_content_type | The declared content type is not supported, or the uploaded file does not match it. What to do | No |
422 upload_size_mismatch | The uploaded file size differs from file_size_bytes. Create a new document with the correct file and byte count. What to do | No |
429 rate_limit_exceeded | Too many requests. Wait at least Retry-After, then retry a limited number of times. Create and upload-complete enforce rate limits today; the other operations reserve this response. What to do | Yes, after Retry-After |
500 internal_error | Something failed on our side. An HTTP 500 alone does not mean you may retry; check retryable and keep the request ID. What to do | No |
503 service_unavailable | The service is temporarily unavailable. Retry the same request a limited number of times when retryable is true. What to do | Yes, with backoff; honor Retry-After if sent |
402 billing_required- your plan or allowance ran out after the upload. The file is kept until its normal expiry, so you can upgrade and call upload-complete again without uploading it again.409 upload_not_complete- the file is not in storage. This is the only response that means you should upload it again.
When you are not sure the upload worked
If the file upload timed out or the connection dropped, call this endpoint before uploading again. A 202 or 200 means the file already arrived: do not upload it again.
The same applies when create document returns 200 awaiting_upload on a retry: the file may or may not be there, so call this endpoint first. A successful confirmation never returns awaiting_upload.
An uploaded file cannot be replaced. If it has the wrong size or type, create a new document instead.
The full recovery walkthrough