Ingest a zip archive or individual files
Requires Member. ONE endpoint, two intake paths chosen by Content-Type:
- application/zip / application/octet-stream — body is the raw zip bytes, max 10 MB compressed.
- multipart/form-data — 1..N individual text files in repeated files parts (each part's filename becomes the memory source). Total request body max 10 MB, max 200 files, max 5 MB per file.
Both paths run the same pipeline and return the same shape, and the STATUS CODE tells you whether the job in the body can still change:
- 200 — the job is terminal (complete or failed), counts are final, do not poll. Small jobs (up to one wave of write batches, 32 chunks) finish inside the request.
- 202 — the job is processing and is still running server-side. Counts are zero, Location names the job URL and Retry-After the poll interval; poll until status leaves processing.
- 413 — the upload chunks to more than 960 pieces, the per-job work ceiling. Refused before anything is written or billed, with the limit named in the message. Split the upload.
files_processed counts files whose EVERY chunk was confirmed stored, counted from write confirmations — a job that stored nothing reports 0. Files that were attempted is files_total - files_skipped.length.
Job-level rejections (200 + failed job): zip only — zip_bomb (50 MB declared uncompressed / 100x compression-ratio caps), too_many_entries (200 entries), invalid_zip; multipart only — too_many_files (more than 200 files parts) and no_usable_files (every uploaded file was skipped by the controls below).
Per-file violations are SKIPPED and reported in files_skipped (capped at 100 rows) while the rest of the job proceeds — identical controls on both paths: over 5 MB, nested archives (.zip/.tar/.gz/… are never recursed into, including when uploaded as one of several multipart files), hostile names (absolute paths, .. segments, backslashes, control chars, over 512 chars), extensions outside the text allowlist, and content that is not valid UTF-8. The compression-ratio and nested-archive-extraction controls are zip-only — multipart bodies are not compressed.
Chunks land as Kairos memories in ns, tagged ingest:{job_id} (plus tag_prefix when given), source set to the sanitized entry path or multipart filename. Free-plan workspaces are rejected up front when the estimated source tokens would exceed the plan inclusion.
Requires the ingest:write scope. Accepts all three lanes: a session JWT (bounded by the caller's role on this workspace) or an il_* machine credential whose own scope set, workspace set and validity window cover it — both ceilings apply and neither can raise the other, so a credential carrying ingest:write is still refused where the role does not permit it.
A credential with no scope record resolves to LEGACY_DEFAULT, which INCLUDES ingest:write — every key minted before scoping keeps working here.
Request
- Base URL: https://api.infolang.ai
- URL: https://api.infolang.ai/v2/workspaces/{id}/ingest
- Auth: one of:
- HTTP bearer
- HTTP bearer
- HTTP bearer
Path parameters
Query parameters
target namespace (default default)
extra tag applied to every chunk
Response
TERMINAL job — nothing left to poll. complete, or failed with a job-level rejection: zip_bomb, too_many_entries, invalid_zip (zip path), too_many_files, no_usable_files (multipart path), or upstream_error when the chunk writes failed
Changes
No recorded changes to this operation across all 1 revision of this API.