# Jobs

Run one action or chain up to eight on your files, get the result by waiting, polling or webhook, and read the receipt.

A **job** runs steps on files: one action, or a chain where each step works on the last step's result.

## One action

Each action has a shortcut, `POST /v1/pdf/<action>`, which is a one-step job:

```bash
curl https://api.fynepdf.com/v1/pdf/ocr \
  -H "Authorization: Bearer $FYNEPDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"file_id":"file_01jc8x4m2k9q7r3t5vwy6z"}'
```

## A chain of steps

`POST /v1/jobs` takes the input files and up to eight steps:

```bash title="curl"
curl https://api.fynepdf.com/v1/jobs \
  -H "Authorization: Bearer $FYNEPDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": ["file_01jc8x4m2k9q7r3t5vwy6z", "file_01jc8x5n7p2s4u6w8y0a1b"],
    "steps": [
      {"action": "merge"},
      {"action": "compress", "params": {"target_size_bytes": 5000000}},
      {"action": "page_numbers", "params": {"position": "bottom-right"}}
    ],
    "wait": 30
  }'
```

```js title="Node"
const job = await fyne.jobs.create({
  inputs: ["file_01jc8x4m2k9q7r3t5vwy6z", "file_01jc8x5n7p2s4u6w8y0a1b"],
  steps: [
    { action: "merge" },
    { action: "compress", params: { target_size_bytes: 5_000_000 } },
    { action: "page_numbers", params: { position: "bottom-right" } },
  ],
  wait: 30,
});
```

```python title="Python"
job = fyne.jobs.create(
    inputs=["file_01jc8x4m2k9q7r3t5vwy6z", "file_01jc8x5n7p2s4u6w8y0a1b"],
    steps=[
        {"action": "merge"},
        {"action": "compress", "params": {"target_size_bytes": 5_000_000}},
        {"action": "page_numbers", "params": {"position": "bottom-right"}},
    ],
    wait=30,
)
```

Rules of a chain:

- Most actions take one file; `merge` and `image_to_pdf` take all of them.
- A step that makes something other than a PDF (Word, Excel, images in a ZIP) must be the last step.
- `GET /v1/actions` lists every action with its parameters and price, and each has a page in this menu.

## Getting the result

Pick one:

- **Wait in the call**: `wait` (0 to 60 seconds). A job that finishes in time answers `200`; otherwise `202`, and you carry on below. Shortcuts wait 30 seconds unless told otherwise; `POST /v1/jobs` answers at once unless you set `wait`.
- **Poll**: `GET /v1/jobs/{id}` until `status` is `succeeded`, `failed` or `canceled`. The `Location` header of a `202` points there.
- **Webhook**: give `webhook_url` and we call it when the job ends. See [Webhooks](https://fynepdf.com/developers/docs/webhooks).

A job is `queued` while it waits for a free slot and `running` once its first step starts; `started_at` is set then, so the receipt's time counts work, not waiting.

Results are named after the first input. When the result is the same type, the name says what was done: `report.pdf` compressed comes back as `report-compressed.pdf`, so it can be saved next to the original. A different type keeps the plain name (`report.docx`).

## The receipt

Every job has one: each step's status, pages and bytes before and after, time taken, credits, and step details (a compress step says whether it met its target; a redact step says how many matches it removed and that none can still be found).

```json
{
  "receipt": {
    "steps": [
      { "step": 1, "action": "merge", "status": "succeeded", "credits": 1, "pages_after": 22 },
      { "step": 2, "action": "compress", "status": "succeeded", "credits": 1, "bytes_before": 14200000, "bytes_after": 4800000, "target_met": true },
      { "step": 3, "action": "page_numbers", "status": "succeeded", "credits": 1, "pages_after": 22 }
    ],
    "credits": 3,
    "duration_ms": 9100
  }
}
```

## Price it first

`POST /v1/jobs/quote` takes the same body and answers with the credits it would cost, without running anything.

## When things go wrong

- A step that fails is never charged, and a job that fails or is canceled gives back everything it spent.
- `POST /v1/jobs/{id}/cancel` stops a job before its next step.
- `error` on a failed job says which step failed and why; see [Errors](https://fynepdf.com/developers/docs/errors).
- Send an `Idempotency-Key` header so a retried request never runs twice ([Keys and authentication](https://fynepdf.com/developers/docs/authentication#safe-retries)).


---

Open this page in a browser: https://fynepdf.com/developers/docs/jobs

More: [All tools](https://fynepdf.com/tools) · [AI agents](https://fynepdf.com/ai/agents) · [llms.txt](https://fynepdf.com/llms.txt) · [Sitemap](https://fynepdf.com/sitemap.xml)
