# POST /v1/decide

One text in, one decision out. Use a ready-made [template](https://layahost.com/docs/templates) or ask your own question, and get a flat response with the decision, its probabilities and the cost.

Endpoint

```http
POST https://layahost.com/v1/decide
```

For several questions about the same text in one request, use the Jev-compatible [POST /v1/systemone](https://layahost.com/docs/systemone) instead. For many texts at once, see [Batch requests](https://layahost.com/docs/batch).

## Request body

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `text` | string | Yes | The text to decide about. Up to 32,000 characters. |
| `template` | string | No | A template slug: `moderation`, `spam`, `support_intent`, `routing`, `sentiment`, `priority` or `language`. See [Decision templates](https://layahost.com/docs/templates). |
| `type` | string | Without `template` | `choice`, `yes_no` or `score`. Ignored when you use a template. |
| `question` | string | Without `template` | The question to answer, up to 2,000 characters. With a template, replaces the template's question. |
| `options` | array or object | For your own `choice` and `score` | The possible answers, either as a list of names (`["billing", "sales"]`) or as an object that maps each name to a short description (`{"billing": "invoices, payments"}`). `choice` takes 2 or more options, within the [option budget](#limits); `score` takes 2 to 10 levels, lowest first. Names can be numbers, such as `["1", "2", "3"]`. Descriptions can be up to 500 characters. With a template, replaces the template's options. Ignored for `yes_no`. |
| `lang` | string | No | A language hint such as `en` or `de`. With `laya-auto`, `en` sends the text to the English checkpoint and any other value to the multilingual one, instead of detecting the language. |
| `model` | string | No | `laya-auto` (default), `laya-english` or `laya-multilingual`. See [Models](https://layahost.com/docs/models). |
| `cache` | boolean | No | Default `true`. Set `false` to skip the response cache: the answer is computed fresh and not stored. |

## Example

A `choice` question with a short description for each option:

POST /v1/decide

```bash
curl https://layahost.com/v1/decide \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Can I get an invoice with my VAT number on it?",
    "type": "choice",
    "question": "Which team should answer this email?",
    "options": {
      "billing": "invoices, payments, refunds",
      "technical": "bugs, errors, API",
      "sales": "pricing, plans, quotes"
    }
  }'
```

POST /v1/decide

```javascript
const res = await fetch("https://layahost.com/v1/decide", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.LAYAHOST_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    text: "Can I get an invoice with my VAT number on it?",
    type: "choice",
    question: "Which team should answer this email?",
    options: {
      billing: "invoices, payments, refunds",
      technical: "bugs, errors, API",
      sales: "pricing, plans, quotes",
    },
  }),
});

if (!res.ok) throw new Error(`layahost ${res.status}: ${await res.text()}`);
const result = await res.json();
console.log(result.decision, result.probabilities);
```

POST /v1/decide

```python
import os
import requests

res = requests.post(
    "https://layahost.com/v1/decide",
    headers={"Authorization": f"Bearer {os.environ['LAYAHOST_API_KEY']}"},
    json={
        "text": "Can I get an invoice with my VAT number on it?",
        "type": "choice",
        "question": "Which team should answer this email?",
        "options": {
            "billing": "invoices, payments, refunds",
            "technical": "bugs, errors, API",
            "sales": "pricing, plans, quotes",
        },
    },
    timeout=10,
)
res.raise_for_status()
result = res.json()
print(result["decision"], result["probabilities"])
```

POST /v1/decide

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://layahost.com']);

$res = $client->post('/v1/decide', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('LAYAHOST_API_KEY')],
    'json' => [
        'text' => 'Can I get an invoice with my VAT number on it?',
        'type' => 'choice',
        'question' => 'Which team should answer this email?',
        'options' => [
            'billing' => 'invoices, payments, refunds',
            'technical' => 'bugs, errors, API',
            'sales' => 'pricing, plans, quotes',
        ],
    ],
]);

$result = json_decode($res->getBody(), true);
echo $result['decision'], PHP_EOL;
```

Response · 200

```json
{
  "decision": "billing",
  "confidence": 0.6506,
  "probabilities": {
    "billing": 0.9036,
    "technical": 0.0506,
    "sales": 0.0458
  },
  "template": null,
  "model": "laya-english",
  "usage": {
    "decisions": 1,
    "input_tokens": 52,
    "cost_micros": 5,
    "cost_usd": 5.0e-6
  },
  "latency_ms": 169.63,
  "request_id": "req_iazyijj7zo5nmmoxzhnivu9d"
}
```

## Response

| Field | Type | Description |
| --- | --- | --- |
| `decision` | string or boolean | The answer: the chosen option for `choice`, `true` or `false` for `yes_no`, and the level name for `score`. |
| `confidence` | number | How sure the model is, from 0 to 1. See [Reading confidence](#confidence). |
| `probabilities` | object | `choice` and `score` only. The probability of each option, keyed by option name. Sorted most likely first for `choice`, in level order for `score`. |
| `probability` | number | `yes_no` only. The probability that the answer is yes. `decision` is `true` when it is 0.5 or more. |
| `score` | number | `score` only. The expected level on a scale where 0 is the first level and *n*−1 the last. |
| `template` | string or null | The template you used, or `null`. |
| `model` | string | The model that answered: `laya-english` or `laya-multilingual`. The `language` template reports `lingua`, its dedicated language detector. |
| `usage.decisions` | integer | Decisions billed. Always `1` on this endpoint. |
| `usage.input_tokens` | integer | Tokens the model read (text plus question and options). |
| `usage.cost_micros` | integer | What the request cost, in millionths of a US dollar: `5` is $0.000005. Use this for exact accounting. |
| `usage.cost_usd` | number | The same cost in US dollars. A JSON number, which may be written in exponent form: `5.0e-6` is $0.000005. |
| `latency_ms` | number | Server-side processing time in milliseconds. |
| `request_id` | string | Unique ID of the request, also sent in the `x-request-id` and `x-typesafe-request-id` headers and shown in [Logs](https://layahost.com/logs). |

## Use a template

Templates bundle a tested question and options. Send only the text and the template slug. This one is a `score` template, so the response also has `score`:

POST /v1/decide

```bash
curl https://layahost.com/v1/decide \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Our whole checkout is down and we are losing orders right now!",
    "template": "priority"
  }'
```

Response · 200

```json
{
  "decision": "urgent",
  "score": 2.9086,
  "confidence": 0.8195,
  "probabilities": {
    "low": 0.0133,
    "normal": 0.0154,
    "high": 0.0207,
    "urgent": 0.9506
  },
  "template": "priority",
  "model": "laya-english",
  "usage": {
    "decisions": 1,
    "input_tokens": 46,
    "cost_micros": 5,
    "cost_usd": 5.0e-6
  },
  "latency_ms": 101.57,
  "request_id": "req_fhmwim3yoqgdfdxf4mzsfp7l"
}
```

See [Decision templates](https://layahost.com/docs/templates) for the full list.

## Ask a yes/no question

Set `type` to `yes_no`. No options are needed. The response has `probability` instead of `probabilities`:

POST /v1/decide

```bash
curl https://layahost.com/v1/decide \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The delivery was two weeks late and nobody answered my emails.",
    "type": "yes_no",
    "question": "Is the customer complaining?"
  }'
```

Response · 200

```json
{
  "decision": true,
  "probability": 0.8481,
  "confidence": 0.8481,
  "template": null,
  "model": "laya-english",
  "usage": {
    "decisions": 1,
    "input_tokens": 43,
    "cost_micros": 5,
    "cost_usd": 5.0e-6
  },
  "latency_ms": 96.41,
  "request_id": "req_7oymodjner418isoiy49zsjs"
}
```

When accuracy matters, a `choice` question with two described options is often more reliable than a bare yes/no question. Try both on your data.

## Score on a scale

Set `type` to `score` and list the levels from lowest to highest:

POST /v1/decide

```bash
curl https://layahost.com/v1/decide \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The delivery was two weeks late and nobody answered my emails.",
    "type": "score",
    "question": "How angry is the customer?",
    "options": ["calm", "annoyed", "angry", "furious"]
  }'
```

Response · 200

```json
{
  "decision": "angry",
  "score": 1.5788,
  "confidence": 0.2046,
  "probabilities": {
    "calm": 0.0319,
    "annoyed": 0.5244,
    "angry": 0.2768,
    "furious": 0.1669
  },
  "template": null,
  "model": "laya-english",
  "usage": {
    "decisions": 1,
    "input_tokens": 45,
    "cost_micros": 5,
    "cost_usd": 5.0e-6
  },
  "latency_ms": 97.47,
  "request_id": "req_7hwhzpjgkpibhof91s7x7wmc"
}
```

`score` is the expected level: the sum of each level's position (0 for `calm` up to 3 for `furious`) times its probability. `decision` is the level nearest to it. That is not always the single most likely level: here `annoyed` has the highest probability, but the expected score of 1.58 is closest to level 2, `angry`. If you need the most likely level, take the largest value in `probabilities`.

Levels can be named with numbers, for a star rating for example. `score` still counts positions from 0, so a score of 1.31 is nearest the second level, `"2"`:

POST /v1/decide

```bash
curl https://layahost.com/v1/decide \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "The product is fine but shipping took forever.",
    "type": "score",
    "question": "Rate the review from 1 to 5 stars.",
    "options": ["1", "2", "3", "4", "5"]
  }'
```

Response · 200

```json
{
  "decision": "2",
  "score": 1.3059,
  "confidence": 0.3685,
  "probabilities": {
    "1": 0.0701,
    "2": 0.679,
    "3": 0.1651,
    "4": 0.0466,
    "5": 0.0392
  },
  "template": null,
  "model": "laya-english",
  "usage": {
    "decisions": 1,
    "input_tokens": 50,
    "cost_micros": 5,
    "cost_usd": 5.0e-6
  },
  "latency_ms": 120.5,
  "request_id": "req_uzivv1hv24gdcyf2bidnyilj"
}
```

Send numeric names as strings. JSON numbers such as `[1, 2, 3]` are not accepted for `score` levels.

## Override a template

With a template, `question` and `options` replace the template's own. This is how you route to your own teams with the `routing` template:

POST /v1/decide

```bash
curl https://layahost.com/v1/decide \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My order arrived broken, I want my money back.",
    "template": "routing",
    "options": {
      "logistics": "shipping, delivery, damaged parcels",
      "finance": "refunds, invoices, payments",
      "product": "product questions and feedback"
    }
  }'
```

Response · 200

```json
{
  "decision": "finance",
  "confidence": 0.108,
  "probabilities": {
    "finance": 0.568,
    "logistics": 0.243,
    "product": 0.189
  },
  "template": "routing",
  "model": "laya-english",
  "usage": {
    "decisions": 1,
    "input_tokens": 52,
    "cost_micros": 5,
    "cost_usd": 5.0e-6
  },
  "latency_ms": 96.03,
  "request_id": "req_rzgml9eicffev62s1ogyfgpm"
}
```

The message fits two teams, and the low `confidence` says so. That is a good case to send to a person.

## Reading confidence

`confidence` runs from 0 to 1, but it is computed differently per question type:

- **`choice` and `score`**: 1 minus the normalised entropy of `probabilities`. It is 0 when every option is equally likely and 1 when one option has all of the probability. It is usually well below the top probability: 0.108 for a 0.568 favourite in the example above.
- **`yes_no`**: the larger of `probability` and 1 − `probability`, so it ranges from 0.5 to 1.
- **`language` template**: the probability of the detected language.

Choose a threshold per question on your own data. A common pattern is to act automatically above the threshold and send everything else to a person.

## Limits

| Field | Limit |
| --- | --- |
| `text` | 32,000 characters |
| `question` | 2,000 characters |
| `options` for `choice` | At least 2. All option names and descriptions of one question must fit in the model's option budget of 192 tokens, roughly 100 to 150 short options. Longer lists get `422`. |
| `options` for `score` | 2 to 10 levels |
| Each option description | 500 characters |

Identical requests may be answered from a short-lived cache unless you send `"cache": false`. The answer is the same and is billed as usual. See [Data & privacy](https://layahost.com/docs/data).

## Errors

An invalid body gets `422` with one entry per problem. It is not billed. Here the request had neither a `template` nor a `type` and `question`:

Response · 422

```json
{
  "detail": [
    {
      "loc": ["body", "type"],
      "msg": "The type field is required when template is not present.",
      "type": "value_error"
    },
    {
      "loc": ["body", "question"],
      "msg": "The question field is required when template is not present.",
      "type": "value_error"
    }
  ]
}
```

A `choice` or `score` question without `options`:

Response · 422

```json
{
  "detail": [
    {
      "loc": ["body", "options"],
      "msg": "The options field is required.",
      "type": "value_error"
    }
  ]
}
```

A `score` question with fewer than 2 or more than 10 levels:

Response · 422

```json
{
  "detail": [
    {
      "loc": ["body", "options"],
      "msg": "A score needs 2 to 10 levels.",
      "type": "value_error"
    }
  ]
}
```

Options that don't fit the option budget get `422` on `["body", "options"]` with a message that says so. See [Errors](https://layahost.com/docs/errors) for authentication, balance, rate-limit and capacity errors.
