file_…) wherever bytes are needed.
Small files go up in one request. Large files go up in resumable segments. Either way you get back a durable handle you can reference until you are done with it.
Uploads are not billed — storage is on us. Extract still charges per page.
Small files (≤ 10 MB)
POST /v1/files — send multipart/form-data with a file part, or JSON with base64 content.
file_too_large — use the chunked flow below.
Large files (> 10 MB, up to 100 MB)
Three steps, one handle throughout: initialize → append → finalize.1
Initialize
Declare the total size. You get a
file_… handle in the uploading state and the segment_size to chunk by (5 MB).2
Append each segment
Send each 5 MB segment with its zero-based
segment_index. The last segment may be smaller. Segments can go in any order and in parallel.3
Finalize
Assemble the segments and get the ready handle, with the whole-file
sha256.Resuming a dropped upload
append is idempotent per segment_index — re-sending an index overwrites it. If a client drops mid-upload, read the file’s status and re-send only the segments that did not land:
finalize refuses an incomplete upload with incomplete_upload, naming the gaps.
Using a file
Pass the handle where a product accepts one. Extract takes it asdocument.file_id instead of inline content — which lets you extract the same file against several schema types without re-uploading:
Downloading
GET /v1/files/{id}/content streams the raw bytes back, proxied through the API (supports Range). This is also how you retrieve a file an assistant produced.