Build Route Evidence Capsules for AI API Gateways
A model route can look stable from the client side while the evidence around it is already drifting.
The HTTP call still works. The OpenAI-compatible request shape still works. The model alias still resolves. The application team sees no broken test. Meanwhile, the dated price row may have changed, a cache field may no longer match the forecast, a policy exception may have moved from temporary to permanent, or the buyer may be looking at a stale spreadsheet that does not name the source date.
That gap is where Tier 1 and Tier 2 teams lose time. Engineering can explain the request. Finance can explain the budget. Security can explain which inputs were redacted. Procurement can explain why a route was approved. But those explanations often live in different places.
A route evidence capsule puts them in one small artifact.
The capsule is not a dashboard. It is not a public usage claim. It is not a private log export. It is a compact review object that travels with a route change, workbook, SDK example, incident review, or deployment gate.
It answers one question:
If this AI API route ships today, can a reviewer see exactly which model row, policy checks, pricing source, and redacted receipt shape supported the decision?
I will use AIWave as the concrete example because it exposes both a live route table and a dated public pricing snapshot. The same pattern applies to any OpenAI-compatible gateway that gives engineers one client surface while still requiring accountable route choices behind the scenes.
What belongs in the capsule
A useful capsule is intentionally small. It should be easy to attach to a pull request, release note, procurement packet, support escalation, or internal runbook.
At minimum, include these fields:
| Field | Purpose |
|---|---|
capsule_id |
Stable identifier for the route decision |
checked_at |
When the evidence was collected |
route_name |
The exact model or gateway route used by the client |
client_shape |
The API family expected by the application |
pricing_sources |
Live and dated sources that were checked |
price_row |
The public base row used for planning |
group_note |
Reminder that account or key group can alter final billing |
policy_checks |
Data, region, retry, timeout, and tool-use boundaries |
receipt_shape |
Redacted fields expected after a request completes |
unknowns |
Items that must not be inferred |
verdict |
pass, review, or block
|
The most important field is often unknowns. Teams get into trouble when they let a missing denominator, missing cache field, or missing route receipt turn into a confident statement. The capsule should make that uncomfortable. If the evidence is absent, say so.
Source check from September 17, 2026
During this run on September 17, 2026, I checked AIWave's public pricing sources before writing the article.
The live route table at https://aiwave.live/api/pricing returned HTTP 200, success=true, 68 route rows, auto_groups=["default"], and pricing version a42d372ccf0b5dd13ecf71203521f9d2.
The dated public snapshot at https://aiwave.live/api/v1/pricing returned HTTP 200, checked=2026-09-10, updated_at=2026-09-10, currency USD, unit per_1m_text_tokens, source /api/pricing, source page https://aiwave.live/pricing, pricing version 8c7a0c0b30661ccbc13d142cb54d1e4ae445fe774b2c6fa501080db97c7a3e56, and 64 public model rows.
Those two sources should not be collapsed into one vague statement like "current pricing". The live route table is the operational source. The dated snapshot is the public evidence artifact. A capsule can use both, but it should record which one provided which fact.
Example rows from the dated public snapshot:
| Model ID | Provider family | Input / 1M text tokens | Cache-hit input / 1M | Output / 1M text tokens | Effective date |
|---|---|---|---|---|---|
deepseek-v4-flash |
DeepSeek | $0.638 |
$0.0202884 |
$1.914 |
2026-08-27 |
deepseek-v4-pro |
DeepSeek | $1.914 |
$0.0637362 |
$5.742 |
2026-08-27 |
glm-4.5 |
GLM | $0.6975 |
$0.1800003375 |
$2.1699999225 |
2026-08-27 |
minimax-m2.5 |
MiniMax | $0.46866 |
$0.046866 |
$1.87464 |
2026-08-27 |
kimi-k2.7-code |
Kimi | $1.89 |
$0.28500066 |
$5.99999967 |
2026-08-27 |
qwen3.8-27b |
Qwen | $0.6695133382 |
not listed | $2.6780533528 |
2026-08-27 |
These rows are public base rates, not final invoices. Final cost still depends on the account or key group, selected route, cache behavior, retry count, output length, and the private request receipt.
That is exactly why the capsule should carry both planning evidence and receipt expectations.
A capsule schema
Start with a schema that is boring on purpose.
{"capsule_id":"route_capsule_deepseek_v4_flash_2026_09_17","checked_at":"2026-09-17T13:05:00Z","route_name":"deepseek-v4-flash","client_shape":"openai.chat.completions","pricing_sources":{"live_route_table":"https://aiwave.live/api/pricing","dated_snapshot":"https://aiwave.live/api/v1/pricing"},"price_row":{"currency":"USD","unit":"per_1m_text_tokens","input":0.638,"cache_hit_input":0.0202884,"output":1.914,"effective_date":"2026-08-27"},"group_note":"Public row is a base rate. The final request receipt controls applied billing.","policy_checks":{"prompt_logged":false,"api_key_logged":false,"retry_cap":1,"timeout_ms":60000,"tool_budget_required":true},"receipt_shape":{"request_id":"present","model":"present","input_tokens":"numeric","output_tokens":"numeric","cache_hit_tokens":"numeric_or_null","charged_amount":"private_receipt_only"},"unknowns":["Future route changes after checked_at","Final output length before request completion","Private account group unless authenticated receipt is inspected"],"verdict":"review"}
Notice that charged_amount is not copied into a public artifact. The capsule records the expected receipt shape, not customer-specific billing data. That distinction keeps the artifact useful without dragging private operations into places they do not belong.
Build it in Python
Here is a small capsule builder. It fetches the dated public snapshot, selects a route, and writes a review object. It uses an environment variable for the API key pattern in the example, but this specific public pricing call does not require a secret.
import datetime as dt
import json
import os
import urllib.request
SNAPSHOT_URL = "https://aiwave.live/api/v1/pricing"
LIVE_URL = "https://aiwave.live/api/pricing"
def fetch_json(url: str) -> dict:
request = urllib.request.Request(
url,
headers={"User-Agent": "route-evidence-capsule/1.0"},
)
with urllib.request.urlopen(request, timeout=20) as response:
return json.loads(response.read().decode("utf-8"))
def find_model(snapshot: dict, model_id: str) -> dict:
for row in snapshot.get("models", []):
if row.get("id") == model_id:
return row
raise ValueError(f"model row not found: {model_id}")
def build_capsule(model_id: str) -> dict:
snapshot = fetch_json(SNAPSHOT_URL)
row = find_model(snapshot, model_id)
missing = []
if row.get("cache_hit_usd_per_1m_tokens") is None:
missing.append("cache_hit_input is not listed for this public row")
verdict = "pass" if not missing else "review"
return {
"capsule_id": f"route_capsule_{model_id}_{dt.date.today().isoformat()}",
"checked_at": dt.datetime.now(dt.UTC).isoformat(),
"route_name": model_id,
"client_shape": "openai.chat.completions",
"pricing_sources": {
"live_route_table": LIVE_URL,
"dated_snapshot": SNAPSHOT_URL,
"snapshot_checked": snapshot.get("checked"),
"snapshot_version": snapshot.get("pricing_version"),
},
"price_row": {
"provider": row.get("provider"),
"currency": snapshot.get("currency"),
"unit": snapshot.get("unit"),
"input": row.get("input_usd_per_1m_tokens"),
"cache_hit_input": row.get("cache_hit_usd_per_1m_tokens"),
"output": row.get("output_usd_per_1m_tokens"),
"effective_date": row.get("effective_date"),
},
"policy_checks": {
"api_key_source": "os.environ.get('AIWAVE_API_KEY')",
"api_key_logged": False,
"prompt_logged": False,
"timeout_ms": 60000,
"retry_cap": 1,
},
"unknowns": missing,
"verdict": verdict,
}
if __name__ == "__main__":
# Pattern only. Do not print or persist the actual key.
api_key = os.environ.get("AIWAVE_API_KEY")
capsule = build_capsule("deepseek-v4-flash")
print(json.dumps(capsule, indent=2))
In production, I would add a second fetch against the live route table and compare route availability, endpoint support, and pricing version. I would also reject a capsule if the model row exists in only one source unless the release owner explicitly accepts that mismatch.
Review gates
The capsule becomes useful when it blocks vague approvals.
Add these gates before a route ships:
| Gate | Pass condition | Review condition | Block condition |
|---|---|---|---|
| Source freshness | Pricing source checked in the current run | Dated snapshot is older than planned | Source cannot be fetched |
| Row identity | Exact model ID exists | Alias maps through an undocumented route | Only a similar model is found |
| Unit clarity | Currency and unit are present | Unit exists but examples mix units | Unit is missing |
| Cache semantics | Cache row is present or explicitly absent | Cache field differs across sources | Forecast assumes cache when no row exists |
| Receipt safety | Receipt shape is redacted | A reviewer asks for private fields | Secret, prompt, or customer data appears |
| Billing group | Group note is explicit | Group is known only after auth | Public text claims final billing without receipt |
| Retry behavior | Retry cap is named | Retry policy differs by route | Forecast ignores retries |
This is a better workflow than a long meeting where everyone says "pricing looks current" without naming the source.
The gate should produce one of three verdicts:
pass - evidence supports the route decision
review - route can proceed only with named unknowns accepted
block - source, row, unit, policy, or receipt safety failed
For many model changes, review is the honest result. A missing cache row is not always a deployment blocker. A changed version field is not always a bug. But both should be visible before the route becomes a default in code, a spreadsheet, or a public example.
Where to store capsules
Do not bury route evidence in chat history. Store capsules near the thing they approve.
For an SDK, put them under evidence/routes/ and link them from the pull request. For a procurement workbook, attach the capsule JSON next to the workbook export. For a production route change, store the capsule with the release artifact. For an incident, create a post-incident capsule that records which assumptions were wrong.
Keep the artifact small enough that a reviewer reads it.
A practical naming scheme:
evidence/routes/
2026-09-17-deepseek-v4-flash-chat-completions.json
2026-09-17-glm-4-5-cache-policy.json
2026-09-17-qwen3-8-27b-no-cache-row-review.json
The name should include the date, model ID, and reason for review. That makes later searches useful without opening every file.
What not to put in the capsule
The capsule is an evidence boundary. Keep it clean.
Do not include API keys. Do not include prompts. Do not include raw responses. Do not include customer identifiers. Do not include private revenue, registration, or request volume. Do not use the capsule as marketing proof. Do not claim a route is faster, more reliable, or better unless the exact benchmark and date are in scope.
The capsule should help a serious reviewer say:
- Which route was chosen.
- Which pricing sources were checked.
- Which date and unit apply.
- Which policy constraints were accepted.
- Which unknowns remain.
- Which private facts are intentionally excluded.
That last point matters. A good artifact is not only clear about what it knows. It is clear about what it refuses to expose.
A release checklist
Before a route evidence capsule is accepted, run this checklist:
[ ] Exact route name appears in the live route table or approved source
[ ] Public snapshot row is present, dated, and uses USD per 1M text tokens
[ ] Cache-hit field is either recorded or explicitly absent
[ ] Account or key group note is present
[ ] Retry cap and timeout are named
[ ] Receipt shape is redacted
[ ] No API key, prompt body, raw customer data, or private usage number appears
[ ] Verdict is pass, review, or block
[ ] Reviewer can reproduce the public source checks
This checklist is deliberately plain. Fancy controls fail when people cannot run them during a real release. A capsule should be easy to regenerate and easy to challenge.
Why this helps Tier 1 and Tier 2 teams
Tier 1 and Tier 2 buyers rarely reject AI API work because an engineer cannot write a request. They slow down because every serious route change crosses multiple concerns: cost, source date, region, retention posture, retry behavior, support path, and receipt auditability.
Route evidence capsules reduce translation work between those concerns.
Engineering gets a stable artifact for code review. Finance gets dated units and source URLs. Security gets a redaction boundary. Procurement gets a small trail that explains why one route was accepted without relying on vague claims. Support gets a way to inspect drift without asking for secrets.
The real benefit is cultural: a team stops treating model choice as a hidden preference and starts treating it as a reviewable decision.
When the next route changes, the question is no longer "Which model did we like?" It becomes "Which evidence capsule supports this route today?"
That is a much better question to ship with.