Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.semji.com/llms.txt

Use this file to discover all available pages before exploring further.

When a request cannot be completed, the Semji API returns a JSON error object alongside an appropriate HTTP status code. All errors follow the same structure, making them straightforward to handle in code. This page documents every error code the API can return, explains what triggers each one, and provides guidance on how to respond.

Error response format

Every error response — regardless of cause or status code — uses the following shape:
{
  "error": {
    "code": "string",
    "message": "string"
  }
}
error.code
string
A stable, machine-readable string identifying the error type. Use this field in your error-handling logic — it will not change between API versions.
error.message
string
A human-readable explanation of the error. For validation_error responses, this describes the specific field that failed validation. Useful for debugging but not guaranteed to be stable across releases.

Error codes reference

HTTP statuserror.codeMeaning
400bad_requestThe request was malformed or a required field is missing
401unauthorizedAPI key is missing, invalid, or revoked
403forbiddenAuthenticated but not permitted to access this resource
404not_foundThe resource does not exist
409conflictRequest conflicts with current state, e.g. version mismatch
422validation_errorRequest body failed schema validation
429rate_limitedToo many requests — hourly or burst limit exceeded
500internal_errorUnexpected server error
502bad_gatewayThe upstream service returned an error
503service_unavailableService temporarily unavailable

Detailed error reference

Returned when the request is structurally malformed — for example, a required query parameter is missing, a path parameter cannot be parsed, or the request body is not valid JSON.
Example response
{
  "error": {
    "code": "bad_request",
    "message": "The request was invalid."
  }
}
How to handle: Inspect the message field for details on what is wrong. Check that all required parameters are present and that your request body is valid JSON with the correct Content-Type: application/json header.
Returned when the Authorization header is absent, does not begin with Bearer sk_, or contains a key that is invalid or has been revoked.
Example response
{
  "error": {
    "code": "unauthorized",
    "message": "A valid API key is required. Use Authorization: Bearer sk_xxx."
  }
}
How to handle: Verify that your Authorization header is formatted correctly (Bearer sk_...), that the key has not been revoked in Settings > Organization > API Keys, and that you are not accidentally including extra whitespace or newline characters in the header value. See Authentication for details.
Returned when the API key is valid but the authenticated user does not have permission to access the requested resource. Common causes: accessing a workspace the user is not a member of, or attempting an admin-only action with a Member-role key.
Example response
{
  "error": {
    "code": "forbidden",
    "message": "You do not have access to this resource."
  }
}
How to handle: Confirm that the user associated with your API key has the required role in the workspace or organization. To check your current user and role, call GET /v1/me and GET /v1/users.
Returned when the resource identified by the URL or a path parameter does not exist, or the authenticated user cannot see it.
Example response
{
  "error": {
    "code": "not_found",
    "message": "The requested resource was not found."
  }
}
How to handle: Double-check the ID in your request path. Note that resources in workspaces you don’t have access to also return 404 rather than 403, to avoid leaking information about what exists.
Returned when the request conflicts with the current state of the resource. The most common cause is an optimistic locking conflict on content updates: the version field you submitted does not match the current version on the server, meaning another client updated the resource since you last fetched it.
Example response
{
  "error": {
    "code": "conflict",
    "message": "The request conflicts with the current state."
  }
}
How to handle: Re-fetch the resource to get the latest version value, apply your changes to the fresh copy, and retry the update with the new version.
Returned when the request body is structurally valid JSON but fails schema validation — for example, an enum field contains an unrecognized value, a required field is null, or a string exceeds its maximum length. The message field names the specific field that failed.
Example response
{
  "error": {
    "code": "validation_error",
    "message": "title: String must contain at least 1 character(s)"
  }
}
How to handle: Read the message to identify the offending field and correct the value in your request. Do not retry without fixing the input — the same request will fail again.
Returned when you exceed the rate limit for your API key — either 1,000 requests per rolling hour or 20 requests per second. The response includes a Retry-After header indicating how many seconds to wait.
Example response
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Please try again later."
  }
}
How to handle: Wait at least the number of seconds in the Retry-After header before retrying. Use exponential backoff with jitter for repeated 429s. See Rate Limits for full retry guidance.
Returned when an unexpected error occurs on the server. This is not caused by your request.
Example response
{
  "error": {
    "code": "internal_error",
    "message": "An internal error occurred."
  }
}
How to handle: Retry the request using exponential backoff. If the error persists, contact Semji support.
Returned when the Semji gateway successfully received your request but the upstream service returned an error. This is typically a transient infrastructure issue.
Example response
{
  "error": {
    "code": "bad_gateway",
    "message": "The upstream service returned an error."
  }
}
How to handle: Retry with exponential backoff. A 502 is not caused by your request and will usually resolve within seconds.
Returned when the API is temporarily unavailable, typically due to planned maintenance or an unexpected outage.
Example response
{
  "error": {
    "code": "service_unavailable",
    "message": "The service is temporarily unavailable."
  }
}
How to handle: Retry after a short delay. Check the Semji status page for any active incidents.

Handling errors in code

The following pattern covers the most important cases — retry on transient server errors, respect rate limit headers, and surface actionable messages for client errors:
import time
import random
import requests

RETRYABLE_STATUSES = {429, 500, 502, 503}

def semji_request(method: str, path: str, **kwargs) -> dict:
    url = f"https://api.semji.com/v1{path}"
    headers = {"Authorization": f"Bearer {API_KEY}"}

    for attempt in range(5):
        response = requests.request(method, url, headers=headers, **kwargs)

        if response.status_code in RETRYABLE_STATUSES:
            retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
            time.sleep(retry_after + random.uniform(0, 1))
            continue

        if not response.ok:
            error = response.json()["error"]
            raise ValueError(f"[{error['code']}] {error['message']}")

        return response.json()

    raise RuntimeError("Request failed after 5 retries")
Key rules:
  • Retry on 429, 500, 502, and 503 using exponential backoff
  • Do not retry on 400, 401, 403, 404, 409, or 422 — these indicate a problem with the request that must be fixed first
  • Re-fetch then retry on 409 — get the latest resource version before submitting your update again
  • Check error.message on 422 to identify which field failed validation