Reference

API overview

What every request to A8 shares, from the base URL and authentication to the request parts and the response fields.

This page as Markdown: https://u22a8.ai/docs/api-overview.md. The index of every docs page: https://u22a8.ai/llms.txt.

Every interface to A8 shares one kind of key and one set of request parts and response fields. Each interface carries them in its own fields, and its page shows where.

§1Base URL and routes

InterfaceBase URLRoute
Chat Completionshttps://api.u22a8.ai/eval/v1POST /chat/completions
Responseshttps://api.u22a8.ai/eval/v1POST /responses
Anthropic Messageshttps://api.u22a8.ai/evalPOST /v1/messages
MCPhttps://api.u22a8.ai/mcpThe judge, teach and retract tools
Models listhttps://api.u22a8.ai/eval/v1GET /models
Table 1. The four interfaces and the models list. Routes are relative to the base URL. An Anthropic SDK takes the shorter base URL and adds /v1/messages itself.

The same request returns the same verdict through any interface.

§2Authentication

Every request carries an API key, as Authorization: Bearer <key> or as x-api-key: <key>. The key's permissions set what the request can do: models:infer to judge, models:explain for precedents and recall, and models:train to teach and retract. See API keys.

§3Request

A request has six parts:

PartRole
modelRequired. a8 for your organization’s latest version, a pinned version, or a8-1-1@reference for the reference model. Its tag carries the minimum accuracy. See Model identifiers.
CriterionWhat is being judged, in plain words. Required, unless every property of the verdict shape carries its own. Several system or developer messages are joined into one.
SubjectThe thing under judgment, in the user messages. Text: a string, or a list of text parts. A user message after A8’s response is a follow-up.
Verdict shapeOptional. A JSON Schema object. The default verdict is one label, or one number from 0 to 100.
Minimum accuracyOptional, 90 by default. Set by the model’s tag, as a8:95, in every interface. See Accuracy and abstention.
ReasoningOptional, on by default. On reads the request however it is laid out; off reads the layout as written. Set by each interface’s own reasoning field.
Table 2. The parts of a request.

Each interface carries the parts in the fields its own clients already send:

InterfaceCriterionSubjectVerdict shapeMinimum accuracyReasoning off
Chat CompletionsSystem messagesUser messagesresponse_formatmodel’s tagreasoning_effort: "none"
Responsesinstructionsinputtext.formatmodel’s tagreasoning: {"effort": "none"}
Anthropic MessagessystemUser messagesoutput_config.formatmodel’s tagthinking: {"type": "disabled"}
MCPinputinputformatmodel’s tagAlways on
Table 3. Where each part travels. Each interface’s page lists every field A8 reads.

With reasoning on, A8 also accepts a prompt that holds the criterion and the subject in one message, as many eval frameworks write their graders. A8 finds each part and answers in the format the prompt asks for. With reasoning off, A8 reads the layout as written, as each interface’s page lays out. See Chat Completions.

§3.1Verdict shape

Each property of the schema is one field of the verdict. Its type sets the kind of judgment the field holds:

PropertyVerdict
boolean, or an enumA label: one of the declared values
number or integerA score between minimum and maximum, which default to 0 and 100
precedentsReserved. Filled with the precedents behind the verdict; see Precedents.
Table 4. How a schema property is read. A $ref into $defs and a nullable anyOf are followed, so a schema generated from a Pydantic or Zod type reads the same as one written by hand.

A property with a description carries its own criterion and is judged on its own, so one request can carry several criteria. The request's criterion applies to the other properties. In this schema, urgent and tone are judged against their descriptions, and queue against the system message:

JSON
{
  "type": "object",
  "properties": {
    "queue": {"enum": ["billing", "shipping", "account"]},
    "urgent": {
      "type": "boolean",
      "description": "Does the customer need an answer today?"
    },
    "tone": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5,
      "description": "How polite is the message?"
    }
  }
}

A forced tool call is read the same way. When a request requires one function, the function's parameters are the verdict shape, and the verdict comes back as that tool call.

§3.2Subject context

Some judgments relate the subject to something else: a source it must be grounded in, a question it must answer, a reference it must match. For those, the subject is a JSON object with output, plus any of reference, context and question. A user message that holds a JSON object with output is read as a subject object, and any other text, JSON included, is judged as text:

KeyHolds
outputThe thing under judgment. Required.
referenceA string, or a list of strings: what the output should match
contextA string, or a list of strings: the material the output should rest on
questionOne string: what the output should answer
Table 5. The keys of a subject object. Any other key returns 400 with the code unknown_subject_key.

The object travels inside the user message as a JSON string:

Python
import json

subject = {
    "output": "Your refund went out on Monday.",
    "context": ["Refund issued on Monday to the original card."],
}
messages = [
    {"role": "system", "content": "Is the output supported by the context?"},
    {"role": "user", "content": json.dumps(subject)},
]

A criterion taught against a standard is judged against that standard. A request that leaves it out abstains and names it in abstention.missing.

§3.3Continue a conversation

A request is a conversation, and A8 answers its latest user message. To follow up on a verdict, send the conversation again with A8’s response as an assistant message and a new user message after it. The follow-up can bring a new subject to judge against the same criterion, change the subject or add a standard such as a reference:

Python
messages = [
    {"role": "system", "content": "Which queue does the ticket belong in?"},
    {"role": "user", "content": "It arrived crushed. I want a refund."},
    {"role": "assistant", "content": '{"queue": "shipping"}'},
    {
        "role": "user",
        "content": "The customer adds: the box was fine. I was charged twice.",
    },
]
JSON
{"queue": "billing"}

Recorded from a8-1-1@20260715t140322z on 2026-10-22.

  • A8 answers the conversation as sent. Assistant messages are read as earlier turns, whatever they hold, and the response depends on the messages in the request alone.
  • The whole conversation is the request. The same conversation against the same version gets the same verdict, and a teach of it records the whole conversation as its input.
  • With reasoning off, A8 judges the latest user message alone. Earlier turns are history, so the conversation gets the verdict its latest user message gets on its own.
  • On Responses, previous_response_id continues from a stored response. Its input and output come before the new input, and the verdict is the one the whole conversation gets. See Responses.

§4Response

Each interface answers with its own object and puts the verdict where that API puts a model's output. These fields are on every response, under the same names:

FieldMeaning
modelThe exact version that answered, with the minimum accuracy in its tag. Send it back to get the same verdict. See Horizons.
usageThe tokens A8 read, and the reasoning tokens reading the request took as the output count, since the verdict is scored. A repeat reports its reading as cached input tokens.
system_fingerprintA token that moves when anything behind the verdict moves. See Reproducibility.
min_accuracyOn every verdict: the level the verdict is promised at, which is the minimum accuracy asked for or the nearest earned level above it
abstentionOn an abstention: kind, asked, answerable_at, earned and missing. Keyed by property under fields when properties declined separately. See Accuracy and abstention.
interval, intervalsOn a score answered at a minimum accuracy above 0: the [low, high] range the level guarantees, in the schema's units
precedentsWhen the request asks for them: the taught examples behind the verdict. See Precedents.
Table 6. The response fields. min_accuracy, abstention, interval, intervals and precedents are extensions, which standard clients carry through untouched.

A Chat Completions response, with the fields in place:

JSON
{
  "id": "eval-9f2c1d84ab30e5f7",
  "object": "chat.completion",
  "model": "a8-1-1:95@20260715t140322z",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "{\"queue\": \"shipping\"}",
        "refusal": null
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 812,
    "completion_tokens": 0,
    "total_tokens": 812,
    "prompt_tokens_details": {"cached_tokens": 0},
    "completion_tokens_details": {"reasoning_tokens": 0}
  },
  "system_fingerprint": "fit-1a2b3c4d5e6f7890.9e2a1b3c",
  "min_accuracy": 95
}

Recorded from a8-1-1@20260715t140322z on 2026-10-22.

An abstention returns 200 and sits where each API puts an answer a model declined to give, so a typed client reads it like any other response. See Accuracy and abstention.

With reasoning on, A8 filters some requests whose text is harmful, such as hate speech, violence or self-harm. A filtered request returns 200 in the slot each API keeps for content its filters stop, apart from verdicts and abstentions, and is free. Each interface’s page shows its form.

§5Versioning and compatibility

The request and response formats follow the APIs A8 implements. Within a model version such as a8-1, A8’s own fields change by addition only. These changes count as compatible:

  • A new optional request parameter.
  • A new response field, or a new field inside abstention or precedents.
  • A new value of abstention.kind. Read an unfamiliar kind as an abstention.
  • A new error code under an existing status.
  • A new response header.
  • A different order of properties in a JSON object.

Every other change ships with a new model version, announced on Deprecations and in the Release notes. See Model identifiers for how identifiers and horizons hold a verdict fixed.

§6Request IDs

Every response carries an x-request-id header, and the Anthropic route also sends it as request-id, the header the Anthropic SDKs read. An error body carries the same ID. Quote it when you write to [email protected] about a request.

SDKWhere the ID is
OpenAI, Pythonresp._request_id
OpenAI, TypeScriptresp._request_id
Anthropic, Pythonmessage._request_id
Anthropic, TypeScriptmessage._request_id
Table 7. Where each SDK exposes the request ID.

§7SDKs

You call A8 through the standard SDKs or any client that takes a custom base URL, such as LangChain, LlamaIndex, the Vercel AI SDK, Pydantic AI and LiteLLM.

SDKPackageWritten against
OpenAI, Pythonopenai3.36.1
OpenAI, TypeScriptopenai7.42.0
Anthropic, Pythonanthropic2.1.0
Table 8. The SDKs the samples in these docs use, and the version each was written against.

The SDKs keep A8’s extension fields on the response object:

Python
resp = client.chat.completions.create(**request)

resp.model                         # the version that answered
resp.model_extra.get("min_accuracy")  # the level the verdict is promised at
resp.model_extra.get("abstention") # set on an abstention

Next steps