Skip to main content

Error responses

When a request fails, the server returns an appropriate HTTP status code with a JSON error body.

Common status codes

StatusMeaning
400Bad request — malformed JSON, missing required fields, or invalid query parameters.
401Unauthorized — no valid session, token, or API key provided.
403Forbidden — the authenticated user lacks the required RBAC permission for this action.
404Not found — the resource type (:resource slug) does not exist, or the specific record ID was not found.
422Validation error — the request body failed server-side validation rules.
500Internal server error — an unexpected error occurred.

Error shape

Most error responses follow this format:
{
  "error": "Unauthorized"
}
Validation errors may include additional detail:
{
  "error": "Validation failed",
  "details": [
    { "field": "email", "message": "must be a valid email address" }
  ]
}

Handling errors

  • Check the HTTP status code first for routing (retry logic, user feedback, etc.).
  • Read the error field for a human-readable description.
  • For 403 responses, verify the user’s RBAC role includes the required permission (e.g. records.write for create/update/delete operations).
  • Do not retry 401, 403, or 404 errors — these indicate a configuration or permissions issue, not a transient failure.

Public endpoints (no auth required)

These endpoints are accessible without authentication:
MethodPathDescription
GET/Service name and basic info. Returns pointers to docs and health endpoints.
GET/healthBasic health check.
GET/health/readyReadiness check (confirms the server and its dependencies are ready to accept requests).
curl https://your-app.up.railway.app/health

CORS and browser clients

If a web application on a different origin calls the CRM API (e.g. a frontend at https://app.yourcompany.com calling https://crm.yourcompany.com), the browser enforces CORS restrictions.

Configuring allowed origins

Set the ALLOWED_ORIGINS environment variable on your BasicsOS server to a comma-separated list of origins:
ALLOWED_ORIGINS=https://app.yourcompany.com,https://admin.yourcompany.com
The server will include the appropriate Access-Control-Allow-Origin headers for these origins.

When CORS is not needed

  • Same-origin requests — if your frontend and API share the same origin, CORS does not apply.
  • Server-to-server requests — requests made from a backend service using a Personal CRM API token (Bearer bos_crm_...) are not subject to CORS.
If you are building a server-to-server integration and do not need browser access, you can skip CORS configuration entirely.