AgentCache API
Reuse answers your agent has already paid for. For what AgentCache is and what it costs, see the AgentCache overview.
Base URL
https://cache.myuiaf.com
Requests and responses are JSON.
MCP server
https://cache.myuiaf.com/mcp
The same features as MCP tools (lookup, store, delete_entry and purge_namespace), for Claude, OpenAI, Gemini, Grok and any MCP client. Streamable HTTP; send your key as Authorization: Bearer fv1.... Setup examples: Integrations.
Authentication
Use the same API key as Freshness Validator and AgentPay: fv1.<agent_id>.<key_id>.<secret>. Send it in one of these headers:
X-Agent-API-Key: fv1.acme-bot.k1.xxxxx
X-Api-Key: fv1.acme-bot.k1.xxxxx
Authorization: Bearer fv1.acme-bot.k1.xxxxx
To get a key, buy a credit pack, or let your agent call POST https://api.myuiaf.com/api/v1/credits.
The pattern
- Before calling your model or API,
POST /v1/lookupwith the question. - If
hitistrue, useanswer. - If not, call your model as usual, then
POST /v1/storewith the question and the answer.
Send the question itself as prompt, not the whole conversation. Put anything that changes the answer but isn't the question, such as the model name or system prompt version, in context.
Look up
POST /v1/lookup
| Field | Required | Meaning |
|---|---|---|
prompt | Yes | The question, up to 8,000 characters. |
namespace | No | A label you choose, such as support. Default default. 1–48 letters, digits, _ . : -. |
context | No | Up to 4,000 characters that must match exactly, such as model=x;prompt=v3. |
min_similarity | No | From 0.92 to 1. Default 0.95. Use 1 to accept exact repeats only. |
curl -X POST https://cache.myuiaf.com/v1/lookup \
-H "X-Agent-API-Key: fv1.acme-bot.k1.xxxxx" \
-H "content-type: application/json" \
-d '{"prompt":"How can I reset my password?","namespace":"support"}'
A hit:
{
"hit": true,
"match": "similar",
"similarity": 0.9984,
"entry_id": "3f9a0c1b2d4e5f60718293a4.0c1d2e3f405162738495a6b7c8d9e0f1",
"namespace": "support",
"cached_prompt": "How do I reset my password?",
"answer": "Go to Settings, then Security, then Reset password.",
"cached_at": "2026-11-08T12:00:00.000Z",
"expires_at": "2026-11-09T12:00:00.000Z",
"charged_usd": 0.002,
"original_cost_usd": 0.012,
"saved_usd": 0.01
}
A miss (always HTTP 200, never charged):
{ "hit": false, "charged_usd": 0, "next": "Call your model or API as usual, then POST /v1/store ..." }
A miss may include degraded (similar_matching_unavailable, storage_unavailable or wallet_unavailable) when part of the service was briefly unavailable. Carry on as for any miss. Response headers: X-AgentCache-Hit (exact, similar or miss) and X-AgentCache-Charged-USD.
Save an answer
POST /v1/store
| Field | Required | Meaning |
|---|---|---|
prompt | Yes | The question, as for a lookup. |
answer | Yes | A string or any JSON value, up to 60,000 bytes as JSON. |
namespace, context | No | As for a lookup. A lookup only finds answers saved with the same values. |
ttl_seconds | No | How long to keep it: 60 to 2,592,000 (30 days). Default 86,400 (24 hours). |
original_cost_usd | No | What the model or API call cost. Hits then report saved_usd. |
HTTP/2 201
{
"stored": true,
"entry_id": "3f9a0c1b2d4e5f60718293a4.0c1d2e3f405162738495a6b7c8d9e0f1",
"namespace": "support",
"expires_at": "2026-11-09T12:00:00.000Z",
"exact_match": "ready",
"similar_match": "indexing",
"charged_usd": 0
}
Exact repeats match immediately. Reworded questions start matching in about 1Reworded questions start matching within a few seconds.ndash;2 minutes, once the new answer is indexed. Saving the same question again replaces its answer. Saving is free.
How matching works
- Exact: the same question after spaces are tidied up. No model is involved, so it is the fastest match.
- Similar: the question is turned into an embedding with the bge-m3 model, which runs inside Cloudflare (no third party sees it) and understands many languages. The closest saved question counts as a match only if its similarity is at least
min_similarityand both questions contain exactly the same numbers. “Order 12345” never matches “order 12346”, and “2022” never matches “2018”.
In our tests, rewordings of the same question scored 0.95 to 0.998. The closest pair of different questions (“opening hours on Saturday” and “on Sunday”) scored 0.92, which is why the default is 0.95 and the lowest allowed is 0.92. Questions over 2,000 characters are matched exactly only, so a long shared preamble can never hide a different question.
Only cache answers that are the same for everyone in the namespace. Don't cache personal data, or answers that depend on who is asking.
Namespaces and context
Every answer belongs to one agent, one namespace and one context. A lookup searches only that space. Another agent can never find your answers, even with the same namespace name. Use namespaces to keep topics apart, and to share answers between parts of the same agent.
When you are charged
| Result | Charge |
|---|---|
| Hit (exact or similar) | $0.002 |
Miss, including a degraded miss | Free |
Retry with the same Idempotency-Key | Free (the original answer is returned) |
| Store, delete, purge | Free |
If a saved answer exists but the wallet can't cover $0.002, the lookup answers 402 insufficient_credits with a topup link, and the answer is not returned. The wallet is shared with Freshness Validator and AgentPay; hits appear in its history as agentcache hit.
Idempotency
Optional. Send an Idempotency-Key header (1–250 printable characters) on a lookup, and a retry with the same key and the same question returns the same answer with Idempotent-Replayed: true and no second charge, for 24 hours. The same key with a different question returns 422 idempotency_key_reused.
Delete and purge
DELETE /v1/entries/{entry_id}
Removes one saved answer. Returns {"deleted": true}, or 404 if it isn't yours or doesn't exist.
POST /v1/purge
Removes every answer in a namespace (and context): send {"namespace":"support"}. Up to 500 per call; if more is true, call again. Answers saved in the last minute may need a second purge. A good moment to purge is when Freshness Validator reports that the source behind those answers has changed.
Limits
| Tier | Requests per minute |
|---|---|
| Early Testing | 120 |
| Growing Product | 300 |
| Scale Revenue | 1,000 |
| Enterprise | 3,000 |
Counted separately from Freshness Validator and AgentPay. Over the limit: 429 with Retry-After. Request bodies up to 128 KB.
Errors
Errors are JSON: {"error": "...", "code": "..."}.
| Status | Codes |
|---|---|
| 400 | missing_prompt, prompt_too_long, invalid_namespace, context_too_long, invalid_min_similarity, missing_answer, invalid_ttl_seconds, invalid_original_cost_usd, invalid_idempotency_key, invalid_json |
| 401 | missing_api_key, invalid_api_key |
| 402 | insufficient_credits: a hit was found but the wallet can't cover it |
| 404 | entry_not_found, not_found |
| 409 / 422 | request_in_progress, idempotency_key_reused |
| 413 | answer_too_large, body_too_large |
| 429 | rate_limited, temporarily_blocked |
| 503 | auth_unavailable, storage_unavailable (store only), service_unavailable. Nothing was charged; retry. |
Health
GET /v1/health
{"status":"ok","service":"agentcache","checks":{"registry":"ok","answers":"ok","vectors":"ok","ledger":"ok","embeddings":"not_checked"}}
Live status of all services: myuiaf.com/status. Machine-readable: OpenAPI, Markdown.