Convert large and scanned files in the queue

Send files up to 25 MB and 200 pages to /v1/convert/jobs. Poll the job or receive a signed webhook, then download Markdown or JSON.

Last updated

Limits 25 MB, 200 pages and about 2 minutes of conversion per file
Credits 10 per file, refunded if the job fails; polls and downloads cost nothing
API key Required, in the X-API-Key header

The queue converts files that the direct call cannot: up to 25 MB and 200 pages, scans included. It runs Docling with OCR and returns Markdown plus a JSON structure file.

Submit a file

curl -H "X-API-Key: $FLATMARK_API_KEY" \
  -F "file=@big-report.pdf;type=application/pdf" \
  -F "webhook_url=https://your-app.example.com/hooks/flatmark" \
  https://api.flatmark.dev/v1/convert/jobs
{
  "job_id": "...",
  "status": "queued",
  "webhook_secret": "...",
  "result_url": "/v1/convert/jobs/.../result",
  "poll_url": "/v1/jobs/..."
}

webhook_url is optional and must point to a public address. webhook_secret is returned only here, so store it with the job ID. A file over 25 MB is rejected (413) before it is stored.

Poll the job

curl -H "X-API-Key: $FLATMARK_API_KEY" https://api.flatmark.dev/v1/jobs/$JOB_ID

status moves from queued to running to succeeded or failed. A failed job states the reason in error, and its 10 credits go back to your balance.

Verify the webhook

When the job finishes, flatmark POSTs a JSON body with job_id, status, result and error to your URL. The header X-Appkit-Signature: sha256=<hex> holds an HMAC-SHA256 of the raw body, keyed with webhook_secret. Delivery is tried up to 3 times.

import hashlib
import hmac


def signature_ok(secret: str, raw_body: bytes, header: str) -> bool:
    digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest("sha256=" + digest, header)

Check the bytes you received before you parse them. The body does not contain the Markdown.

Subscribe to job events

Instead of polling, subscribe one endpoint to every job's outcome. Add it at /app/webhooks, or with the API:

curl -H "X-API-Key: $FLATMARK_API_KEY" -H "Content-Type: application/json" \
  -d '{"url": "https://your-app.example.com/hooks/flatmark", "event_types": ["job.completed", "job.failed"]}' \
  https://api.flatmark.dev/v1/webhooks

The response shows the signing secret once. Each event carries job_id, kind, status and finished_at, signed per Standard Webhooks. Verify it with any Standard Webhooks library.

Download the result

curl -H "X-API-Key: $FLATMARK_API_KEY" \
  "https://api.flatmark.dev/v1/convert/jobs/$JOB_ID/result?format=markdown" -o result.md

Jobs belong to your account, so any of its API keys can read them. Results are deleted 7 days after submission.

Next step

Sign in with a magic link and create the API key the queue needs.

FAQ

Should I poll or use a webhook?
Use a webhook if you have a public endpoint. Otherwise poll every few seconds. Polls cost nothing.
Why would a queued job fail?
The file has more than 200 pages, the conversion takes longer than about 2 minutes, or no text is found. The job's 10 credits are refunded.