Errors

Every error code, what caused it and what to do next.

Every response outside 2xx is one JSON object. That includes requests refused before they reach an endpoint: an unconvertible parameter (?page=abc), a missing parameter or header, malformed JSON or a value of the wrong type.

{
  "code": "SLOT_UNAVAILABLE",
  "message": "The requested time slot is no longer available. Pick another start from GET /api/v1/availability/starts.",
  "field": "scheduledStart"
}

Branch on code, never on message

code is the stable contract. message is an English sentence for logs and support. It can change wording at any time and never echoes parser internals or your raw input.

A wrong Content-Type answers 415 and a method the path does not support answers 405 (with an Allow header), both with the code INVALID_INPUT. An unknown path answers 404 NOT_FOUND, but only to a valid key. Without one, every /api/v1 request is 401 INVALID_API_KEY first, whether the path exists or not.

Request size

Every /api/v1 request body is capped at 64 KB. A larger body answers 413 FILE_TOO_LARGE ("The request body is too large (max 64 KB).") before it is read. The one exception is POST /images with a secret key, a multipart upload with a 60 MB limit.

The field an error is about

An error that concerns one input of the request also carries field: the name of that input as the reference spells it. It is a body path such as paidAt, customer.email or billing.ico, a query parameter such as fromDate, or a header such as Idempotency-Key. When the error is not about a single input, field is absent.

{ "code": "INVALID_INPUT", "message": "paidAt is required when issuing a voucher through the API.", "field": "paidAt" }

Keep branching on code. Use field to point at the input in your own UI. message is an English sentence for developers and logs, so do not show it to your customers verbatim.

Strict request bodies

Every /api/v1 write body is checked against the endpoint's schema. A property the endpoint does not define (a typo, or a field of another endpoint) is 400 UNKNOWN_FIELD, with field naming it as a path:

{ "code": "UNKNOWN_FIELD", "message": "...", "field": "customer.foo" }

Nothing is stored and the Idempotency-Key is not used up, so fix the body and retry. The one free-form object is metadata of POST /orders. PATCH /studio refuses the fields that change in the admin only (bank account, currency, allowed domains and the like) the same way instead of ignoring them.

Every code

  • INVALID_API_KEY401

    Missing, malformed, unknown or revoked key, or the studio is deleted.

    Check the key in the portal or, for a studio key, in the studio's admin. A wrong key and an unknown key look the same on purpose.

  • INSUFFICIENT_SCOPE403

    The key lacks the scope this endpoint needs. A publishable key on a scoped endpoint ends here too.

    Give the secret key the scope, or call from your server.

  • PLAN_REQUIRED403

    A studio is below the Pro subscription, or a live key of an organization's business was used before live mode was turned on.

    For a studio, subscribe to Pro and the key works again. For an organization, turn on live mode in the portal, or use a test key.

  • BILLING_SUSPENDED403

    A live organization key whose organization was suspended because the monthly charge stayed unpaid for 14 days. Test keys keep working.

    Live mode comes back with a new payment.

  • ORIGIN_NOT_ALLOWED403

    A browser request from a domain the key's owner has not allowed.

    Add the domain to the allowed websites: in the portal under Settings → Allowed websites, or with allowedDomains on PATCH /businesses/{id}. A studio does it in its admin.

  • SECRET_KEY_IN_BROWSER403

    A secret key was sent from a browser (the request carried an Origin header).

    Use a publishable key in the browser. Keep the secret key on your server.

  • DEMO_STUDIO403

    A write reached the public demo studio. Nothing was stored.

    Use a test studio for writes.

  • NOT_FOUND404

    The resource does not exist or belongs to another studio, or the path does not exist.

    Check the id and the path.

  • INVALID_INPUT400

    A parameter, header or body field is missing, malformed or out of range. 405 and 415 use this code too.

    The message names the field.

  • UNKNOWN_FIELD400

    A write request body contains a property this endpoint does not define (a typo, or a field of another endpoint). field names it, for example customer.foo. Nothing was stored and the Idempotency-Key is not used up.

    Remove or rename the field named in field and send the request again, with the same Idempotency-Key if you like.

  • INVALID_SUBJECT400

    The subject sent with an order or booking link does not fit the studio's subject type: unknown type, missing required attribute, wrong value type, a choice outside its options, or an unknown attribute.

    Read field (the attribute key, or subject.type) and compare with GET /subject-types.

  • CONFLICT409

    The request is valid but the studio's state forbids it.

    Read the message, it says which state blocks the request.

  • STUDIO_NOT_PUBLISHED409

    The studio is not published, so it has no booking data to read and takes no bookings. GET /availability/starts, GET /availability/calendar and POST /orders answer this, with a publishable or a secret key.

    Publish the studio in the admin, or use the test studio: a test studio is always bookable.

  • RATE_LIMITED429

    A burst or storefront limit was hit.

    Wait Retry-After seconds, then retry.

  • QUOTA_EXCEEDED429

    The monthly quota of a secret key is used up.

    Retry after Retry-After seconds (the next UTC month) or make fewer calls. The quota cannot be raised.

  • IDEMPOTENCY_IN_PROGRESS409

    Another request with the same Idempotency-Key is still running.

    Retry shortly with the same key.

  • IDEMPOTENCY_KEY_MISMATCH422

    The same Idempotency-Key came with a different body.

    Use a new key for a new request.

  • API_KEY_DAILY_VOUCHER_CAP_EXCEEDED422

    POST /gift-vouchers only: this key would pass its daily cap on voucher value.

    Wait for the studio's next day, or ask the owner to raise the cap. Retrying unchanged does not help.

  • CANNOT_PUBLISH_WITHOUT_SERVICES409

    A publish call (POST /catalog/publish or POST /publish) on a studio with no active service. Nothing was published.

    Create or unarchive a service, then publish again.

  • CANNOT_PUBLISH_WITHOUT_CONTACT409

    A publish call (POST /storefront/publish or POST /publish) on a studio with neither a phone nor a public e-mail. Nothing was published.

    Add a phone or a public e-mail to the studio, then publish again.

  • FILE_TOO_LARGE413

    POST /images only: the file is over the upload limit of 60 MB.

    Upload a smaller file.

  • SLOT_UNAVAILABLE409

    POST /orders only: the window was taken. Nothing was created.

    Ask GET /availability/starts again and let the customer pick another start.

  • TERM_IN_PAST409

    POST /orders/{id}/revive only: the booked term has passed or starts too soon to be honoured, so the order stays CANCELLED.

    Send the revive request again with a new scheduledStart that lies far enough in the future.

  • TERMS_VERSION_STALE409

    The studio published new terms and conditions after you loaded GET /studio, so the acceptedTermsVersion you sent is no longer current. Nothing was created and the Idempotency-Key is not used up.

    Read GET /studio again, show the customer the new terms, and resend the order with acceptedTermsVersion set to the new terms.version.

  • SERVICE_KNOWN_CARS_ONLY422

    A selected service is sold only for a car the studio already knows (orderAudience KNOWN_CARS) and the order does not prove one: no knownCarToken, an invalid or expired one, or a car without a completed order. Nothing was created.

    Send a valid knownCarToken from the studio's return reminder, or drop that service from the order.

  • ADDON_SOLD_ONLY_WITH422

    A selected add-on is sold only together with certain services (soldOnlyWithServiceIds) and none of them is in the order. Nothing was created.

    Add one of the services the add-on is sold with, or drop the add-on from the order.

  • PENDING_ORDERS_LIMIT429

    The studio confirms orders manually and already has 10 unconfirmed orders from the API, so the publishable key's next order is refused. Secret keys and studios that confirm automatically have no such cap.

    Wait until the studio confirms or cancels some of the pending orders, then retry. Retry-After does not apply; do not loop.

  • PDF_UNAVAILABLE503

    The voucher PDF could not be rendered right now.

    Retry.

  • INTERNAL_ERROR500

    Something went wrong on our side.

    Retry shortly.

Retrying

Retry INTERNAL_ERROR and PDF_UNAVAILABLE shortly. Wait Retry-After seconds on RATE_LIMITED and QUOTA_EXCEEDED. For writes, retry with the same Idempotency-Key so the write happens once; see Idempotency. Do not retry the other codes unchanged: the request has to change first.

On this page