Help API

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

  1. GET /v1/bookings/:uid returns the booking and an ETag header:

    ETag: "3"
    

    The number is the booking's current version. It also appears in the response body as data.version.

  2. PATCH /v1/bookings/:uid requires that ETag on If-Match:

    If-Match: "3"
    
  3. If the booking's current version is still 3, the patch applies and the version is bumped to 4. The response carries ETag: "4".

  4. If someone else mutated the booking in between (so the current version is now 4), the server returns 409 version_conflict and 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-GET the booking, apply your change on top of the fresh version, and retry.

Error matrix

ConditionHTTPCode
If-Match missing428 Precondition Requiredmissing_if_match
If-Match not a valid integer400 Bad Requestinvalid_if_match
Version no longer current409 Conflictversion_conflict

Weak ETags are accepted, so 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, since 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, or version, which return 422 field_immutable regardless 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.