# Jobs

> How Parsings and Operations process a Document, and what they have in common.

A **Job** processes one [Document](https://docs.axelered.com/documents_guide). There are two families of Jobs:

* a &#x2A;*[Parsing](https://docs.axelered.com/parse)** turns the Document into a structured Parsed Document of pages and blocks, which you read as Markdown, text, HTML or JSON;
* an **Operation** runs a language model on the Document: [Summarization](https://docs.axelered.com/summarize), [Classification](https://docs.axelered.com/classify) or [Extraction](https://docs.axelered.com/extract).

Each kind is a resource of its own, with the same endpoints:

| Kind           | Resource           | Output                                         |
| :------------- | :----------------- | :--------------------------------------------- |
| Parsing        | `/parsings`        | The Parsed Document, at `/{parsing_id}/output` |
| Summarization  | `/summarizations`  | A title and a summary, in `output`             |
| Classification | `/classifications` | A category and its motivation, in `output`     |
| Extraction     | `/extractions`     | The fields of your JSON Schema, in `output`    |

<Mermaid
  chart="`
flowchart LR
  D[&#x22;Document&#x22;] --> P[&#x22;Parsing&#x22;]
  P --> R[&#x22;Parsed Document&#x22;]
  D --> S[&#x22;Summarization<br/><small>parses, then summarizes</small>&#x22;]
  D --> C[&#x22;Classification<br/><small>parses, then classifies</small>&#x22;]
  D --> E[&#x22;Extraction<br/><small>parses, then extracts</small>&#x22;]
`"
/>

Every Operation parses its Document itself, with the `parsing` settings of its own configuration: it never reuses a Parsing you submitted. To summarize and classify the same Document, submit one Summarization and one Classification: each runs, fails and is billed on its own.

***

## 🏗️ Configuration

The configuration of a Job is sent as JSON in the `config` form field. Every Job has a `perimeter`; the other fields depend on its kind.

| Field          | Jobs       | Default              | Description                                                                                      |
| :------------- | :--------- | :------------------- | :----------------------------------------------------------------------------------------------- |
| `perimeter`    | all        | `external`           | Where your data may go, for the Parsing and the language model. See [Perimeters](https://docs.axelered.com/config_guide). |
| `tier`         | Parsing    | `fast`               | The Parsing Tier: how the Document is read. See [Parse](https://docs.axelered.com/parse).                                 |
| `pages`        | Parsing    | all pages            | The pages to parse. See [Parse](https://docs.axelered.com/parse).                                                         |
| `parsing`      | Operations | `{ "tier": "fast" }` | How the Operation parses the Document: its Parsing Tier and `pages`, as for a Parsing.           |
| `tier`         | Operations | `fast`               | The Operation Tier: the language model. See [Operation Tiers](https://docs.axelered.com/config_guide#-operation-tiers).   |
| `instructions` | Operations | none                 | Extra instructions for the model.                                                                |

Each Operation adds its own fields: see [Summarize](https://docs.axelered.com/summarize), [Classify](https://docs.axelered.com/classify) and [Extract](https://docs.axelered.com/extract).

***

## 🔄 Lifecycle

A Job is `queued`, then `running`, then `done` or `failed`. A `failed` Job produced nothing and costs nothing.

The `wait` query parameter (up to 30 seconds) keeps the request open until the Job finishes: the response is `200` when it finished, `202` while it is still running. Read the Job again, with `wait`, until it finishes. For example, with a Summarization:

<Mermaid
  chart="`
sequenceDiagram
  participant C as Client
  participant API as Axelered
  C->>API: POST /summarizations?wait=30
  alt Finished within 30s
      API-->>C: 200 Summarization (done or failed)
  else Still running
      API-->>C: 202 Summarization (queued or running)
      loop Until finished
          C->>API: GET /summarizations/{summarization_id}?wait=30
      end
  end
`"
/>

A done Operation carries its Output in `output`: `value` holds what the model returned, `truncated: true` says the Document was longer than the Operation can read, and the model read only its start.

***

## 💳 Credits

| Job       | Credits                                                                                                                                    |
| :-------- | :----------------------------------------------------------------------------------------------------------------------------------------- |
| Parsing   | `accurate` Parsing of PDFs, images and presentations: one per page. Any other Parsing: one.                                                |
| Operation | Its Parsing, as above, plus one for a `fast` Operation or three for an `accurate` one ([Operation Tiers](https://docs.axelered.com/config_guide#-operation-tiers)). |

A Job is charged once it is `done`, and its cost is in its `credits`. When the workspace has no Credits left, new Jobs are rejected with `402 balance_exhausted`.

***

## 🛠️ Submit a Job

Every kind is submitted the same way. Pass exactly one of `file` (uploaded as a new Document) or `documentId` (a Document you already uploaded).

```bash
curl -X POST "https://api.axelered.com/v1/summarizations?wait=30" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "documentId={document_id}" \
  -F 'config={"length": "short", "parsing": {"tier": "accurate"}}'
```

Add `idempotency_key=<key>` to the query to make a retry safe: a key already used in the workspace for the same kind returns `409 idempotency_conflict`.

| Error                       | When                                                                                        |
| :-------------------------- | :------------------------------------------------------------------------------------------ |
| `400 unreadable_file`       | The file is corrupt and its pages cannot be read.                                           |
| `400 unsupported_format`    | The file type is not supported, or not with `accurate` Parsing.                             |
| `402 balance_exhausted`     | The workspace has no Credits left.                                                          |
| `403 perimeter_not_allowed` | The workspace only allows `local`. See [Compliance Guard](https://docs.axelered.com/config_guide#-compliance-guard). |
| `404`                       | The `documentId` does not exist.                                                            |
| `409 idempotency_conflict`  | The idempotency key was already used; the `Location` header is the Job that holds it.       |
| `413 too_many_pages`        | `accurate` Parsing would read more than 100 pages. See [Documents](https://docs.axelered.com/documents_guide).       |
| `422 invalid_output_schema` | The `outputSchema` of an [Extraction](https://docs.axelered.com/extract) is not a valid JSON Schema.                 |
| `503 perimeter_unavailable` | The Perimeter cannot run this Job. See [Perimeters](https://docs.axelered.com/config_guide#-availability).           |

All the codes and the error format are in [Errors](https://docs.axelered.com/errors).

### List, Read & Delete

Each resource has the same three endpoints, documented in the API reference of its kind:

* **List**: newest first, optionally for one Document with `?documentId=`. Lists leave out the `output` of Operations.
* **Read**: status, credits and, for a done Operation, its `output`, with optional `wait`.
* **Delete**: hide a Job. Its Document is kept.

Deleting a Document hides all its Jobs, and their files are removed with it.
