Retry writes safely

Make every create safe to retry without double-charging.

Supported create calls and PaymentIntent transitions can carry an Idempotency-Key. Reuse the same key for one logical operation. Reusing it with a different body, endpoint, or PaymentIntent returns 400 idempotency_error without running the second operation.

$KEY=$(uuidgen)
$curl https://api.fluveo.dev/v1/payment_intents \
> -u sk_test_123: \
> -H "Idempotency-Key: $KEY" \
> -d amount=4242 \
> -d currency=usd
$# Retry the same request with the same $KEY to get the original response back.

Derive the key from your own operation id (an order id, a job id) so a retry after a timeout reuses it deterministically. A PaymentIntent transition that is still active or has an ambiguous outcome returns 409 idempotency_error with Retry-After; wait that many seconds and retry with the same key. Fluveo will not dispatch the transition twice.

Completed PaymentIntent transition snapshots remain replayable for at least 24 hours. The exact JSON response is encrypted at rest and capped at 64 KiB. If a stale claim needs crash recovery, Fluveo synchronizes processor state but returns 409 rather than freezing a potentially racing read as the original response. Keep retrying the same key; do not start the operation with a new key while the original outcome is ambiguous.

Create requests use deterministic object identity rather than the transition snapshot store. A create-side 5xx api_error remains indeterminate and may be retried against the same key and object — see Errors.