Skip to main content
Use the REST API alone when there is no browser in the flow: files arrive from your own upload pipeline, a batch process, email, or another system. Your server submits each file as a job with the ordered steps to run on it, then collects the result.
If a customer uploads the file in a page you control, prefer embedding the Element — you get the drop zone, progress, findings, and auto-fix UI for free, and only the verification happens server-side. This page is for flows with no widget at all.
Every request in this flow is server-to-server, authenticated with your secret key as a bearer token. Never call these endpoints from the browser.
1

Get the file to Filecheck

A job source can reference the file three ways:For fileRef, mint presigned upload credentials with POST /uploads:
The response contains a fileRef plus a presigned S3 form POST (upload.url and upload.fields). POST the file there as multipart/form-data within 300 seconds, then use the fileRef as your job source.
2

Submit the job

POST /jobs is the canonical submission: each entry in sources[] is one file plus the ordered steps[] to run on it. A common print flow checks the file, auto-fixes what it can, and re-checks:
Steps run sequentially per source, each feeding its output to the next; steps incompatible with the file’s detected type are recorded as skipped. Available step types include preflight, autofix, repreflight, validate, previews, optimize, convert, upscale, removebg, and deliver — see the API reference for each step’s parameters. A job accepts up to 50 sources; each source becomes its own task under the job. metaData (up to 4 KB) is echoed back on responses and webhook callbacks, so use it to carry your own correlation ids.For the common cases you can skip composing steps and call a sugar wrapper, which builds them for you:
3

Collect the result

Jobs are asynchronous by default — POST /jobs returns 201 immediately with the job id. Pick whichever result channel fits your flow:Wait synchronously. Set sync: true on the submission to hold the connection up to ~27 seconds. You get 200 with the completed job, or 202 with pending: true if it is still running (fall back to polling or the webhook). Good for small files in a request/response cycle. (POST /jobs/validate is the inverse: synchronous by default, async: true to detach.)Poll. Fetch the job until it reaches a terminal status (ready, partial, or rejected):
Webhook. Pass a per-job webhook on submission (as in the example above, with optional headers for authenticating the callback), or configure account-level webhooks in the admin to receive job.created / job.completed for every job. Either way, fetch the full job when the callback arrives rather than trusting the payload alone.
4

Read the outcome and download the output

?expand=runs returns a flattened per-file summary — one entry per source — with the verdict and download links:
outcome is pass, warn, or fail per file; how warnings and failures roll up into the job’s final status is controlled by the policy.onFail you submitted (reject, accept_with_warnings, or manual_review). When a step produced a fixed or converted file, hasOutput is true and downloadUrl is a short-lived link to it. Omit expand to get the full job object with per-task step detail instead.

See also

  • API overview — base URL, conventions, and the generated reference for every endpoint.
  • Webhooks — account-level event delivery and handling guidance.
  • Verify jobs — the server-side checklist before fulfilling an order.