Skip to content
AstroWay/api v2.325.2 · docs
all systems operational

Idempotency

Last updated View as Markdown Agent setup

All AstroWay API endpoints are naturally idempotent: same input always produces same output, no side effects (except credit consumption and usage logging).

This means retrying on network errors is safe. But to ensure a retry doesn’t charge credits twice, pass an Idempotency-Key header.

POST /v1/chart HTTP/1.1
X-Api-Key: aw_live_...
Idempotency-Key: 01HXY2A7ZM0ABCDEF
Content-Type: application/json
{ "date": "1990-07-14", "time": "14:30:00", ... }

Idempotency-Key - a string of 1-255 visible ASCII characters with no spaces, unique per logical operation. Recommended: ULID or UUID v4. Our SDKs add a key to every POST themselves and keep it across their own retries.

The key applies to POST, PUT and PATCH and belongs to your API key: another API key sending the same Idempotency-Key never sees your response. Endpoints whose response can carry a secret ignore the header: key and account management (/keys, /site-keys, /auth/*, /me), webhook subscriptions (/webhooks/*), OAuth (/oauth/*) and payments (/payments/*). On any other endpoint, a response that contains a credential field (api_key, signing_secret, token and the like) is not stored either, and the key is freed.

  • For 24 hours after the first request, a repeat with the same key, method, path, body and query string returns the stored response (same status, Content-Type and body) without recalculation and without charging credits. The body is compared after JSON parsing, so field order and whitespace do not matter.
  • The replayed response carries Idempotent-Replayed: true, X-Credits-Used: 0 and Idempotent-Original-Credits-Used with the price of the first request.
  • 24 hours after the first request the key is forgotten; a new request with the same key is treated as a normal new request.

A replay goes through the same key check and the same rate limit as any request: a revoked key gets 401, not the stored response.

StatusCodeWhen
400INVALID_IDEMPOTENCY_KEYthe key is empty, longer than 255 characters, contains a space or a non-ASCII character, or the header was sent twice
409IDEMPOTENCY_KEY_REUSEDthe key was already used with a different body or query string. A new request needs a new key
409IDEMPOTENCY_IN_PROGRESSthe first request with this key is still running. The response carries Retry-After: 1; retry and you get its result

None of these responses is charged.

  • Only a successful (2xx) response. An error (4xx, 5xx) is not charged and not remembered, so after one you can retry with the same key, including with a corrected body.
  • A dropped connection. If the client disconnects before the response is complete, the request is not charged and the key is freed for the retry.
  • Streamed (SSE) and binary responses are stored whole and replayed as one body with the same Content-Type. A stream whose last event is an error (type: "error") is not stored even though its status is 200, and the key is freed for a retry. Such a stream is not charged, although the X-Credits-Used header, sent before the stream began, shows the price of the call.
  • A response over 1 MB is not stored, and the key is released. A repeat with the same key is a new request and is charged like one.
  • If the key store is unavailable, the request is processed as if no key had been sent: you get a response rather than a 500, but a retry during that time may be charged again.

  • In webhook handlers where retries come from an external system (e.g. a payment provider or CRM sending events you parse and use for a calculation)
  • In background jobs where retry is standard behavior on failures
  • In CI/CD pipelines where a test may run multiple times

For normal “user clicks a button → show a chart” flows, idempotency isn’t needed - the user sees the result anyway, repeat clicks are rare.

  • Don’t set the key to save credits on identical requests: use X-Cache for that (free, 5 minutes)
  • Don’t generate the key from hash(body): different requests would then never get a 409, and a bug that sends the wrong body would go unnoticed