A8 reference

The wire contract for the OpenAI-compatible eval endpoint: two routes, the fields that carry meaning, and what comes back. The concepts behind them are on the A8 overview and abstention.

Base URL and authentication

Base URLhttps://api.u22a8.ai/eval/v1
EvaluatePOST /chat/completions, or the base URL itself
List modelsGET /models
AuthenticationAuthorization: Bearer <key>. The key needs the eval:run ability.
Rate limitNo fixed published limit. Sustained or abusive traffic is throttled at the edge and receives 429.

Table 1. The base URL, the two routes relative to it, and the credential each requires.

Request

The body is an OpenAI chat-completion request. Three parts carry meaning.

FieldRole
modelRequired. a8 for the live model, a pinned snapshot, or a8-0-2@reference for the shared baseline with none of your corrections in it — see horizons.
messages — systemRequired. The criterion: what is being judged. developer is accepted as a synonym for system.
messages — userRequired. The last user message is the subject: the thing under judgment.
response_formatOptional. A json_schema describing the verdict's shape. Without it the verdict comes back as plain text.
min_accuracyOptional. The accuracy to answer at — an integer 099, where 0 asks for no promise. See abstention. Defaults to 90.
expectedOptional. The verdict you wanted, which fine-tunes the model. See fine-tuning.

Table 2. Request fields. The standard OpenAI chat fields — temperature, top_p, seed and the rest — are accepted and ignored, so a body written for another provider does not break. Any other unrecognised field is rejected by name; see 422 below.

Describing the verdict shape

When a schema property carries a description, that description becomes its own criterion and is judged independently. One request can therefore carry several criteria at once — the system message applies only to properties that don't describe themselves.

{ "model": "a8", "messages": [ {"role": "system", "content": "Is the answer grounded in the context?"}, {"role": "user", "content": "The tower was finished in 1889."} ], "response_format": { "type": "json_schema", "json_schema": { "name": "verdict", "schema": { "type": "object", "properties": { "grounded": {"type": "boolean"} } } } } }

Giving the subject a context

Where the judgement is relational — grounded in a source, answering a question, matching a reference — the user message may be a JSON object with an output field plus at least one of reference, context, or question. Anything else is read as plain text.

Response

A standard chat.completion object. The verdict is the message content — a label, a number, or a JSON object matching the requested schema.

{ "id": "eval-9f2c1d84ab30e5f7", "object": "chat.completion", "model": "a8-0-2@20260715t140322z", "choices": [{ "index": 0, "message": {"role": "assistant", "content": "{\"grounded\": true}"}, "finish_reason": "stop" }], "usage": {"prompt_tokens": 812, "completion_tokens": 0, "total_tokens": 812}, "system_fingerprint": "fit-1a2b3c4d5e6f7890.9e2a1b3c" }
FieldMeaning
modelThe exact snapshot that answered — more specific than what was asked for. Send it back verbatim to reproduce this verdict. See horizons.
usagecompletion_tokens is always 0: nothing writes the verdict. prompt_tokens is what the model read.
system_fingerprintA change detector covering everything that determined the verdict. See reproducibility.
min_accuracyPresent on every answer: the level the verdict is promised at, which is the level asked for or the nearest earned one above it. 0 means no promise was requested. See abstention.
abstentionPresent when the model declined to answer — reason for a single verdict, fields when a schema's properties declined separately. reason is human-readable prose; its wording and its numbers are not part of the contract. See abstention.
interval / intervalsPresent on a graded verdict answered under a promise: the [low, high] range the promised level guarantees, in the schema's declared units. Absent when min_accuracy is 0.

Table 3. Response fields. The first three are standard OpenAI slots; the rest are extensions that standard clients ignore.

Examples

# curl curl -s https://api.u22a8.ai/eval/v1/chat/completions \ -H "Authorization: Bearer $U22A8_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "a8", "messages": [ {"role": "system", "content": "Does this reply meet our support quality bar?"}, {"role": "user", "content": "Sorry for the delay — your parcel left the depot this morning."} ] }'
# python — any OpenAI-compatible client from openai import OpenAI client = OpenAI( base_url="https://api.u22a8.ai/eval/v1", api_key="<your key>", ) resp = client.chat.completions.create( model="a8", messages=[ {"role": "system", "content": "Does this reply meet our support quality bar?"}, {"role": "user", "content": "Sorry for the delay — your parcel left the depot this morning."}, ], )

Status codes

StatusCondition
401No Authorization: Bearer header, or the key is not valid.
403The key lacks the eval:run ability.
404The pinned horizon names no stored snapshot. See horizons.
422The body cannot be read as an eval — no messages, no system or user message, a min_accuracy outside 099, or an unrecognised body field. A misspelled parameter is rejected rather than silently replaced by the default.
429Rate limited. Back off and retry.
503Temporary: the pinned horizon is still fine-tuning (Retry-After: 30), or an upstream dependency is briefly unavailable (Retry-After: 5). OpenAI clients retry this automatically.

Table 4. Status codes. Errors carry an OpenAI-shaped error body, and every response carries an x-request-id header worth quoting in a support request.