Errors

Every error has the same shape. Branch on code, show detail to a person, and quote request_id to support.

{
  "detail": "A sentence a person can read.",
  "code": "ERR_VALIDATION",
  "request_id": "the id to quote to support",
  "errors": [{ "field": "name", "code": "...", "message": "..." }]
}

errors appears on validation errors, with one entry per field. Every response also carries X-Request-Id. Codes are stable; new ones may be added, so treat an unknown code by its HTTP status.

Codes

Code Status When What to do
ERR_TENANT_HEADER 400 X-Tenant-Id is missing or not a UUID. Send the account id given with the key, or use a Bearer credential, which does not need it.
ERR_ACTOR_INACTIVE 401 The user this credential acts as is no longer active. An admin assigns the key to another user in Settings, Integrations.
ERR_AUTH_INVALID_KEY 401 The key or token is malformed, unknown or wrong. Check the value was copied whole from Settings, Integrations.
ERR_AUTH_KEY_REVOKED 401 The key was revoked or switched off. Create a new key in Settings, Integrations.
ERR_AUTH_MISSING_KEY 401 No credential was sent. Send X-Api-Key or Authorization: Bearer.
ERR_WRONG_ENVIRONMENT 401 A sandbox key was sent to the live API, or a live key to the sandbox. Use the base URL that matches the key: api.woodsystems.com for wsk_live_, api-sandbox.woodsystems.com for wsk_test_.
ERR_QUOTA_EXCEEDED 402 The month's calls are used up and no more can be billed. Add a payment method or raise the cap under Settings, Billing.
ERR_ACCOUNT_SUSPENDED 403 The account is suspended. The account owner settles billing under Settings, Billing.
ERR_FORBIDDEN 403 The account service refused the call. Read detail.
ERR_NOT_ENTITLED 403 The account does not include the API. The account owner adds API & Integrations under Settings, Billing.
ERR_OAUTH_NOT_ALLOWED 403 Connected apps cannot do this. Use the WoodSystems web app, or an API key for this call.
ERR_ROLE_REQUIRED 403 The user the credential acts as has a role below what this call needs. Ask an admin to raise their role, or assign the key to a user with the role.
ERR_SANDBOX_ONLY 403 This call exists only in the sandbox. Use the sandbox base URL.
ERR_SCOPE_MISSING 403 The credential does not hold the permission this call needs. Add the named scope to the key, or reconnect the app with it.
ERR_TENANT_MISMATCH 403 The key belongs to a different account than X-Tenant-Id names. Check that the key and the account id came from the same place.
ERR_NOT_FOUND 404 No such record in this account. Check the id; records of other accounts are never visible.
ERR_CONFLICT 409 The change conflicts with the record's current state. Read the record again and retry.
ERR_DELETE_BLOCKED 409 The record cannot be deleted while other records depend on it. Read detail for what depends on it.
ERR_FEATURE_OFF 409 The account has this area switched off. Switch it on under Company Config.
ERR_IDEMPOTENCY_IN_PROGRESS 409 A call with this Idempotency-Key is still running or never finished. Wait and retry; or retry with a new key after checking whether the record exists.
ERR_LOCKED 409 The record is locked: a sent or signed document, a payroll-locked day, a scheduled event. Change it in the web app, where the lock can be lifted.
ERR_NO_MAILBOX 409 The user the credential acts as has no connected mailbox to send from. That user connects Gmail or Outlook under Profile settings, Personal Inbox, Send email as me.
ERR_OVER_RECEIPT 409 More was received than is still outstanding on the purchase order line. Receive at most the outstanding quantity named in detail.
ERR_IDEMPOTENCY_MISMATCH 422 This Idempotency-Key was used with a different request body. Use a new Idempotency-Key for a new request.
ERR_IDEMPOTENCY_REQUIRED 422 This write needs an Idempotency-Key header. Send a unique string per submission, such as a UUID.
ERR_VALIDATION 422 The request body or query is not valid. Read errors for each field.
ERR_RATE_LIMITED 429 Too many calls in a short time. Wait for Retry-After seconds; read X-RateLimit-Remaining.
ERR_INTERNAL 500 Something failed on our side. Quote request_id to support.
ERR_SEND_FAILED 502 The mail provider refused or failed the send. Read detail for the provider's reason; reconnect the mailbox if it says so.
ERR_UPSTREAM 502 The account service could not complete the call. Retry with backoff; quote request_id to support if it persists.
ERR_LIMITER_UNAVAILABLE 503 The rate limiter could not record the call, so it was not made. Retry after Retry-After seconds; quote request_id to support if it persists.
ERR_UPSTREAM_TIMEOUT 504 The account service took too long. Retry with backoff.