Skip to Content
ConceptsUpload sessions

Upload sessions

An upload session is the container you put files into before kicking off OCR. It’s the gate that catches unreadable or oversize files before they spend OCR credits, and the boundary that lets you batch related documents together (think: “the supplier invoices that arrived this morning”).

The three-entity data model

UploadSession ← 1:1 → Request ← 1:N → Document (batch slot) (job) (each page)
EntityPurposeLifetime
UploadSessionHolds uploaded files; gates per-file size + count limitsHours (default 24, configurable via UPLOAD_SESSION_TTL)
RequestA single OCR job — references one session + document typeDays (kept in DB for audit; original files purged on TTL)
DocumentOne page of a request, with its own confidence + extracted fieldsDays (retention follows the parent request)

Lifecycle

  1. POST /api/v1/ocr/upload-sessions → server mints a session_id with the merchant’s limit_file (default 20) and limit_size_mb (default 10).
  2. POST /api/v1/ocr/upload-sessions/{session_id}/files → upload one or more files (multipart). Server rejects anything past the per-merchant limits; nothing reaches the OCR engine yet.
  3. POST /api/v1/ocr/requests → reference the session_id, pick a document_type (or a custom schema), and the request enters the queue. Each file becomes a Document row.
  4. Webhook fires per document as extraction completes.

Client-side validation against limit_file + limit_size_mb is strongly recommended before step 2 — file rejections at upload time are cheap (HTTP 200 with a business-error code), but they slow your operators down. Surface the limits in your UI.

Session expiry

Sessions expire after UPLOAD_SESSION_TTL (default 24 hours). After expiry:

  • Files in the session staging bucket are purged
  • Any new request referencing the session_id fails with UPLOAD_SESSION_EXPIRED
  • Existing requests already submitted continue normally; the session only gates the upload + request-creation steps

You can’t extend a session — create a new one and re-upload.

Errors at this layer

Business-level errors arrive as HTTP 200 with a JSON error_code (not HTTP 4xx) so retries don’t confuse network-layer failures with application-layer ones:

error_codeMeaning
UPLOAD_SESSION_NOT_FOUNDBad session_id — typo or expired
UPLOAD_SESSION_EXPIREDTTL elapsed
UPLOAD_SESSION_MISMATCHSession belongs to a different merchant
FILE_TOO_LARGEOver per-file limit_size_mb
FILE_COUNT_EXCEEDEDPast limit_file in this session

See API errors for the full code table.