Skip to main content
The Idempotency-Key header is specified but not yet read from the HTTP request in v1. The checkout endpoint generates idempotency keys internally; the refund and cancel endpoints do not currently pass idempotency keys to Stripe at all. This page documents the intended contract so integrations can be written to support the header once it is enforced. Do not rely on client-supplied key deduplication in the current release.
Network failures between a client and the API can leave the outcome ambiguous: did the charge succeed, or not? Retrying a failed request without coordination may cause a double-charge. The Idempotency-Key header is the planned mechanism to let you safely retry any money-side POST without that risk.

Money endpoints this header will apply to

These endpoints perform or reverse a financial transaction:
MethodPathOperation
POST/api/v1/hub/{hub_id}/checkoutStart a checkout session (paid or free)
POST/api/v1/teams/{team_id}/hubs/{hub_id}/payments/{payment_id}/refundRefund a payment
POST/api/v1/teams/{team_id}/hubs/{hub_id}/subscriptions/{sub_id}/cancelCancel a subscription (admin)
POST/api/v1/hub/{hub_id}/me/subscriptions/{sub_id}/cancelCancel own subscription (member)
All other routes (read, list, update, delete) are either idempotent by nature or do not touch money, so Idempotency-Key will not apply there.

Planned key format

Any sufficiently random string up to 255 characters. A UUIDv4 or UUIDv7 is the recommended format:
Idempotency-Key: 018f4b3c-1234-7abc-8def-000000000099
Generate a fresh key for each new attempt at a distinct operation. Do not reuse a key for a different operation or a different amount — the key is intended to be tied to the exact request.

Intended retry semantics (planned)

Once the header is enforced, the intended behavior is:
  1. Generate a key before sending the request.
  2. If the request times out or you receive a network error (not an HTTP error response), reuse the same key and retry.
  3. If you receive an HTTP error with a body (4xx or 5xx), the request reached the server. Inspect the response:
    • 4xx — do not retry with the same key; the error is client-side.
    • 5xx — you may retry with the same key; the server will deduplicate.
  4. A repeated request with the same key will return the same response without double-charging.

Double-charge prevention pattern (prepare now)

Write your checkout integration to generate and attach a key even before the header is enforced:
# Generate a key before the first attempt
KEY=$(uuidgen | tr '[:upper:]' '[:lower:]')

# Attach it on every attempt — safe to send today (ignored for now)
curl -X POST "$MIO_BASE_URL/api/v1/hub/$HUB_ID/checkout" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Authorization: Bearer <contact-token>" \
  -H "Idempotency-Key: $KEY" \
  -d '{
    "data": {
      "type": "checkout_sessions",
      "attributes": {
        "price_id": "price_abc123",
        "success_url": "https://app.example.com/success",
        "cancel_url": "https://app.example.com/cancel"
      }
    }
  }'
Sending the header before enforcement is harmless — it is ignored. Once enforcement lands, your integration will get deduplication without any code change.

Key lifetime (planned)

Keys will be scoped to the team that owns the hub. Hubs under different teams have separate key namespaces, so the same key string used for hub A (team X) does not conflict with the same string used for hub B (team Y).