---
title: "TypeSafe Decisions"
subtitle: "Get typed answers about a state with span-02."
---

Decisions are served by Respan's own models. A decision is a typed answer, not free text: you send a `state` (text or any JSON) and a set of `questions`, each a `choice`, `noul` (yes/no probability), `score` or `number`, and span-02 returns one answer per question with probabilities and a confidence. Use it where you would otherwise prompt a chat model and parse its reply: routing tickets, flagging intent, grading severity.

**Pick a model:** filter by output type `decisions` on the [model catalog](https://www.respan.ai/models), or read [Span-02](/docs/documentation/span-02/quickstart) and [Models](/docs/ai-gateway/models/overview).

## Quickstart

<Tabs>
<Tab title="cURL">
```bash
curl https://gateway.respan.ai/api/v1/systemone \
  -H "Authorization: Bearer $RESPAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "span-02",
    "state": "My package arrived damaged. I want a refund now.",
    "questions": {
      "wants_refund": { "type": "noul", "instructions": "Does the customer ask for a refund?" },
      "department": {
        "type": "choice",
        "instructions": "Which team should handle this ticket?",
        "criteria": {
          "returns": "Exchanges, wrong or damaged items",
          "billing": "Charges, invoices, payment problems"
        }
      }
    }
  }'
```
</Tab>
<Tab title="Python">
```python
import os
import requests

response = requests.post(
    "https://gateway.respan.ai/api/v1/systemone",
    headers={"Authorization": f"Bearer {os.environ['RESPAN_API_KEY']}"},
    json={
        "model": "span-02",
        "state": "My package arrived damaged. I want a refund now.",
        "questions": {
            "wants_refund": {"type": "noul", "instructions": "Does the customer ask for a refund?"},
            "department": {
                "type": "choice",
                "instructions": "Which team should handle this ticket?",
                "criteria": {
                    "returns": "Exchanges, wrong or damaged items",
                    "billing": "Charges, invoices, payment problems",
                },
            },
        },
    },
)
print(response.json()["answers"])
```
</Tab>
<Tab title="TypeScript">
```typescript
const response = await fetch("https://gateway.respan.ai/api/v1/systemone", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RESPAN_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "span-02",
    state: "My package arrived damaged. I want a refund now.",
    questions: {
      wants_refund: { type: "noul", instructions: "Does the customer ask for a refund?" },
      department: {
        type: "choice",
        instructions: "Which team should handle this ticket?",
        criteria: {
          returns: "Exchanges, wrong or damaged items",
          billing: "Charges, invoices, payment problems",
        },
      },
    },
  }),
});
console.log((await response.json()).answers);
```
</Tab>
</Tabs>

The response is `{"model", "answers", "usage"}`, with answers under the same ids as your questions.

{/* REVIEW: span-02 docs use POST /api/v1/decisions on api.respan.ai; gateway-next serves /api/v1/systemone. Decide which path is canonical and align both. */}

## Options

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `model` | string | required | A decisions model, such as `span-02`. |
| `state` | string or object | required | What the questions are about: text or any JSON. |
| `questions` | object | required | Questions keyed by your own ids. Each has a `type` (`choice`, `noul`, `score`, `number`), `instructions`, and for `choice` the `criteria` to pick from. |
| `reasoning` | object | no deadline | A thinking deadline, such as `{"mode": "on", "budget_ms": 300}`. See [anytime reasoning](/docs/documentation/span-02/concept#anytime-reasoning). |
| `stream` | boolean | not taken | A decision is answered whole; `stream` is refused with `400`. |

[Question types](/docs/documentation/span-02/question-types) shows a full request and response for each type.

## Endpoints

| Endpoint | Notes |
| --- | --- |
| `POST /api/v1/systemone` | The decisions endpoint. |
| `POST /api/systemone` | Same contract. |
| `POST /api/alpha/decisions` | Same contract, for clients of the alpha endpoint. |

The body is the System One format, so a System One client works by changing its base URL.

## Providers

The model's catalog entry decides who answers: TypeSafe and OpenRouter at their System One endpoints, and EmpirioLabs at its decisions endpoint. You call every one the same way.

{/* REVIEW: the span-01 Scores section (POST /api/v1/scores) was removed because gateway-next doesn't serve it; restore it when it does. */}

## Respan parameters

Respan parameters such as `customer_identifier`, `metadata` and `thread_identifier` go in the body next to `state` and `questions`, or in the `X-Data-Respan-Params` header. Tag a decision with the same `thread_identifier` as the chat that triggered it to see both together. See [Respan parameters](/docs/ai-gateway/customers/respan-params).

Decisions are not redacted, so an organization with [PII redaction](/docs/ai-gateway/features/pii-redaction) on is refused.

## Pricing and logs

- Each decision is one trace with one `chat` row (`io_format` typesafe): the questions as the system turn, the state as the user turn, and the answers as the reply.
- It is priced on the model's catalog entry from the tokens the answer reports. See the [model catalog](https://www.respan.ai/models) for each model's price.
- Your key's TPM limit applies, with no completion tokens reserved.

## Next steps

- [span-02 quickstart](/docs/documentation/span-02/quickstart): question types and reasoning.
- [Span-02](/docs/documentation/span-02/quickstart): Respan's own model.
