ZIP Files
Upload a ZIP archive containing multiple documents in a single call. Each file inside the ZIP is extracted and processed as an independent document.
Each file inside the ZIP becomes a separate document — they can be of different types. Bundle a batch from an external system into one ZIP and send a single request. You can also combine a ZIP upload with the Classifier to detect each type automatically.
Step 1 — Upload the ZIP
Upload the ZIP exactly like any other file — same endpoint, same info field. Invofox detects the MIME type automatically.
The upload response does not include documentIds — Invofox doesn’t know how many files the ZIP contains until it’s extracted. Save the importId instead:
Any clientData you include in the info field is propagated to every document extracted from the ZIP — all of them share the exact same clientData.
Step 2 — Get the results
Retrieve the documentIds once processing is done. Webhooks are the recommended approach; you can also poll the import.
Option A · Webhooks (recommended for production)
A document.processed event fires for each file as it finishes, carrying the full extracted document in its data field — same payload format as Step 3 of Integrating Invofox.
Because you don’t know upfront how many files a ZIP contains, you can’t rely on counting document.processed events to know when the ZIP is fully done. Instead, listen for import.processed — this event fires once, after every file in the ZIP has been processed. Iterate data.files[] for the documentIds (the ZIP’s own entry has an empty documentIds — skip it).
Option B · Poll the import
Poll GET /v1/ingest/imports/{importId} until status is "processed". While processing, status is "processing" and the documents counter increases as each file is extracted — don’t rely on it until status is "processed". The response holds one entry for the ZIP itself (compressed: true, documentIds: []) plus one entry per extracted file. The real documentIds are on those child entries — iterate over all files[] and skip any with compressed: true.
Each extracted file keeps its original name inside the archive (files[].filename) — unlike the Splitter, which renames its outputs to split_n.pdf. Collect every documentId across the child entries.
Fetch each document
For each documentId, call GET /documents/{documentId} — same response format as the standard flow. Documents extracted from a ZIP carry import.fromZip: true and import.filename set to the file’s name inside the archive:
A file inside the ZIP can fail on its own (unsupported format, corrupt, or password-protected) while the import as a whole still reaches status: "processed" — so always check each child’s status/error. See Rejected files for how to handle the file.rejected webhook.