Flavoso APIFundamentalsIdempotency

Idempotency

With an Idempotency-Key, a repeated POST is not carried out twice. That is how you retry safely after a network error.

Why

If your app gets no answer to a POST, it does not know whether it arrived: was the order accepted, the reservation created? Without protection, a retry creates a second reservation. With an Idempotency-Key, Flavoso answers the retry with the result of the first attempt.

How it works

  • On POST, send the Idempotency-Key header with a unique string: 1 to 255 printable ASCII characters. On PUT, PATCH and DELETE, Flavoso ignores the header.
  • The key applies per connection. Flavoso keeps the first response (status and body) for 24 hours.
  • If the same request arrives again with the same key, the first response comes back, with Idempotent-Replayed: true, and nothing happens a second time.
  • Method, path and the raw bytes of the body are compared. So a retry must send exactly the same body: even different whitespace or a different order of fields makes it a different request, and the same key with a different request gives 422 idempotency_key_reused.
  • If the first request is still running, the second gives 409 idempotency_in_progress. Wait a moment, then retry. If the first request never finished (it was aborted on our side), the key is free again after 2 minutes.
  • A response with 5xx or 409 conflict is not kept: the retry is carried out.
# Create the key ONCE per operation and keep it for every retry of that operation
KEY=$(uuidgen)
curl -X POST https://api.flavoso.com/v1/orders/ORDER_ID/accept \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $KEY"
# No answer? Send exactly the same command again, with the same $KEY.
HTTP/1.1 200 OK
Idempotent-Replayed: true
X-Request-Id: req_9a1b2c3d4e5f60718293a4b5
Content-Type: application/json

{ "object": "order", "id": "cce01f52-5188-410f-9659-6ce26ba9b784", "status": "confirmed", ... }

Good keys

The key belongs to the operation, not to the attempt. Create it once, when your program decides to do something, and use it for every retry of exactly this operation.

  • Derived from your own data: accept-<order id>, ack-<order id>, booking-<your booking number>.
  • Or a UUID, stored together with the job in your queue.
  • Never a new key per attempt: then it protects against nothing.

What can be retried anyway

  • Status changes: an order already at the target status comes back unchanged with 200, and accept returns an order that is already past pending unchanged.
  • POST /orders/{id}/acknowledge: taken over stays taken over; the same external_id again changes nothing.
  • PUT /menu, PUT /store/hours, POST /menu/availability and every PATCH: they set a target state and do not toggle. Sending one twice has the same effect as sending it once.

On POST, an Idempotency-Key still never hurts and also makes the response identical; on PUT and PATCH, Flavoso ignores it.

Still unclear? Write to support@flavoso.com and include the id from X-Request-Id. It lets us find your request in the log.