> ## Documentation Index
> Fetch the complete documentation index at: https://docs.60db.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Evaluate

> Wire-compatible twin of Evaluate, for callers that already speak the upstream model service's own contract

Byte-for-byte wire-compatible twin of [Evaluate](/api-reference/judge/evaluate) — same auth, same billing, same request body — for a caller that already speaks the upstream model service's own contract directly. This path matches the upstream's own `POST /v1/systemone` exactly, so that caller needs no custom integration to point at `api.60db.ai`.

Three differences from `POST /judge/evaluate`:

* The response is the **raw upstream answer** — no `{success,data}` envelope, and no `id` / `saved` / `credits_charged` fields.
* Errors are `{error:{code,message}}`, not `{success:false,message,code}`.
* A run through this route is **never saved** to Judge history — there's no `save`, `label`, or `rubric_id` on the wire, and nothing you send changes that.

Billing still happens exactly as on `/judge/evaluate` — the same wallet, the same refund-on-failure — it just has nowhere to go in the upstream's own envelope, so it rides the `x-credit-charged` / `x-credit-balance` / `x-billing-tx` response headers instead of the body.

<Info>
  Billed per input token, same rate as Evaluate. See [Judge pricing](/api-reference/judge/pricing).
</Info>

## Request

### Headers

<ParamField header="Authorization" type="string" required>
  Bearer token — **your standard 60db API key** (`sk_…`), or a user JWT. The same credential as every other Judge route.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  application/json
</ParamField>

### Body

Identical to [Evaluate](/api-reference/judge/evaluate#body), minus the 60db-local fields that don't exist on the upstream's own wire format:

<ParamField body="state" type="string | object | array" required>
  The content every question is asked about. Top-level numbers, booleans and `null` are rejected.
</ParamField>

<ParamField body="questions" type="object" required>
  Map of **answer key** → question, 1–32 entries — `choice`, `score` or `noul`. See [Evaluate → Body](/api-reference/judge/evaluate#body) for the full shape of each type.
</ParamField>

<ParamField body="model" type="string" default="jev-latest">
  Model name. Fetch the valid list from [List models](/api-reference/judge/models).
</ParamField>

<Note>
  No `rubric_id`, `save`, or `label` fields — those are 60db-local conveniences with no place in the upstream contract. Use [Evaluate](/api-reference/judge/evaluate) if you need a saved rubric or run history.
</Note>

## Response

The raw upstream object — no envelope:

<ResponseField name="model" type="string">
  The resolved model id, e.g. `60db-decision-model-v1`.
</ResponseField>

<ResponseField name="answers" type="object">
  One answer per question, under the same key you supplied. Same shape as [Evaluate's `data.answers`](/api-reference/judge/evaluate#response).
</ResponseField>

<ResponseField name="usage" type="object">
  `input_tokens` and `output_tokens` (snake\_case, as the upstream reports them). `output_tokens` can be non-zero — billing is input-only regardless.
</ResponseField>

<ResponseField name="metadata" type="object">
  Includes `escalated_questions` — how many answers the service refined when confidence was low. The same model answers every question; there is no separate second-stage model.
</ResponseField>

## Errors

| Status | Meaning |
| - | - |
| `400` | Invalid rubric — the message names the offending question. Also returned when the request exceeds 512 KiB or the 200,000-token context. |
| `402` | Insufficient credits. |
| `403` | Your role cannot run the judge, or an API key lacks the `judge` scope. |
| `429` | The judge's inference queue is full — back off and retry. |
| `502` / `503` | The judge service is misconfigured or unavailable. |

Every error above is returned as `{"error": {"code": "...", "message": "..."}}`, not `{success:false,...}`.

## Example

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.60db.ai/v1/systemone \
    -H "Authorization: Bearer your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
        "state": "Agent: I can'"'"'t refund that, it'"'"'s outside the window.",
        "questions": {
            "tone": {
                "type": "choice",
                "criteria": {
                    "professional": "Calm and courteous",
                    "dismissive": "Brushes the caller off",
                    "unknown": "Not clear"
                }
            }
        }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.60db.ai/v1/systemone', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer your-api-key',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      state: "Agent: I can't refund that, it's outside the window.",
      questions: {
        tone: {
          type: 'choice',
          criteria: {
            professional: 'Calm and courteous',
            dismissive: 'Brushes the caller off',
            unknown: 'Not clear',
          },
        },
      },
    }),
  });
  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.60db.ai/v1/systemone",
      headers={
          "Authorization": "Bearer your-api-key",
          "Content-Type": "application/json",
      },
      json={
          "state": "Agent: I can't refund that, it's outside the window.",
          "questions": {
              "tone": {
                  "type": "choice",
                  "criteria": {
                      "professional": "Calm and courteous",
                      "dismissive": "Brushes the caller off",
                      "unknown": "Not clear",
                  },
              },
          },
      },
  )
  data = response.json()
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "model": "60db-decision-model-v1",
    "answers": {
      "tone": {
        "type": "choice",
        "choice": "dismissive",
        "probabilities": { "dismissive": 0.86, "professional": 0.11, "unknown": 0.03 },
        "confidence": 0.79
      }
    },
    "usage": { "input_tokens": 812, "output_tokens": 0 },
    "metadata": { "backend": "60db-local", "source_model": "60db-jev-source", "escalated_questions": 0 }
  }
  ```
</ResponseExample>
