Docs/API reference/Submit a job
Reference

Submit a job

Create jobs by posting one or more files to a pipeline. Each file becomes its own job; processing is asynchronous by default, and the response returns as soon as the job is queued.

Request ​

POST/v1/jobsRequires jobs:write

Send multipart/form-data. Every parameter is a form field; the text parameters are also accepted in the query string.

ParameterTypeDescription
files (required)fileThe document. Repeat the field to submit several files — each becomes a separate job. PDF, DOCX, PNG, JPEG, TIFF, BMP, GIF or WebP, up to 100 MB. A pipeline can accept a narrower set.
pipeline_idstringThe pipeline to run. See Pipeline selection.
pipeline_versionintegerRun a specific version of the pipeline, draft or published. Defaults to the latest published version.
schema_idstringThe extraction schema to use. When omitted, the pipeline's catch-all routing rule decides.
prioritystringstandard (default) or high.
client_reference_idstringYour own reference. Stored on the job and echoed back; not used to detect duplicates.
environmentstringproduction or test — which Jobs tab the job appears on. When omitted, the job is tagged production. See Authentication.
modestringasync (default) or sync. Any other value is treated as async.
bash
curl -X POST https://api.us.idpforge.cloud/v1/jobs \
  -H "X-API-Key: $IDP_API_KEY" \
  -F "files=@Globex-INV-4471.pdf" \
  -F "pipeline_id=$PIPELINE_ID" \
  -F "client_reference_id=ap-inbox-4471"

Response ​

An async submission returns 202 Accepted with an array holding one object per uploaded file, in upload order.

FieldDescription
job_idThe new job's id.
statusqueued for an async submission; processing for a sync job that is still running (see below).
execution_modeasync, or sync for a sync job that is still running.
status_urlAbsolute URL of the job. GET it to poll status.
result_urlThe same URL with include=result.
degradation_reasonSet when you asked for mode=sync but got this object back instead of a finished job. sync_budget_exceeded means the job took longer than the sync window and is still running — poll status_url.
submitted_atWhen the job was accepted.
client_reference_idPresent when you sent one.

A sync submission waits for each job to finish and returns 200 OK with an array of full job objects — the shape GET /v1/jobs/{job_id} returns with include=stages,result.

When a sync job takes too long ​

A sync request waits about 50 seconds in total, across all of its files. If processing runs longer, you get 202 Accepted instead of 200, and the job keeps running. Each entry in the array is then either a finished job or an accepted job whose status is processing and whose degradation_reason is sync_budget_exceeded — poll its status_url until it finishes. Files that hadn't started when the window closed are queued as async jobs with the same degradation_reason.

Files in a multi-file request are processed in order. If a later file is rejected, the jobs already created for earlier files stand, and the response is the error.

json
[
  {
    "job_id": "01a08dcc-a671-7a63-a2e2-dec7c6ecbb38",
    "status": "queued",
    "execution_mode": "async",
    "status_url": "https://api.us.idpforge.cloud/v1/jobs/01a08dcc-a671-7a63-a2e2-dec7c6ecbb38",
    "result_url": "https://api.us.idpforge.cloud/v1/jobs/01a08dcc-a671-7a63-a2e2-dec7c6ecbb38?include=result",
    "submitted_at": "2026-09-11T00:09:55.315027355Z",
    "client_reference_id": "ap-inbox-4471"
  }
]
json
[
  {
    "job_id": "01a08dcc-a671-7a63-a2e2-dec7c6ecbb38",
    "status": "processing",
    "execution_mode": "sync",
    "status_url": "https://api.us.idpforge.cloud/v1/jobs/01a08dcc-a671-7a63-a2e2-dec7c6ecbb38",
    "result_url": "https://api.us.idpforge.cloud/v1/jobs/01a08dcc-a671-7a63-a2e2-dec7c6ecbb38?include=result",
    "submitted_at": "2026-10-07T10:00:00Z",
    "degradation_reason": "sync_budget_exceeded"
  }
]

Pipeline selection ​

The pipeline is chosen in this order:

  1. pipeline_id on the request — it always wins, including over the key's own pipeline.
  2. The pipeline the key is bound to. A key restricted to exactly one pipeline counts as bound to it.
  3. The workspace's default pipeline, and failing that a platform-provided parse pipeline.

Pass pipeline_id unless the key is bound to a single pipeline. In Studio, the API endpoint card on a pipeline's Versions tab shows its pipeline_id.

Errors ​

StatuserrorMeaning
400MISSING_PARTNo files field — for example, the file was sent as file.
400MISSING_FILEA files part was empty.
400PIPELINE_NOT_PUBLISHEDThe pipeline has no published version and no pipeline_version was given.
402PAYMENT_REQUIREDNot enough credits, or the job would exceed the workspace's spending cap. No job is created.
404VERSION_NOT_FOUNDThe requested pipeline_version does not exist.
413FILE_TOO_LARGEThe upload exceeds the 100 MB limit.
422UNSUPPORTED_FILE_TYPEThe file type is not accepted by the platform or by this pipeline.
422FILE_TOO_LARGEThe file exceeds this pipeline's size limit.

Credits ​

Submitting a job reserves credits before it is queued. If the balance is too low, the submission is rejected with 402 Payment Required and no job is created. The reservation settles to what the job actually used. Jobs tagged test reserve and consume credits exactly like production jobs. See Credits.

Job status ​

GET/v1/jobs/{job_id}Requires jobs:read

include adds optional blocks, comma-separated:

ValueAdds
stagesstages — per-stage progress, timings and credits.
resultresult — the job's output, returned only when status is completed.

A job moves through these statuses:

StatusMeaning
queuedAccepted and waiting to start.
preprocessingThe file is being normalised.
processingPipeline stages are running.
awaiting_reviewPaused for human review.
completedEvery stage finished. include=result returns the output.
completed_with_errorsFinished, but at least one stage failed. error names the first failing stage.
failedAn unrecoverable error stopped the job. error carries code, message and stage.
timed_outA synchronous job exceeded its timeout.
cancelledCancelled with POST /v1/jobs/{job_id}/cancel, which requires jobs:cancel.
blockedA failure that needs an operator parked the job. Not final — an operator fix re-runs it.
partialSome documents moved on while others are held for an operator. Not final.

An unknown id returns 404 with the code job_not_found. A well-formed id for a job that has aged out of retention returns job_expired.

json
{
  "job_id": "0191f3a2-7c4e-7b1d-9a55-3e0c8f2d6b41",
  "status": "completed",
  "api_type": "extract",
  "execution_mode": "async",
  "priority": "standard",
  "input": {
    "file_name": "Globex-INV-4471.pdf",
    "mime_type": "application/pdf",
    "page_count": 1
  },
  "created_at": "2026-09-11T06:12:44.318Z",
  "completed_at": "2026-09-11T06:13:58.402Z",
  "total_time_taken_ms": 74084,
  "client_reference_id": "ap-inbox-4471"
}

Retention ​

Jobs, their results and their documents are retained for 24 hours after submission. After that a job ages out: its result and documents are deleted, and GET /v1/jobs/{job_id} returns job_expired. Read or deliver what you need within that window, or subscribe to a webhook so the result reaches you as soon as it is ready.

Was this page helpful?
Last updated 7 Oct 2026