Skip to main content

Errors & Error Handling

HTTP status codes, error response format, and how to recover from common errors.


Errors & Error Handling

Synapse uses standard HTTP status codes with a consistent error response format. This page explains how to interpret and recover from errors.

Error Response Format

All errors return JSON with this structure:

{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Mind Key fehlt oder ungültig.",
  "docs": "https://synapse.schaefer.zone/docs/getting-started/authentication"
}
Field Description
statusCode HTTP status code
error HTTP status name
message Human-readable error description
docs URL to relevant documentation (when applicable)

HTTP Status Codes

200 OK

Success. The request was processed correctly.

201 Created

Success. A new resource was created (e.g. POST /memory).

204 No Content

Success. No body returned (e.g. DELETE /memory/:id).

400 Bad Request

The request was malformed. Common causes:

  • Missing required JSON fields
  • Invalid JSON syntax
  • Invalid enum value (e.g. wrong category)
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "category must be one of: identity, preference, fact, project, skill, mistake, context, note, credentials"
}

Fix: Check the request body against the API docs. Ensure all required fields are present and have valid values.

401 Unauthorized

Authentication failed. Common causes:

  • Missing Authorization header
  • Invalid Mind Key or JWT
  • Using a Mind Key where a JWT is required (or vice versa)
{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Mind Key fehlt oder ungültig.",
  "docs": "https://synapse.schaefer.zone/docs/getting-started/authentication"
}

Fix: Verify your token. See Authentication.

403 Forbidden

You're authenticated but not allowed to perform this action. Common causes:

  • Trying to delete another user's mind
  • Trying to verify a memory with a Mind Key (requires JWT)
  • Mind is disabled

Fix: Check if you're using the correct token type for this endpoint.

404 Not Found

The requested path or resource doesn't exist.

**Do NOT guess endpoint paths.** Only the paths listed in `GET /endpoints` exist. If you get a 404, you used a wrong path.
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Route GET /memory/list not found",
  "docs": "https://synapse.schaefer.zone/docs/api/errors"
}

Fix: Call GET /endpoints to see the list of valid endpoints. Compare your URL against the list character-by-character.

409 Conflict

The request conflicts with existing state. Common causes:

  • Trying to register with an email that already exists
  • Duplicate webhook URL

Fix: Use a different value, or use PUT to update the existing resource.

429 Too Many Requests

You hit a rate limit. Only applies to ?key= query parameter auth (60/min).

{
  "statusCode": 429,
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Use Authorization header for unlimited access."
}

Response headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 42

Fix: Switch to Authorization: Bearer header (no rate limit), or wait Retry-After seconds.

500 Internal Server Error

Server error. This shouldn't happen — if it does, it's a bug.

Fix:

  1. Retry with exponential backoff (1s, 2s, 4s, 8s)
  2. Check GET /health to see if the server is up
  3. If persistent, report the error

503 Service Unavailable

Server is temporarily down (e.g. during deployment, database migration).

Fix: Wait and retry. Check GET /health.

Recovery Patterns

Retry with exponential backoff

import time
import requests

def call_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        try:
            r = requests.get(url, headers={"Authorization": f"Bearer {KEY}"})
            if r.status_code == 429:
                wait = int(r.headers.get("Retry-After", 60))
                time.sleep(wait)
                continue
            if r.status_code >= 500:
                time.sleep(2 ** attempt)
                continue
            return r
        except requests.RequestException:
            time.sleep(2 ** attempt)
    raise Exception(f"Failed after {max_retries} retries")

Auth error handling

def safe_call(url, key):
    r = requests.get(url, headers={"Authorization": f"Bearer {key}"})
    if r.status_code == 401:
        # Mind Key invalid — alert user
        raise AuthError("Mind Key invalid or expired")
    return r

Common Error Scenarios

"Mind Key fehlt oder ungültig"

  • You forgot the Authorization header
  • You used ?key= but the key is wrong
  • You're using a JWT where a Mind Key is required

"Route not found"

  • You guessed a path that doesn't exist
  • You used a verb wrong (e.g. GET /memory vs POST /memory)
  • Check GET /endpoints for valid paths

"Rate limit exceeded"

  • You're using ?key= and exceeded 60 req/min
  • Switch to Authorization: Bearer header

Next Steps