TattooBookingDevelopers

Errors

The TattooBooking API returns errors as RFC 9457problem+json — a stable, well-defined schema that's easier to consume than ad-hoc error envelopes.

Error envelope

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json

{
  "type": "/errors/validation_failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "email must be a valid email address",
  "code": "validation_failed",
  "instance": "/v1/clients"
}
  • type — URI reference identifying the error class
  • title — short human-readable summary
  • status — HTTP status code (matches the response status)
  • detail — human-readable explanation specific to this occurrence
  • code — machine-readable error code (the one you switch on)
  • instance — URI of the specific endpoint that errored

Some errors include extra fields. For example, a 403 fromrequireScope includes required_scopes and granted_scopes so you know what to fix.

Status code reference

StatusMeaningAction
400Bad request (malformed)Fix client; not retryable.
401Auth missing/invalidCheck the bearer token.
403Forbidden — scope, plan, or IPRead code + extra.
404Not foundCross-tenant resources also return 404.
409Conflict (duplicate, racing update)Reconcile; not retryable.
422Validation failedFix the payload.
429Rate limitedWait and retry — see Retry-After header.
500Server errorRetry with exponential backoff.
503Service unavailable (Redis, etc.)Retry.

Common codes

The code field is the stable contract — switch on this in code, not on title or detail:

  • missing_api_key, invalid_api_key, revoked_api_key, expired_api_key, inactive_api_key, ip_not_allowed
  • invalid_access_token, revoked_access_token, expired_access_token, revoked_grant, app_suspended
  • insufficient_scope — auth ok, but the key/grant lacks the required scope
  • plan_limit_reached — the tenant's plan caps this resource (also: feature_not_available)
  • validation_failed, validation_error, invalid_cursor, invalid_id — some endpoints report simple 400 field problems as validation_error; treat both validation codes the same way
  • rate_limit_exceeded — see Retry-After
  • duplicate_email — POST /v1/clients with an email that already exists; the body includes existing_id so you can reconcile
  • conflict — the update conflicts with the resource's current state (409). Example: changing an appointment's status away from CANCELLED/NO_SHOW while a charged cancellation fee exists — refund the fee first. Not retryable without changing state.
  • resource_not_found

Validation errors

Validation failures return 422 with detail explaining which field failed and why. If multiple fields fail, the response lists them in extra.errors.

{
  "type": "/errors/validation_failed",
  "title": "Validation failed",
  "status": 422,
  "code": "validation_failed",
  "extra": {
    "errors": [
      { "path": "email", "message": "must be a valid email address" },
      { "path": "budget_range_min", "message": "must be ≥ 0" }
    ]
  }
}