Direct API integration
There is no proprietary API to learn. The optimizer is an OpenAI-compatible
gateway: point a stock OpenAI client — or curl — at it, and every feature works
over plain HTTP. This page is the whole surface for a team that does not want a
dependency.
The one change
Swap the base URL to the edge, send your optimizer key as the bearer token, and
send your provider key in x-provider-key. That is the integration.
curl https://rfa-labs.com/v1/chat/completions \
-H "Authorization: Bearer $SHIMMY_API_KEY" \
-H "x-provider-key: $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [{ "role": "user", "content": "Say hello." }]
}' Authorization: Bearer sk-opt-…— your optimizer key. It identifies the tenant and is stored only as a hash; it is not your provider key.x-provider-key— the upstream key the gateway calls the model with (your OpenAI, Anthropic, etc. key). Alternatively, store per-tenant provider keys once and omit this header.model: "auto"— hands model choice to the gateway. A pinned model name is honored verbatim and turns routing off (and no saving is claimed on that call)."discover"makes the gateway search for the cheapest model that holds this step’s quality.
Any provider works from the same client — naming a Claude model is enough, because the edge translates OpenAI’s wire format to each provider server-side:
{ "model": "claude-haiku-4-5", "messages": [{ "role": "user", "content": "hi" }] } Telling the gateway what it can’t see
The gateway sees independent HTTP requests. Three things about your workload it
otherwise has to guess — how calls nest into runs, what each step is for, and
whether the answer was good — you can state outright by attaching an optimizer object to the request body. This is the wire contract; the SDK simply builds it
for you.
curl https://rfa-labs.com/v1/chat/completions \
-H "Authorization: Bearer $SHIMMY_API_KEY" \
-H "x-provider-key: $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [{ "role": "user", "content": "Classify: is this spam?" }],
"optimizer": {
"run": { "id": "job-1042", "seq": 0, "is_start": true },
"step": { "id": "classify_intent", "kind": "classification" }
}
}' The block is fully optional and every field within it is too. A request with no optimizer object behaves exactly as a plain OpenAI call. The fields:
| Field | Meaning |
|---|---|
run.id | Stable id grouping the calls of one execution. Any string you can reproduce for the run — a job id, a trace id. |
run.seq | 0-based position of this call in the run. |
run.parent | The step this call was made from. The one field that separates a fan-out from a chain. |
run.is_start | Whether this call opens the run (gates plan-cache lookup). |
step.id | Stable identity for this step, surviving prompt edits — so its learned routing is not reset when you reword. |
step.kind | What kind of work it is (classification, extraction, reasoning, …) — a difficulty prior, not a pin. |
step.quality.min_score | Raise this step’s quality bar. Can only tighten the tenant floor, never loosen it. |
intent.objective | cost, quality, or latency — which way to lean when they conflict. |
source.file / line / release | Where in your code the call was made, so a dashboard row points at a line and evidence is scoped per deploy. |
Reading what a call cost
The response carries an optimizer block alongside the usual choices:
# The response carries an `optimizer` block alongside the usual choices:
{
"choices": [ ... ],
"optimizer": {
"cache_hit": false,
"baseline_cost": 0.0121,
"served_cost": 0.0018,
"actual_cost": 0.0018,
"exploration_cost": 0.0,
"saving": 0.0103
}
} | Field | Meaning |
|---|---|
saving | Baseline cost minus what was actually spent. |
baseline_cost | What this call would have cost on your pinned/declared model. |
served_cost | The optimized path alone. |
exploration_cost | What was paid to learn whether a downshift was safe — converges toward zero as a step settles. |
cache_hit | Whether it was served from cache. |
Reporting outcomes
The quality gate can buy a signal by dispatching a second call and paying a judge
— that spend reaches you as exploration_cost. Your own code already knows
whether the JSON parsed or the tool ran. Report it, and free observation replaces
bought grading:
curl https://rfa-labs.com/v1/outcomes \
-H "Authorization: Bearer $SHIMMY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"run_id": "job-1042",
"step_id": "classify_intent",
"signals": { "schema_valid": true, "tool_executed": true }
}' Signals you can send (any subset): schema_valid, tool_executed, retried, run_completed, human_verdict (accepted / edited / rejected), and score (a [0,1] number from your own eval). A hard failure you observed
outranks any score.
Not double-billing a retry
If your client retries a completion (timeout, dropped connection), send an Idempotency-Key so the gateway replays the first attempt’s result instead of
dispatching — and metering — a second time.
curl https://rfa-labs.com/v1/chat/completions \
-H "Authorization: Bearer $SHIMMY_API_KEY" \
-H "x-provider-key: $OPENAI_API_KEY" \
-H "Idempotency-Key: 8f3c…-per-logical-request" \
-H "Content-Type: application/json" \
-d '{ "model": "auto", "messages": [ ... ] }' Reading savings
Everything the dashboard shows is a plain authenticated GET. The savings total,
split by source:
curl https://rfa-labs.com/v1/dashboard/savings \
-H "Authorization: Bearer $SHIMMY_API_KEY" For the per-call detail — what each request was routed to, what it saved, why — GET /v1/calls. The full set of control-plane reads and writes (billing
statement, agents, settings) is listed in the control-plane reference; every method
there is a thin wrapper over a /v1 endpoint you can call directly the same way.
Next
- SDK vs direct API — what you give up by staying on raw HTTP, and what you don’t.
- Concepts — what runs, steps and outcomes mean, and why the gateway cannot infer them.
- Control plane — every
/v1read and write.