Idempotency
Retry a call safely with an Idempotency-Key - the same key replays the original answer instead of billing you twice.
POST /agent/ask is not naturally idempotent: two calls produce two
answers and two charges. Send an Idempotency-Key and a retry replays
the first response instead of running the agent again.
Reach for it whenever a retry could be triggered by something other than you - a network timeout, a queue redelivery, a user double-click.
Sending a key
Any string of 1-255 printable ASCII characters. A UUID per logical operation is the usual choice.
curl -s https://api.neurobro.ai/api/v1/agent/ask \
-H "Content-Type: application/json" \
-H "X-API-Key: $NEUROAPI_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"prompt":"What is the BTC funding rate?","mode":"smart"}'Keys are scoped to your API key, so they can't collide with another account's - or with your own other keys.
What a retry does
Repeat the request with the same key and the same body within 24
hours and you get the original status, body and X-Request-Id back,
plus:
Idempotent-Replayed: trueA replay is not billed again: cost_units is debited once, however
many times you retry. The X-Request-Id you get back is the first call's -
that's the one to quote when reporting an issue.
When it doesn't replay
| Situation | Result |
|---|---|
| Same key, different body | 422 idempotency_key_mismatch - use a fresh key per distinct request. |
| First call still running | 409 idempotent_request_in_flight - retry once it finishes. |
| Key older than 24h | Treated as new; the agent runs and you are billed. |
| Key isn't 1-255 printable ASCII | 400 invalid_idempotency_key. |
| Query string sent alongside the key | 400 invalid_query_string. |
Two things are never cached, so a retry re-runs and re-bills:
- Streaming responses (
stream=true). 5xxresponses - a server-side failure is always safe to retry.
Only mutating methods (POST, PUT, PATCH, DELETE) participate;
GET requests ignore the header.
Retrying well
Pair the key with backoff. Generate it before the first attempt and reuse it for every retry of that operation - a key generated inside the loop defeats the mechanism.
import time, uuid
import httpx
key = str(uuid.uuid4()) # once, outside the loop
for attempt in range(3):
response = httpx.post(
"https://api.neurobro.ai/api/v1/agent/ask",
headers={"X-API-Key": API_KEY, "Idempotency-Key": key},
json={"prompt": "What is the BTC funding rate?", "mode": "smart"},
timeout=60.0,
)
if response.status_code not in (409, 429, 503):
break
time.sleep(2**attempt)See Errors for the full status and code reference.