---
title: "Create a conversion job"
method: POST
path: "/jobs"
tags: ["Jobs"]
---

# Create a conversion job

`POST /jobs`

## Request

- Base URL: `https://pdf2md.dev`
- URL: `https://pdf2md.dev/jobs`
- Auth: HTTP bearer

Accepts a PDF file (multipart) or a link to a PDF (JSON). Maximum file size — 10 MB.
Priority is assigned by the number of device runs per day for the selected converter (minimum 4).
Processing lasts up to 5 minutes; if exceeded, the job fails with an error. The result is stored for 1 hour after it is ready.

## Headers

- `Idempotency-Key` string
- `X-Timestamp` integer, required
- `X-Nonce` string, required
- `X-Body-SHA256` string, required
- `X-Signature` string, required

## Request body

- CreateJobFromUrlRequest
  - `url` string, uri, required: Direct link to a PDF
  - `file_name` string: File name for display (optional)
  - `converter_code` string, required: Converter code (MVP: pdf_to_md)
  - `ocr_lang` 'ru' | 'en' | 'ja' | 'es' | 'pt' | 'de' | 'fr': OCR language hint (EP-070, additive). Selects the OCR recognition model for scanned pages / forced OCR in BOTH engines (MinerU maps ja→japan and es/pt/de/fr→latin; docling builds a per-request EasyOCR list <lang>+en). Only affects OCR: PDFs with a digital text layer are extracted, not recognized, and ignore this hint. Absent → the engine's env default (current ru+en behavior). Unknown values are rejected with 400.

## Response `201`

Job queued

- JobResource
  - `job_id` string, uuid, required
  - `status` 'queued' | 'processing' | 'ready' | 'error' | 'canceled' | 'deleted', required: Job status
  - `converter_code` string, required
  - `status_since` string, date-time, required: Time of entry into the current status (UTC)
  - `priority` integer, required: A lower number — higher priority. v2 (EP-023, §7.7): a band scale, `min` is no longer 4 — the client treats the value as opaque (timers are computed from `status_since`/`ready_at`, not from priority).
  - `priority_assigned_at` string, date-time, required: When priority was assigned/lowered
  - `error_message` string, nullable
  - `error_code` string, nullable: Stable machine error code for a failed job (EP-031). Additive — absent on success and on older records. Clients localize by this code; the human error_message is a fallback.
  - `file_name` string, required
  - `output_size` integer, nullable: Markdown size (bytes), only for `ready`
  - `download_url` string, uri, nullable: Populated for `ready`
  - `pages` integer, nullable: Number of pages in the source PDF (EP-018). An additive field — absent on the old backend/old jobs; clients should ignore it if missing.
  - `truncated` boolean: `true` — the result is partial: conversion reached the soft time budget and a disclaimer was appended to the end of the Markdown (EP-018). Additive, backward-compatible: absence/`false` = full result.

## Other responses

- `400`: Invalid data (no file/URL, not a PDF, broken link)
- `401`: Invalid or expired device_token / request signature
- `403`: Device blocked
- `409`: Replay detected (nonce already used)
- `413`: File exceeds the 10 MB limit
- `429`: Device or IP limits exceeded

---

[API](https://skmtc.dev/pdf2md/apis/pdf-to-markdown-api-facade.md) · [All operations](https://skmtc.dev/pdf2md/apis/pdf-to-markdown-api-facade/llms.txt) · [OpenAPI document](https://skmtc.dev/pdf2md/apis/pdf-to-markdown-api-facade/revisions/4636782fb8b6?raw)
