# Models

> Small models, each trained for one job inside a product — a chat's title, a line of preview in an inbox. Your code calls them over HTTP with a key, and they are billed by the token.

A general model can do these jobs if you write it a prompt. Ours are trained to do only them: a 2B model that writes titles and previews answers in a few hundred milliseconds, for a tenth of a dollar per million tokens it reads.

| Model | What it does | Price |
| --- | --- | --- |
| [Rubric](https://docs.divergentlabs.xyz/models/rubric.md) | a chat's title in 2 to 7 words, and a one-line preview of an email, message, ticket, issue, event, doc or agent action | $0.10 per million input tokens, output free |

## Asked with data, not a prompt

Each model was trained on one rendering of its input, so it is not sent a prompt. It is sent the thing itself, as JSON: the chat for a title, the email for a preview. We render that exactly as the model was trained on, ask it, and check the line that comes back before it reaches you. A line that fails the check is replaced with one built from the input, and the answer says so with `fallback: true`, so a line that is too long, quoted, or not English never reaches your list.

## Calling one

Every model has its own base URL:

```text
https://api.divergentlabs.xyz/api/inference/<model>/v1
```

A request carries an API key as a bearer token, and the key needs the `inference:invoke` scope. Make one under **Settings** in the dashboard.

```bash
curl https://api.divergentlabs.xyz/api/inference/rubric/v1/titles \
  -H "Authorization: Bearer $DIVERGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "why does my docker container exit immediately?"}]}'
```

To try one before writing code, use **Playground** in the dashboard. The curl under the form changes as you edit it, so what works there can be pasted into a terminal.

## What it costs

Each model is priced per million tokens, and each answer carries the `usage` the model reported. Nothing is charged per request: the meter adds up an org's tokens for each model and each UTC day, prices the day, and posts what has not been charged yet, so a day rounds up to a cent once rather than on every request.

A request needs credit. An org at zero gets a 402 before the model is asked. The charges show on the dashboard's Billing page by model, and each request shows under **Endpoints → Requests**, with the key that made it and how long the model took.

## When something is wrong

Errors have one shape across every model, with `code` to branch on and `message` for a person to read:

```json
{ "error": { "code": "invalid_request", "type": "invalid_request_error", "message": "item.tool: required, as a string", "param": "item.tool" } }
```

Each model's page lists the codes it answers with. A 502 means the model did not answer, and nothing was charged for it.
