Optimistic locking
Mutations on existing bookings use
optimistic concurrency control keyed by a
monotonically-increasing version integer. The
current version travels as an ETag on reads;
PATCH callers must echo it back on If-Match.
How it works
-
GET /v1/bookings/:uidreturns the booking and anETagheader:ETag: "3"The number is the booking's current
version. It also appears in the response body asdata.version. -
PATCH /v1/bookings/:uidrequires that ETag onIf-Match:If-Match: "3" -
If the booking's current version is still
3, the patch applies and the version is bumped to4. The response carriesETag: "4". -
If someone else mutated the booking in between (so the current version is now
4), the server returns409 version_conflictand your patch is not applied:{ "error": { "code": "version_conflict", "message": "The If-Match version does not match the current booking version", "details": {}, "request_id": "req_…" } }Re-
GETthe booking, apply your change on top of the fresh version, and retry.
Error matrix
| Condition | HTTP | Code |
|---|---|---|
If-Match missing |
428 Precondition Required |
missing_if_match |
If-Match not a valid integer |
400 Bad Request |
invalid_if_match |
| Version no longer current | 409 Conflict |
version_conflict |
Weak ETags are accepted — If-Match: W/"3" is
treated the same as If-Match: "3". The version
starts at 1 on creation and increments on every
successful PATCH, cancel, or
reschedule.
What about cancel and reschedule?
POST /v1/bookings/:uid/cancel and
POST /v1/bookings/:uid/reschedule do
not require If-Match — they are
idempotent operations whose intent is unambiguous regardless
of intervening edits. They still bump the version, so a later
PATCH after a cancel must use the post-cancel ETag.
Example: read-modify-write
# 1) GET to learn the current version
curl -i -H "Authorization: Bearer $TOKEN" \
https://api.42min.us/v1/bookings/abc-def-…
# ETag: "3"
# { "data": { "uid": "abc-def-…", "version": 3, "metadata": { "crm_id": "C-7" }, … } }
# 2) PATCH with that ETag
curl -X PATCH https://api.42min.us/v1/bookings/abc-def-… \
-H "Authorization: Bearer $TOKEN" \
-H "If-Match: \"3\"" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"metadata":{"crm_id":"C-8","stage":"qualified"}}'
# → 200, ETag: "4"
Don'ts
-
Don't try to PATCH
start,end,timezone,status,event_type_id,uid, orversion— those return422 field_immutableregardless of the ETag. To move a booking, use reschedule; to end it, use cancel. - Don't cache an ETag indefinitely. The version may bump from webhooks, workflows, or the dashboard at any moment.
-
Don't try to compare ETags — they are integers, but treat
them as opaque tokens. The only safe operation is to echo
them back on
If-Match.
Last updated May 14, 2026.