Intake API
Programmatic registration of review work for embedded pipelines (P3-004).
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/intake/submit | Single-item submission |
POST | /v1/intake/batch | Multi-item submission (max batch size enforced server-side) |
GET | /v1/intake/submissions/{submission_id} | Poll submission + item statuses |
Schemas: OpenAPI integrator subset.
Request shape (single)
Required fields include filename, file_size, mime_type. Optional: module, tier, external_reference, item_metadata (size/depth limits apply).
POST /v1/intake/submit records intake metadata and creates submission/item rows. Use the portal upload / document APIs when binary content must land in encrypted storage — do not assume base64 body on this route.
Idempotency
Send an optional Idempotency-Key header (1–128 characters) on POST /v1/intake/submit and POST /v1/intake/batch (ADR-067).
| Retry | Result |
|---|---|
| Same key + same JSON body | Stored 201 is replayed. No second submission, audit event, or webhook. |
| Same key + different body | 409 IDEMPOTENCY_KEY_MISMATCH |
| Same key while the first call is still running | 409 IDEMPOTENCY_IN_PROGRESS — retry after a short wait |
| Empty or longer-than-128 key | 422 IDEMPOTENCY_KEY_INVALID |
| No header | Same as before this feature — a new submission every time |
Keys are scoped to your tenant + your user + the route (submit vs batch). They expire after 24 hours (API_IDEMPOTENCY_TTL_HOURS). Only successful 201 responses are remembered; a validation 422 is not stored, so you may reuse the same key after you fix the body.
Portal POST /v1/documents, batches, and pay do not honor this header yet.
Status polling
GET /v1/intake/submissions/{submission_id}
Authorization: Bearer …
Response includes submission aggregate status and per-item rows (document_id when linked).
Example
See scripts/integrator/curl-intake-submit.example.sh.
Auditing
Successful submits emit audit actions such as intake.submitted / intake.batch_submitted (tenant-scoped).