> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fitsociety.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Error reference

> Complete reference of Public API error keys: framework keys, endpoint validation keys, HTTP statuses, meanings, and how to resolve each error.

Every Public API bearer error uses the error envelope documented on the
[contracts page](/public-api/contracts#error-envelopes): an `error` object with
`code` (HTTP status), `key` (machine-readable key), `message` (human-readable
text), optional `details`, and a `meta.requestId`.

Match client logic on the exact `error.key` string, never on `error.message`.
Messages may be reworded or translated; keys are stable.

`error.key` values come in two families:

* **Framework keys** are dotted lowercase (`auth.invalid_token`,
  `rate_limit.exceeded`). They are emitted by the shared Public API plumbing:
  authentication, scopes, rate limiting, idempotency, routing, and server
  errors. They can occur on any bearer endpoint.
* **Endpoint validation keys** are `UPPER_SNAKE`
  (`PUBLIC_API_INVALID_CLIENT_ID`, `CLIENT_NOT_FOUND`). They are emitted by
  endpoint request validation and domain checks, so each key only occurs on the
  endpoints that use the underlying resource.

## Framework keys

`403 auth.provider_unavailable` means Public API access is currently unavailable
for the token's company. Check the provider's global status and company
allowlist with the platform administrator. An unexpired token cannot bypass
this restriction; requesting another token does not restore disabled access.

| Key | HTTP status | Meaning | How to resolve |
| :- | :- | :- | :- |
| `auth.missing_bearer` | 401 | The `Authorization` header is missing or is not a Bearer token. | Send `Authorization: Bearer <access_token>`. |
| `auth.invalid_token` | 401 | The access token is malformed, expired, or revoked. | Request a new token from `POST /public/v1/oauth/token`. |
| `auth.invalid_client` | 401 | The OAuth client behind the token no longer exists or is disabled. | Check the API client status in the coach portal, or create a new client. |
| `auth.missing_context` | 401 | The token carries no usable company context. | Request a new token. Contact support when the issue persists. |
| `scopes.insufficient` | 403 | The token is missing a scope required by this endpoint. | Request a token that includes every scope the endpoint page documents. |
| `scopes.health_consent_required` | 403 | The endpoint requires a health-consent-gated scope, but the API client was created without the health data consent. | Have a coach recreate the API client with `"consents": { "healthData": true }`. |
| `scopes.private_communication_consent_required` | 403 | The endpoint requires a private-communication-gated scope, but the API client was created without that consent. | Have a coach recreate the API client with `"consents": { "privateCommunication": true }`. |
| `rate_limit.exceeded` | 429 | The per-client rate limit was exceeded. | Wait `Retry-After` seconds (also in `meta.rateLimit.retryAfterSeconds`) and retry. |
| `idempotency.required` | 400 | A write request is missing the `Idempotency-Key` header. | Send a stable `Idempotency-Key` on every `POST`, `PUT`, `PATCH`, and `DELETE`. |
| `idempotency.invalid` | 400 | The `Idempotency-Key` is empty or longer than 200 characters. | Use a non-empty key of at most 200 characters. |
| `idempotency.conflict` | 409 | The same key was reused with a different method, path, query, or body. | Use a new key for a new request; reuse a key only for exact retries. |
| `idempotency.in_progress` | 409 | The first request with this key is still processing. | Wait briefly and retry with the same key. |
| `resource.not_found` | 404 | No route matches the requested path. | Check the URL path and HTTP method against the endpoint documentation. |
| `request.failed` | varies | Generic fallback when no specific key applies. | Inspect the HTTP status and `error.message`. |
| `webhook.request_invalid` | 400 | Generic fallback for invalid webhook management requests. | Check the request against the [webhooks page](/public-api/webhooks). |
| `server.internal_error` | 500 | An unexpected Public API server error occurred. | Retry later. Report `meta.requestId` to support when the issue persists. |

## Endpoint validation keys

Endpoint validation keys use `UPPER_SNAKE`. The tables below list every key the
Public API can emit. `PUBLIC_API_*` keys are Public API specific; the domain
keys in the second table are shared with internal validation logic but are just
as stable.

### PUBLIC*API*\* keys

| Key | HTTP status | Meaning | How to resolve |
| :- | :- | :- | :- |
| `PUBLIC_API_AUDIT_LOG_NOT_FOUND` | 404 | Audit log entry was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_AUDIT_STORE_UNAVAILABLE` | 500 | The audit store is currently unavailable. | Retry later. Contact support when the issue persists. |
| `PUBLIC_API_AVAILABILITY_SLOT_NOT_BOOKABLE` | 409 | This availability slot can no longer be booked. | Fetch the current resource state and adjust the request. |
| `PUBLIC_API_BOOKING_REQUEST_NOT_FOUND` | 404 | Booking request was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_BOOKING_REQUEST_NOT_PENDING` | 400 | Booking request is no longer pending. | Fetch the current resource state and adjust the request. |
| `PUBLIC_API_CHARGEBACK_NOT_FOUND` | 404 | Chargeback was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_CLIENT_EMAIL_REQUIRED_FOR_INVITE` | 400 | An email address is required to invite this client. | Include the missing field or context in the request. |
| `PUBLIC_API_CLIENT_NOT_FOUND` | 404 | Client was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_CLIENT_PRODUCT_NOT_FOUND` | 404 | Client product was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_COACH_NOT_FOUND` | 404 | Coach was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_COACH_REQUIRED` | 400 | A coach is required for this request. | Include the missing field or context in the request. |
| `PUBLIC_API_COMPANY_NOT_FOUND` | 404 | Company was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_COMPANY_POLICIES_NOT_FOUND` | 404 | Company policies were not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_CUSTOM_FIELD_VALUES_REQUIRED` | 400 | Provide at least one custom field value. | Include the missing field or context in the request. |
| `PUBLIC_API_DATE_RANGE_ORDER_INVALID` | 400 | The end date must be on or after the start date. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_DATE_RANGE_REQUIRED` | 400 | Provide both a start date and an end date. | Include the missing field or context in the request. |
| `PUBLIC_API_DATE_RANGE_TOO_LARGE` | 400 | The requested date range is too large. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_DOCUMENT_FOLDER_NOT_FOUND` | 404 | Document folder was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_DOCUMENT_NAME_REQUIRED` | 400 | Enter a document name. | Include the missing field or context in the request. |
| `PUBLIC_API_DOCUMENT_NOT_FOUND` | 404 | Document was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_DOCUMENT_NOTHING_TO_UPDATE` | 400 | Update at least one document field. | Include at least one updatable field in the request body. |
| `PUBLIC_API_DOCUMENT_TYPE_REQUIRED` | 400 | Enter a document type. | Include the missing field or context in the request. |
| `PUBLIC_API_DOCUMENT_URL_INVALID` | 400 | Enter a valid document URL. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_ERROR` | 400, 403, 404, or 409 | The Public API request failed. | Generic fallback. Inspect the HTTP status and `meta.requestId`, and contact support when the cause is unclear. |
| `PUBLIC_API_EVENT_TEMPLATE_DURATION_REQUIRED` | 400 | Enter an event template duration. | Include the missing field or context in the request. |
| `PUBLIC_API_EVENT_TEMPLATE_NAME_REQUIRED` | 400 | Enter an event template name. | Include the missing field or context in the request. |
| `PUBLIC_API_EVENT_TEMPLATE_NOT_FOUND` | 404 | Event template was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_EVENT_TYPE_NAME_REQUIRED` | 400 | Enter an event type name. | Include the missing field or context in the request. |
| `PUBLIC_API_EVENT_TYPE_NOT_FOUND` | 404 | Event type was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_FIELD_TOO_LONG` | 400 | One of the provided fields exceeds its maximum length. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_HEALTH_CONSENT_REQUIRED` | 400 | The requested scopes include health data, but the health data consent was not accepted. | Emitted by the coach-app client creation endpoint. Include `"consents": { "healthData": true }` when granting health-gated scopes. |
| `PUBLIC_API_IDEMPOTENCY_PERSISTENCE_FAILED` | 500 | The idempotency record could not be stored. | Retry the request with the same `Idempotency-Key`. Contact support when the issue persists. |
| `PUBLIC_API_INVALID_ACCESS_ZONES` | 400 | Access zones are invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_ATTENDANCE_STATUS` | 400 | Attendance status is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_AUDIT_LOG_ID` | 400 | Audit log id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_BOOKING_REQUEST_ID` | 400 | Booking request id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_BOOKING_REQUEST_STATUS` | 400 | Booking request status is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_BOOLEAN` | 400 | Provide a valid boolean value. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_CALENDAR_EVENT_ID` | 400 | Calendar event id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_CANCELLATION_TIMING` | 400 | Cancellation timing is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_CAPACITY_ACTION` | 400 | Capacity action is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_CHARGEBACK_ID` | 400 | Chargeback id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_CLIENT_ID` | 400 | Client id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_CLIENT_PRODUCT_ID` | 400 | Client product id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_COACH_ID` | 400 | Coach id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_COORDINATES` | 400 | Coordinates are invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_CURRENCY` | 400 | Currency is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_DATE` | 400 | Provide a valid date. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_DATE_RANGE` | 400 | Provide a valid date range. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_DOCUMENT_FOLDER_ID` | 400 | Document folder id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_DOCUMENT_ID` | 400 | Document id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_ENUM` | 400 | One of the provided fields has an unsupported value. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_FIELD_TYPE` | 400 | One of the provided fields has an invalid type. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_FORM_TYPE` | 400 | Form type is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_GOAL_DATE` | 400 | Goal date is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_GOAL_ENUM` | 400 | One of the goal fields has an unsupported value. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_GOAL_NUMBER` | 400 | One of the goal fields has an invalid number. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_INSTANCE_DATE` | 400 | Instance date is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_INTEGER` | 400 | Provide a valid integer value. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_INVOICE_ID` | 400 | Invoice id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_INVOICE_TYPE` | 400 | Invoice type is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_LOCATION_ID` | 400 | Location id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_LOCATION_TYPE` | 400 | Location type is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_NUMBER` | 400 | Provide a valid number. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_PAUSE_WINDOW` | 400 | Pause window is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_PAYMENT_METHOD` | 400 | Payment method is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_PAYMENT_REQUEST_ID` | 400 | Payment request id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_PRODUCT_ID` | 400 | Product id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_PRODUCT_TYPE` | 400 | Product type is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_RECURRING_BOOKING_ID` | 400 | Recurring booking id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_RECURRING_END_DATE` | 400 | Recurring end date is invalid. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVALID_SUBSCRIPTION_ID` | 400 | Subscription id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVALID_TRANSACTION_ID` | 400 | Transaction id is invalid. | Send a valid identifier as documented for the endpoint. |
| `PUBLIC_API_INVOICE_MESSAGE_NOT_ALLOWED` | 400 | An invoice message is not allowed for this invoice. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_INVOICE_NOT_FOUND` | 404 | Invoice was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_LOCATION_NAME_REQUIRED` | 400 | Enter a location name. | Include the missing field or context in the request. |
| `PUBLIC_API_LOCATION_NOT_FOUND` | 404 | Location was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_NO_FIELDS_TO_UPDATE` | 400 | Update at least one field. | Include at least one updatable field in the request body. |
| `PUBLIC_API_PAYMENT_REQUEST_NOT_FOUND` | 404 | Payment request was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_PRICE_FIELDS_NOT_ALLOWED` | 400 | Price fields cannot be updated through this endpoint. | Send a value that matches the documented format and limits. |
| `PUBLIC_API_PRIVATE_COMM_CONSENT_REQUIRED` | 400 | The requested scopes include private communication, but that consent was not accepted. | Emitted by the coach-app client creation endpoint. Include `"consents": { "privateCommunication": true }` when granting private-communication-gated scopes. |
| `PUBLIC_API_PRODUCT_ALREADY_EXISTS` | 409 | A product with this name already exists. | Fetch the current resource state and adjust the request. |
| `PUBLIC_API_PRODUCT_NOT_FOUND` | 400 or 404 | Product was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_TRANSACTION_NOT_FOUND` | 404 | Transaction was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_PRODUCT_REVOKE_NOT_SUPPORTED` | 400 | This product type cannot be revoked. | See the message and endpoint documentation for details. |
| `PUBLIC_API_PRODUCT_VALIDATION_FAILED` | 400 | Product validation failed. | See the message and endpoint documentation for details. |
| `PUBLIC_API_RECURRING_BOOKING_ALREADY_CANCELLED` | 400 | Recurring booking is already cancelled. | Fetch the current resource state and adjust the request. |
| `PUBLIC_API_RECURRING_BOOKING_NOT_FOUND` | 404 | Recurring booking was not found. | Check that the id exists and belongs to the authenticated company. |
| `PUBLIC_API_RECURRING_END_MODE_CONFLICT` | 400 | Provide either a recurring end date or an occurrence count, not both. | Send only one of the two end-mode fields. |
| `PUBLIC_API_REQUIRED_FIELDS` | 400 | One or more required fields are missing. | Include the missing field or context in the request. |
| `PUBLIC_API_UNKNOWN_FIELDS` | 400 | The request contains unknown fields. | Remove undocumented fields from the request body. |
| `PUBLIC_API_UNKNOWN_GOAL_FIELDS` | 400 | The request contains unknown goal fields. | Remove undocumented fields from the request body. |
| `PUBLIC_API_UNSUPPORTED_PRODUCT_TYPE` | 400 | This product type is not supported. | Send a value that matches the documented format and limits. |

### Domain keys

| Key | HTTP status | Meaning | How to resolve |
| :- | :- | :- | :- |
| `ASSIGNED_COACH_REQUIRED` | 400 | assignedCoach is required | Include the missing field or context in the request. |
| `CHECKUP_CUSTOM_START_DATE_REQUIRED` | 400 | Start date required for custom schedule type | Include the missing field or context in the request. |
| `CHECKUP_INVALID_OR_MISSING_MONTHLY_DAY` | 400 | Invalid or missing monthly(day) schedule type | Send a value that matches the documented format and limits. |
| `CHECKUP_INVALID_OR_MISSING_MONTHLY_WEEK` | 400 | Invalid or missing monthly(week) schedule type | Send a value that matches the documented format and limits. |
| `CHECKUP_INVALID_OR_MISSING_WEEKLY_ON` | 400 | Invalid or missing weekly schedule type | Send a value that matches the documented format and limits. |
| `CHECKUP_INVALID_REPEAT_EVERY` | 400 | Invalid repeat interval for custom schedule type | Send a value that matches the documented format and limits. |
| `CHECKUP_SETTING_NOT_FOUND` | 404 | Checkup setting not found | Check that the id exists and belongs to the authenticated company. |
| `CLIENT_ALREADY_EXISTS` | 409 | An account with this email already exists. Please log in to continue. | Fetch the current resource state and adjust the request. |
| `CLIENT_ALREADY_EXISTS_IN_COMPANY` | 409 | This Client Already Exists in your company | Fetch the current resource state and adjust the request. |
| `CLIENT_NOT_FOUND` | 400 or 404 | Client not found | Check that the id exists and belongs to the authenticated company. |
| `CLIENT_REGISTRATION_REQUEST_NOT_FOUND` | 404 | Client registration request not found. | Check that the id exists and belongs to the authenticated company. |
| `COACH_ID_REQUIRED` | 400 | Coach ID is required | Include the missing field or context in the request. |
| `COACH_NOT_FOUND` | 404 | Coach not found | Check that the id exists and belongs to the authenticated company. |
| `COMPANY_ID_REQUIRED` | 400 | companyId is required. | Include the missing field or context in the request. |
| `COMPANY_MCP_GOALS_NOT_FOUND` | 404 | No goals were found for this client. | Check that the id exists and belongs to the authenticated company. |
| `COMPANY_MCP_INVALID_CLIENT_ID` | 400 | Client id is invalid. | Send a valid identifier as documented for the endpoint. |
| `COMPANY_MCP_SUBSCRIPTION_NOT_FOUND` | 404 | Subscription was not found. | Check that the id exists and belongs to the authenticated company. |
| `COMPANY_NOT_FOUND` | 404 | Company not found | Check that the id exists and belongs to the authenticated company. |
| `CREDENTIAL_VALUE_REQUIRED` | 400 | credentialValue is required | Include the missing field or context in the request. |
| `CREDIT_PACK_VALIDITY_REQUIRED` | 400 | Credit packs require a positive validity period before credits can be issued | Include the missing field or context in the request. |
| `DATE_REQUIRED` | 400 | date is required | Include the missing field or context in the request. |
| `DEVICE_NOT_AUTHORIZED` | 401 | Device not authorized | Check the device key used for the access endpoint. |
| `EMAIL_REQUIRED` | 400 | Email is required | Include the missing field or context in the request. |
| `ENTRY_AFTER_HABIT_END_DATE` | 400 | Entry is after habit end date | Log the entry within the habit's active date range. |
| `ENTRY_BEFORE_HABIT_START_DATE` | 400 | Entry is before habit start date | Log the entry within the habit's active date range. |
| `FIRST_NAME_MAX_50` | 400 | First name cannot be longer than 50 characters. | Send a value that matches the documented format and limits. |
| `FIRST_NAME_MIN_2` | 400 | First name must be at least 2 characters long. | Send a value that matches the documented format and limits. |
| `FIRST_NAME_REQUIRED` | 400 | First name is required | Include the missing field or context in the request. |
| `FORM_NOT_FOUND` | 400 or 404 | Form not found. | Check that the id exists and belongs to the authenticated company. |
| `HABIT_CAN_ONLY_BE_LOGGED_ON_SPECIFIC_DAYS` | 400 | This habit can only be logged on: `{{days}}` | Log the entry on one of the habit's scheduled days. |
| `HABIT_ENTRY_NOT_FOUND` | 404 | Habit Entry not found | Check that the id exists and belongs to the authenticated company. |
| `HABIT_NOT_FOUND` | 404 | Habit not found | Check that the id exists and belongs to the authenticated company. |
| `INBODY_INSTALLATION_NOT_FOUND` | 404 | InBody installation was not found. | Check that the id exists and belongs to the authenticated company. |
| `INBODY_WEBHOOK_SECRET_INVALID` | 401 | InBody webhook secret is invalid. | Send a value that matches the documented format and limits. |
| `INVALID_CHECKUP_SCHEDULE_TYPE` | 400 | Invalid checkup form schedule type | Send a value that matches the documented format and limits. |
| `INVALID_CHECKUP_SETTING_ID` | 400 | Invalid checkup setting id | Send a valid identifier as documented for the endpoint. |
| `INVALID_COACH_ID` | 400 | Invalid coach | Send a valid identifier as documented for the endpoint. |
| `INVALID_CREDENTIAL_TYPE` | 400 | credentialType is not supported | Send a value that matches the documented format and limits. |
| `INVALID_CURSOR` | 400 | Pagination cursor is invalid. | Send a valid identifier as documented for the endpoint. |
| `INVALID_EMAIL` | 400 | Invalid email format | Send a value that matches the documented format and limits. |
| `INVALID_FORM_ID` | 400 | Invalid form id | Send a valid identifier as documented for the endpoint. |
| `INVALID_HABIT_ENTRY_ID` | 400 | Invalid Habit Entry ID | Send a valid identifier as documented for the endpoint. |
| `INVALID_HABIT_GOAL_PERIOD` | 400 | Habit goal period is invalid. | Send a value that matches the documented format and limits. |
| `INVALID_HABIT_ID` | 400 | Invalid Habit ID | Send a valid identifier as documented for the endpoint. |
| `INVALID_JSON_PAYLOAD` | 400 | Invalid JSON payload. | Send a value that matches the documented format and limits. |
| `INVALID_MEASUREMENT_ENTRY_ID` | 400 | Invalid measurementEntryId | Send a valid identifier as documented for the endpoint. |
| `INVALID_MEASUREMENT_TYPE_ID` | 400 | Invalid measurement type id | Send a valid identifier as documented for the endpoint. |
| `INVALID_MEASUREMENTTYPEID` | 400 | Invalid measurementTypeId | Send a value that matches the documented format and limits. |
| `INVALID_PROGRESS_PHOTO_ID` | 400 | Progress photo id is invalid. | Send a valid identifier as documented for the endpoint. |
| `INVALID_PROGRESS_PHOTO_ORIENTATION` | 400 | Progress photo orientation is invalid. | Send a value that matches the documented format and limits. |
| `INVALID_ROLE_SPECIFIED` | 400 | Invalid role specified. Valid roles are: `{{roles}}` | Send a value that matches the documented format and limits. |
| `INVALID_UNIT` | 400 | Invalid unit | Send a value that matches the documented format and limits. |
| `INVALID_UNIT_FOR_MEASUREMENT` | 400 | Unit `{{UNIT}}` is not allowed for measurement `{{MEASUREMENT}}`. Allowed units: `{{ALLOWED_UNITS}}` | Send a value that matches the documented format and limits. |
| `LAST_NAME_MAX_50` | 400 | Last name cannot exceed 50 characters | Send a value that matches the documented format and limits. |
| `MAXIMUM_ALLOWED_VALUE_EXCEEDED` | 400 | Maximum allowed value is `{{max}}` | Send a value that matches the documented format and limits. |
| `MEASUREMENT_ENTRY_NOT_FOUND` | 404 | Measurement entry not found | Check that the id exists and belongs to the authenticated company. |
| `MEASUREMENT_TYPES_NOT_FOUND` | 404 | Measurement types not found | Check that the id exists and belongs to the authenticated company. |
| `MOBILE_APP_RELEASE_WEBHOOK_UNAUTHORIZED` | 401 | Mobile app release webhook is not authorized. | Check the credentials used for this integration. |
| `NOTE_MAX_LENGTH` | 400 | Note cannot exceed `{{MAX}}` characters | Send a value that matches the documented format and limits. |
| `NOTHING_TO_UPDATE` | 400 | Nothing to update - provide at least one field. | Include at least one updatable field in the request body. |
| `OCCURRED_AT_INVALID_FORMAT` | 400 | occurredAt must be ISO (YYYY-MM-DDTHH:MM:SS.000Z) | Send a value that matches the documented format and limits. |
| `OCCURRED_AT_REQUIRED` | 400 | occurredAt is required | Include the missing field or context in the request. |
| `PDF_NOT_AVAILABLE` | 404 | No PDF is available for this resource. | The invoice has no generated PDF yet. The Public API does not generate missing PDFs on read. |
| `PROGRESS_PHOTO_NOT_FOUND` | 404 | Progress photo was not found. | Check that the id exists and belongs to the authenticated company. |
| `REASON_REQUIRED` | 400 | A reason is required. | Include the missing field or context in the request. |
| `SCAN_ID_REQUIRED` | 400 | scanId is required | Include the missing field or context in the request. |
| `TAG_NOT_FOUND` | 400 or 404 | No tag found with the provided ID. | Check that the id exists and belongs to the authenticated company. |
| `TV_DASHBOARD_ACTIVE_SESSION_EXISTS` | 409 | A TV is already paired. Disconnect it first before pairing a new screen | Disconnect the paired screen before pairing a new one. |
| `TV_DASHBOARD_SESSION_INVALID` | 400 | TV dashboard session is invalid | Send a value that matches the documented format and limits. |
| `TV_DASHBOARD_SESSION_NOT_FOUND` | 404 | TV dashboard session was not found or has expired | Check that the id exists and belongs to the authenticated company. |
| `VALID_NUMERIC_VALUE_REQUIRED` | 400 | Valid numeric value is required | Include the missing field or context in the request. |
| `VALUE_REQUIRED` | 400 | value is required | Include the missing field or context in the request. |
| `WISHLIST_INTAKE_INVALID_PAYLOAD` | 400 | Wishlist intake payload is invalid | Send a value that matches the documented format and limits. |
| `WISHLIST_INTAKE_ROUTING_CONTEXT_MISSING` | 422 | We could not link this wishlist intake item to an internal support ticket. | Contact support; the intake could not be routed internally. |

## OAuth token endpoint errors

`POST /public/v1/oauth/token` does not use the bearer error envelope. It
returns standard OAuth 2.0 (RFC 6749) error responses:

| Error code | HTTP status | Meaning |
| :- | :- | :- |
| `invalid_request` | 400 | The token request is malformed or missing parameters. |
| `invalid_client` | 401 | Unknown client ID or wrong client secret. |
| `unauthorized_client` | 403 | The client is disabled or not allowed to use this grant. |
| `unsupported_grant_type` | 400 | Only `client_credentials` is supported. |
| `invalid_scope` | 400 | A requested scope is unknown or not granted to this client. |
| `server_error` | 500 | Unexpected error while issuing the token. |

See the [authentication page](/public-api/authentication) for the token request
and response shape.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.