Errors

The Sphere API uses standard HTTP status codes to indicate the success or failure of a request. When something goes wrong, the response body includes a structured error message to help you diagnose the issue.

You can identify whether a request succeeded by checking the HTTP status code. Codes in the 2xx range indicate success, 4xx codes indicate a client error (something in your request is wrong), and 5xx codes indicate a server-side issue.


Status codes

Here is a complete list of HTTP status codes returned by the Sphere API, grouped by category.

Success codes

  • Name
    200 OK
    Description

    The request succeeded and the response body contains the requested data.

  • Name
    201 Created
    Description

    A new resource was created successfully. The response body contains the created resource.

  • Name
    204 No Content
    Description

    The request succeeded but there is no response body. Commonly returned by DELETE operations.

Client error codes

  • Name
    400 Bad Request
    Description

    The request is malformed — invalid JSON, missing required headers, or unrecognized parameters.

  • Name
    401 Unauthorized
    Description

    Authentication failed. The token is missing, expired, or invalid.

  • Name
    403 Forbidden
    Description

    The authenticated user does not have permission to perform this action. Check workspace role and scopes.

  • Name
    404 Not Found
    Description

    The requested resource does not exist, or you do not have access to it in the current tenant context.

  • Name
    409 Conflict
    Description

    The request conflicts with the current state of the resource. For example, creating a tenant with a slug that already exists.

  • Name
    422 Unprocessable Entity
    Description

    Validation failed. The request body contains invalid data. See the errors object for field-level details.

  • Name
    429 Too Many Requests
    Description

    Rate limit exceeded. Wait for the duration specified in the Retry-After header before retrying.

Server error codes

  • Name
    500 Internal Server Error
    Description

    An unexpected error occurred on the server. If this persists, report it with the X-Correlation-Id.

  • Name
    502 Bad Gateway
    Description

    The gateway received an invalid response from an upstream service. This can occur during engine orchestration if a dependent service is down.

  • Name
    503 Service Unavailable
    Description

    The service is temporarily unavailable, usually during maintenance or deployment. Retry after a short delay.

Status code summary

2xx  Success
├── 200  OK
├── 201  Created
└── 204  No Content

4xx  Client Error
├── 400  Bad Request
├── 401  Unauthorized
├── 403  Forbidden
├── 404  Not Found
├── 409  Conflict
├── 422  Unprocessable Entity
└── 429  Too Many Requests

5xx  Server Error
├── 500  Internal Server Error
├── 502  Bad Gateway
└── 503  Service Unavailable

Error response format

All error responses follow a consistent JSON structure. The exact shape depends on the type of error.

General errors (4xx/5xx)

Most errors return a simple message field describing what went wrong.

Validation errors (422)

Validation errors include an additional errors object that maps field names to arrays of error messages. This allows you to display field-level errors in forms.

General error (401)

{
  "message": "Unauthenticated."
}

Validation error (422)

{
  "message": "The given data was invalid.",
  "errors": {
    "login": [
      "The login field is required."
    ],
    "password": [
      "The password must be at least 8 characters."
    ]
  }
}

Conflict error (409)

{
  "message": "A tenant with slug 'acme' already exists."
}

POST/auth/api/v1/auth/login

Validation errors (422)

When you submit a request with invalid data, the API returns a 422 status code with detailed field-level errors. Each field that failed validation is listed in the errors object with an array of human-readable error messages.

Common validation rules include:

  • Name
    required
    Description

    The field must be present and non-empty.

  • Name
    email
    Description

    The field must be a valid email address.

  • Name
    min:N
    Description

    The field must have at least N characters (strings) or be at least N (numbers).

  • Name
    max:N
    Description

    The field must not exceed N characters or value.

  • Name
    unique
    Description

    The value must not already exist in the database (e.g., duplicate email).

POST
/auth/api/v1/auth/login
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"login": "", "password": "short"}'

Authentication errors (401)

A 401 response means the request could not be authenticated. This happens in three cases:

  • Name
    Missing token
    Description

    No Authorization header was provided. Add Authorization: Bearer {access_token} to your request.

  • Name
    Expired token
    Description

    The access_token has expired (after 60 minutes). Use the refresh_token to obtain a new one via /auth/api/v1/auth/refresh.

  • Name
    Invalid token
    Description

    The token is malformed, has been tampered with, or was signed with a different key. Obtain a fresh token by logging in again.

Token expired

{
  "message": "Unauthenticated."
}

JavaScript — auto-refresh on 401

async function apiCall(url, token, refreshToken) {
  let response = await fetch(url, {
    headers: { Authorization: `Bearer ${token}` },
  })

  if (response.status === 401) {
    // Token expired — refresh it
    const refreshResponse = await fetch(
      'https://your-sphere.example.com/auth/api/v1/auth/refresh',
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ refresh_token: refreshToken }),
      },
    )
    const tokens = await refreshResponse.json()
    // Retry with new token
    response = await fetch(url, {
      headers: { Authorization: `Bearer ${tokens.access_token}` },
    })
  }

  return response
}

Authorization errors (403)

A 403 response means the user is authenticated but does not have sufficient permissions for the requested action. This is different from 401 — the token is valid, but the user's role or scope does not allow the operation.

Common causes:

  • Name
    Workspace role
    Description

    The user has a viewer role in the workspace but attempted a write operation. Upgrade to editor or owner.

  • Name
    Token scope
    Description

    The token was issued with limited scopes (e.g., guest token type) that do not include the requested permission.

  • Name
    Resource ownership
    Description

    The user is trying to access or modify a resource owned by another user without the appropriate admin privileges.

Insufficient permissions

{
  "message": "This action is unauthorized."
}

Rate limiting (429)

All Sphere API endpoints enforce rate limiting to protect against abuse. When you exceed the allowed number of requests, the API returns a 429 status with a Retry-After header indicating how many seconds to wait before retrying.

  • Name
    Retry-After
    Type
    response header
    Description

    The number of seconds to wait before making another request.

  • Name
    X-RateLimit-Limit
    Type
    response header
    Description

    The maximum number of requests allowed in the current window.

  • Name
    X-RateLimit-Remaining
    Type
    response header
    Description

    The number of requests remaining in the current window.

Rate limit exceeded (429)

{
  "message": "Too Many Attempts."
}

Response headers

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-Correlation-Id: a1b2c3d4-e5f6-7890-abcd-ef0123456789

JavaScript — respect rate limits

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options)

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || '60'
      const waitMs = parseInt(retryAfter, 10) * 1000
      await new Promise((resolve) => setTimeout(resolve, waitMs))
      continue
    }

    return response
  }
  throw new Error('Rate limit exceeded after max retries')
}

Correlation ID

Every response from the Sphere API includes an X-Correlation-Id header. This is a unique identifier that traces the request through all services in the platform — from the Traefik gateway through sphere-auth, sphere-core, and any downstream engines.

When reporting errors or unexpected behavior, always include the correlation ID. It allows the platform team to find the exact request in logs across all services.

Extracting the correlation ID

curl -v https://your-sphere.example.com/core/api/v1/families \
  -H "Authorization: Bearer {token}" 2>&1 | grep X-Correlation-Id
# < X-Correlation-Id: a1b2c3d4-e5f6-7890-abcd-ef0123456789

Was this page helpful?