Idempotency
The public API supports an Idempotency-Key header on write endpoints (POST, PUT, PATCH). Use it for any write that’s safe to retry but unsafe to duplicate (checking out a checkin, starting a break, etc.).
How it works
Section titled “How it works”- You generate a key per logical request — a UUID is ideal — and send it in the
Idempotency-Keyrequest header. - The gateway records a tuple of caller identity plus idempotency key → the full response (status, headers we control, body).
- If the same key arrives again for the same endpoint from an equivalent caller, we return the recorded response and do not re-run the operation.
- Records expire 24 hours after the original request.
Example: a checkout retry that is safe to repeat. The siteId and
checkinId come from the URL.
curl -X PATCH https://aware-api.invalid/api/v1/sites/54321/checkins/8f5b9a4d-3c2e-4b1f-9d8a-72e6c1f0a4b3/checkout \ -H "Authorization: Bearer $AWARE_ACCESS_TOKEN" \ -H "Idempotency-Key: 8f5b9a4d-3c2e-4b1f-9d8a-72e6c1f0a4b3" \ -H "Content-Type: application/json" \ -d '{"source": "USER", "timestamp": "2026-05-12T22:15:33Z"}'const res = await fetch( 'https://aware-api.invalid/api/v1/sites/54321/checkins/8f5b9a4d-3c2e-4b1f-9d8a-72e6c1f0a4b3/checkout', { method: 'PATCH', headers: { Authorization: `Bearer ${process.env.AWARE_ACCESS_TOKEN}`, 'Idempotency-Key': '8f5b9a4d-3c2e-4b1f-9d8a-72e6c1f0a4b3', 'Content-Type': 'application/json', }, body: JSON.stringify({ source: 'USER', timestamp: '2026-05-12T22:15:33Z' }), },)- Scope. Keys are scoped per authenticated caller so two unrelated tokens cannot collide on meaning.
- Length. 1–255 characters. ASCII only.
- Endpoint match. A key is bound to the endpoint it was first used on. Reusing it on a different endpoint returns
409 Conflict. - In-flight retries. If the original request is still in flight when a retry arrives, the retry gets
409with typeIdempotencyConflict. Once the first request completes, a retry with the same key replays the stored response.
When not to use it
Section titled “When not to use it”GETrequests don’t need it — they’re already safe to retry.
Recommended pattern
Section titled “Recommended pattern”Generate the idempotency key at the edge of your system (the request handler that triggered the action), persist it alongside the work item you’re acting on, and reuse the same key across all retries of that work item:
const idempotencyKey = crypto.randomUUID()await db.insertOutboundCheckout({ idempotencyKey, checkinId, payload })
await retry(() => fetch(`/api/v1/sites/${siteId}/checkins/${checkinId}/checkout`, { method: 'PATCH', headers: { Authorization: `Bearer ${accessToken}`, 'Idempotency-Key': idempotencyKey, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }),)That way a crashed retrier still sees the same key on its next attempt.