Help API

    Errors

    Every error response — including auth failures, rate-limit responses, and validation errors — has this shape:

    {
      "error": {
        "code": "insufficient_scope",
        "message": "This action requires the 'bookings:create' scope",
        "details": { "required_scope": "bookings:create" },
        "request_id": "req_…"
      }
    }
    
    • code — stable machine identifier. Switch on this, not on message.
    • message — human-readable explanation. Wording may change.
    • details — endpoint-specific extra fields (e.g. the offending parameter name, or the required scope). May be empty {}.
    • request_id — unique per request. Quote this when reporting an issue.

    The HTTP status is set per RFC 7231 — switch on it for routing (5xx ⇒ retry, 4xx ⇒ fix the request) and use code for granular handling.

    Common error codes

    Authentication (401)

    Code Meaning
    invalid_token Missing, malformed, or unknown bearer token.
    token_expired Token is past its expiry.
    token_revoked PAT or OAuth token has been revoked.

    These responses also include WWW-Authenticate: Bearer realm="42min", error="…" — useful for clients that follow the RFC 6750 challenge protocol.

    Authorization (403)

    Code Meaning
    insufficient_scope Token is valid but missing the required scope. details.required_scope names which one.
    forbidden Generic refusal — auth and scope are fine, but the actor isn't allowed to do this.

    Validation (400 / 422)

    Code Meaning
    validation_error Request body failed validation.
    invalid_request The request itself is malformed (bad headers, bad shape).
    invalid_query_param A query parameter is missing or malformed. details.param names which one.
    attendee_email_invalid attendee.email failed format check.
    invalid_if_match If-Match is not a valid integer.
    field_immutable A PATCH tried to write a field that can only change via dedicated endpoints (e.g. start). details.fields lists them.
    event_type_disallows_reschedule The event type has disableRescheduling.

    Conflict / state (409)

    Code Meaning
    slot_unavailable Requested slot is no longer free.
    event_type_inactive Event type's status is not on.
    booking_in_past Booking starts (or started) in the past.
    booking_already_cancelled Reschedule attempted on a non-confirmed booking.
    version_conflict If-Match doesn't match the current booking version.
    idempotency_in_progress Same Idempotency-Key still being processed. Retry-After: 1.
    idempotency_key_conflict Same key, different body within the 24h window.
    pat_name_taken Another PAT in this account has the same name.
    pat_limit_exceeded Account has 42 active PATs already.

    Not found (404)

    Code Meaning
    not_found Generic.
    event_type_not_found Event type doesn't exist or is in another account.
    booking_not_found Booking doesn't exist, was hard-deleted, or its UID is malformed.
    interaction_not_found OAuth consent interaction expired or doesn't exist.

    We deliberately collapse "wrong tenant" into not_found — a 404 doesn't leak the existence of resources in other accounts.

    Precondition / payload (412 / 413 / 415 / 428)

    Code Meaning
    missing_if_match PATCH without If-Match. (428 Precondition Required.)
    missing_idempotency_key Write without Idempotency-Key. (400.)
    invalid_idempotency_key Idempotency-Key longer than 255 chars. (400.)

    Rate-limiting (429)

    Code Meaning
    rate_limited Bucket exhausted. Retry-After header set; see Rate limits.

    OAuth (400 / 401)

    Code Meaning
    invalid_client Bad client_id / client_secret, or unknown client.
    invalid_grant Bad auth code, bad refresh token, PKCE failure, redirect-URI mismatch, or replay detected.
    invalid_scope Requested scope not allowed for this client, or unknown scope name.
    invalid_redirect_uri redirect URI is not registered or fails scheme rules.
    unsupported_grant_type grant_type is not authorization_code or refresh_token.
    unsupported_response_type response_type is not code.
    invalid_client_metadata DCR request rejected (scope not in allowlist, etc.).
    access_denied User declined on the consent screen. Returned via redirect, not a JSON body.

    Server (5xx)

    Code Meaning
    internal_error Something went wrong server-side. Quote request_id to support.
    slot_lock_timeout Could not acquire the per-slot lock when creating/rescheduling a booking. Retry-After: 1. (503.)
    1. 5xx or network failure — retry with the same Idempotency-Key after a brief delay (exponential backoff, capped). Writes are safe to retry as long as the key stays the same.
    2. 429 — wait for Retry-After or X-RateLimit-Reset, then retry.
    3. 401 token_expired — refresh (OAuth) or rotate (PAT). For OAuth, if the refresh attempt itself returns invalid_grant with "session has been revoked", start the authorize flow from scratch.
    4. 409 version_conflict — re-GET and reapply your patch on the new version.
    5. 409 slot_unavailable — the slot was taken between your check and your create. Pick another slot (the booking page or /v1/slots will reflect the new state).
    6. 4xx other — surface to the user; usually a bug in the request.

    Always log request_id from error.request_id (or meta.request_id on success) — it's the fastest way for support to trace what happened.