Change the base URL. Keep your code.
Tīrtha speaks three dialects: OpenAI Chat, Anthropic Messages, and OpenAI Responses. Plain text, tools, and streaming work on all three. Below are copy-paste examples, the full config reference, and the error codes.
One base URL, one key.
Any OpenAI-compatible client works. Point it at the Tīrtha base URL, use your key, and set the model to tirtha/auto. The gateway chooses the tier for you.
The primary path.
POST /v1/chat/completions. Standard OpenAI request and response shapes. System prompts and multi-turn history are passed through. The response is the OpenAI shape you already parse.
Note: temperature is fixed at 0 and model is chosen by the gateway, so both are ignored if you send them. See the config reference below for the full honored-versus-ignored list.
Server-sent events, usage on the last chunk.
Set stream: true. To get token usage in the stream, set stream_options: {"include_usage": true} and read it from the final chunk.
OpenAI wire format, checked before it is served.
Send tools and, if you want, tool_choice. Tool calls come back in the OpenAI tool_calls shape, identical across all three dialects. Every tool call passes an internal check before it reaches you.
Same engine, three front doors.
Point Claude Code at Messages, point Codex at Responses, point everything else at Chat. Tools and streaming work on all three.
| Dialect | Endpoint | For |
|---|---|---|
| OpenAI Chat | POST /v1/chat/completions | The default; most SDKs and tools |
| Anthropic Messages | POST /v1/messages | Claude Code and Anthropic SDKs; system and history are native |
| OpenAI Responses | POST /v1/responses | Codex and the Responses SDK |
The reply is translated back into the dialect you called, so your existing client parses it unchanged. Usage fields and stop reasons follow each dialect's own convention.
Ask if an answer is backed by its source.
POST /v1/verify. Not part of the OpenAI standard, so point at it directly. Give a source and a claim; get a verdict, a confidence, and a short reason. It is a consistency check against the source, not a fact-checker of the world.
The key is required. To try it with no key, use tirtha.ai/verify.
Every param, honored or dropped.
Standard OpenAI parameters
| Param | Honored | Default | Notes |
|---|---|---|---|
messages | Yes | required | System prompt and full history passed through |
tools, tool_choice | Yes | none | Triggers the tool-calling path |
stream | Yes | false | Server-sent events |
stream_options | partial | none | Only include_usage is read |
response_format | Yes | none | {"type":"json_object"} passed through |
max_tokens | Yes | tier cap | Capped to the serving tier's limit |
temperature | ignored | 0 | Fixed at 0; determinism makes reuse safe |
model | ignored | tirtha/auto | The gateway selects the tier |
top_p | ignored | - | Declared for spec; moot at temperature 0 |
stop | soon | - | Declared, not yet wired |
Tīrtha extensions (body.tirtha.*)
| Field | Type | Default | Purpose |
|---|---|---|---|
mode | string | auto | Care dial: auto · max · value · low. Request overrides key overrides account. |
tests | string | none | The most useful field here. Checks that must pass before an answer is trusted; failures escalate. Also the only way to get a cached answer: we re-run your tests against a previously checked solution and return it only if they pass. Without tests we never serve from cache, and every request generates fresh. |
no_cache | boolean | false | Skip the cache for this request, both directions: nothing is read from it and nothing is written to it. Use it when the prompt carries something you do not want stored. Read this with the privacy note: when an answer passes verification we store it together with the prompt that produced it, in a store that is shared by default, so no_cache is the per-request opt out. Without the flag, a repeated request with tests can come back served_by: cache-exact; with it, every call goes to the model. |
domain | string | key default | Scope tag for reuse of solved work |
subdomain | string | key default | Sub-scope tag |
Which tier answered, and whether it was checked.
Every response carries a tirtha object beside the standard OpenAI fields, so you always know which tier served the answer and whether it passed the gate.
| Field | Meaning |
|---|---|
served_by | Which tier answered: a lower-cost model (e.g. deepinfra), frontier-value / frontier-max, cache-exact, or cache-crosscontext (a solution first written in another context, re-verified against your tests before serving). |
cache_eligible | false when you sent no tests, which means this request could not be served from cache. The response also carries cache_hint explaining it. Send tests to make a request cache-eligible. |
checked / checked_by | true only if the answer passed the gate, and checked_by names the check (tests, schema, consensus, cache): your tests for code, or structural + schema validation for a tool call. A schema-valid call is well formed, not necessarily correct. false = best-effort (a plain-text answer, or a declined call). |
escalated | true if a frontier model was used. The cascade climbs lower-cost → frontier-value → frontier-max only as far as the gate requires. |
mode | The care dial in effect for this request (auto/low/value/max). |
The refuse contract (tool-calling)
The core reliability promise: on the primary path, Tīrtha does not serve a tool call that fails your schema. The failover result is on /capabilities. When the model is not confident a tool applies, it does not invent a call and does not return an error. It returns a normal 200 with an empty tool_calls array and plain text explaining the limit, with checked:false. A malformed or schema-invalid lower-cost call is escalated to a frontier model first; only if no valid call can be produced is the empty-call answer returned.
What comes back when it will not serve.
Errors follow the OpenAI error shape. Two behaviors are worth knowing: rate and quota return 429, and hitting your daily spend cap does not fail. It degrades to the lower cost path and tells you so in the response.
| Status | Type | Meaning |
|---|---|---|
401 | invalid_api_key | Missing or bad Bearer key |
429 | rate_limit_error | Per-key rate exceeded. Honor Retry-After. |
429 | quota_exceeded | Monthly quota exceeded |
429 | server_busy | Concurrency gate full; retry shortly |
200 | meta.spend_capped:true | Daily spend cap reached; served on the lower cost path, never a silent switch |
200 | meta.premium_limited:true | Included premium allowance reached; served on the lower cost path |
The rest of the story.
The server info card has the capabilities matrix, limits, cache policy, and the honesty block. Security has the data posture. Pricing has the plans. Found a wrong answer? Report it and we send a receipt.
Free beta. API reference current as of 2026-07-18.