Skip to main content
The Ingest endpoints handle document uploads and status polling. Parsing runs asynchronously — upload returns a task_id immediately, which you then poll until ingestion completes.
Use an official SDK if you can — the Python and JavaScript SDKs wrap the direct-upload flow into a single client.ingest.file(...) / client.ingest.batch(...) call that works for any file size. The endpoint-level details below are only needed if you’re calling the REST API directly.

Upload a Document

The default upload flow streams your file bytes straight from your client to Polyvia’s storage backend, then asks our API to register and parse it. This is a three-step flow that works for any file size — there is no practical upper limit.

Step 1 — Get an upload URL

POST /api/v1/ingest/upload-url No request body.
string
required
Short-lived signed URL for the storage backend. Expires in ~1 hour and is single-use.

Step 2 — PUT the file to that URL

Stream the raw file bytes to the returned upload_url. Set Content-Type to the file’s MIME type.
Do not include your Polyvia Authorization: Bearer poly_<key> header on this request. The URL is already signed, and forwarding the key to a different origin would leak it unnecessarily.
Storage responds with the new object’s identifier:

Step 3 — Finalize the upload

POST /api/v1/ingest/finalize application/json
string
required
The storageId returned by storage in Step 2.
string
required
MIME type of the uploaded file.
string
Display name. Defaults to “Untitled” if omitted.
string
Assign the document to a group on creation.

Response

string
required
Unique identifier for the uploaded document
string
required
Ingestion task identifier — use this to poll for status
string
Initial status: always pending

Example


Upload Multiple Documents

For batches, run the direct-upload flow once per file. The official SDKs do this in client.ingest.batch(...) — each file is uploaded and finalized independently, so a failure on one file is isolated to that entry instead of failing the whole batch.

Quick Multipart Upload (small files)

These multipart endpoints proxy file bytes through the API server, which has a 4.5 MB total request-body limit. They exist as a one-call convenience for small uploads. For any file size, prefer the direct-upload flow above (or use an SDK, which does it for you).

POST /api/v1/ingest

multipart/form-data
file
required
The document to upload. See Supported File Formats below.
string
Display name in your workspace. Defaults to the filename.
string
Assign the document to a group on upload.
Returns the same {document_id, task_id, status} shape as /finalize.

POST /api/v1/ingest/batch

multipart/form-data. Same fields as /ingest but files is repeated per file and names is a comma-separated string aligned to files. Returns {results: [...], errors: [...] | null}.

Check Ingestion Status

Poll a parse task started by either upload flow.

Endpoint

GET /api/v1/ingest/{task_id}

Path Parameters

string
required
The task identifier returned by /ingest/finalize (or the legacy multipart endpoints)

Response

string
Task identifier
string
Document identifier
string
Processing status (see table below)
string | null
Error message if status is failed, otherwise null

Example

cURL

Supported File Formats

See Supported Formats for parser-by-parser details on what gets extracted from each file type.
Documents are typically processed within 1–2 minutes. Audio files take longer — roughly real-time playback for transcription. Poll the status endpoint every few seconds to check progress.