Idempotency

Retry write operations safely with `Idempotency-Key`: a retry returns the first answer.

Draft

Operations that act on the real world — vehicle commands, bookings — take an Idempotency-Key header. Retrying with the same key returns the first answer instead of running the operation again.

  • Required on POST /v1/vehicles/{vehicle_id}/commands, POST /v1/bookings and POST /v1/bookings/{booking_id}/cancel; optional (honoured when sent) on PATCH /v1/bookings/{booking_id}.
  • The key: 1 to 255 printable ASCII characters without spaces; a UUID v4 per logical operation. Keys are scoped to the connection.
  • Generate the key once per operation and store it with your own record, so a retry after a crash or timeout reuses it.

What a retry gets

  • Same key, same request, finished: the stored response with Idempotent-Replayed: true. Nothing runs again.
  • Same key, same request, still running: 409 idempotency_in_progress with Retry-After: 1.
  • Same key, different request: 409 idempotency_key_conflict; nothing runs.
  • 429 and 5xx are not stored: retry later with the same key.
  • Refusals after the key was accepted (402, 403, 404, 409, 422) are stored: fix the cause and use a new key.

To see how a command ended, poll GET /v1/commands/{command_id} — never resend it. PINs and passwords are not part of the request fingerprint: use a new key when the user corrects a PIN.