They are not interchangeable. An idempotency key protects a record that may not exist yet; an ETag protects one that already does.
Retrying a create with ExternalId
Send your own unique id with the create. If the same id arrives again, Alvys returns the record the first call created instead of writing a second one.
The key is the request, not just the id
Reusing a key with different money is refused, not applied:
A correction is a new record, not a retry — give it a new key. An update to an existing record is a different operation entirely; see below.
Scope the key to the thing it identifies.
detention-2026-09-09 is too coarse if a trip can carry two detention charges on one day — the second is refused as a conflict. Include the stop, the event, or whatever makes this charge distinct.Choosing a key
- Stable across retries. A key regenerated on each attempt offers no protection at all. Derive it from something in your own system — an event id, a row id — not from a timestamp or a random value created at send time.
- Unique within your tenant. Two tenants may use the same string safely; two charges in one tenant may not.
- Case-sensitive, and compared after surrounding whitespace is trimmed.
ABCandabcare two different keys. - Optional. Omit it and no idempotency is offered — a retry creates a second record.
503 means retry, not fail
A 503 Service Unavailable on a keyed create means the write could not be confirmed and may already exist. Retry the identical request. Recording it as uncreated is the one response that produces a lost charge, because the record may be there.
Updating an existing record
An update carries the opposite risk: the record exists, and someone else may have changed it since you read it. That is a precondition problem, not an idempotency one, and it is handled with anETag and an If-Match header rather than a key.
See Updating Records Safely.
Using both together
A create and an update use different mechanisms, and a robust integration uses both:- Create with an
ExternalIdyou derived from your own record. A retry is safe. - Keep the
ETagfrom the create response. - Update with
If-Match. A stale validator tells you to re-read rather than silently overwriting.
ExternalId on an update does nothing — the key belongs to the create, and an update is addressed by the record id in the path.