Error Reference¶
All Identity OS API errors follow a consistent format:
Authentication Errors¶
| Code | HTTP | Meaning | Fix |
|---|---|---|---|
unauthorized | 401 | Missing or invalid API key | Check Authorization: Bearer idos_sk_xxx header |
forbidden | 403 | Valid key but insufficient permissions | Check your tier limits or contact support |
Instance Errors¶
| Code | HTTP | Meaning | Fix |
|---|---|---|---|
not_found | 404 | Instance ID doesn't exist | Verify the instance_id; it may have been deleted |
invalid_request | 422 | Missing required fields or invalid values | Check request body matches the API spec |
conflict | 409 | Concurrent modification detected | Retry the request — optimistic locking will resolve |
Engine Errors¶
| Code | HTTP | Meaning | Fix |
|---|---|---|---|
not_found | 404 | Instance not found for processing | Create the instance first via POST /v1/instances |
invalid_request | 422 | Invalid mode_target or signal_strength | mode_target must be one of the 7 modes; signal_strength must be 0.0–1.0 |
throttled | 429 | Too many requests in the current cycle | Wait for MIN_CYCLE_INTERVAL to pass, or use caller-controlled timestamp |
Rate Limiting Errors¶
| Code | HTTP | Meaning | Fix |
|---|---|---|---|
rate_limited | 429 | Per-minute rate limit exceeded | Check X-RateLimit-Reset header for when to retry |
quota_exceeded | 429 | Monthly quota exhausted | Upgrade your plan or wait for the next billing cycle |
service_unavailable | 503 | Rate limiter backend unavailable (fail-closed mode) | Transient — retry after a few seconds |
Rate limit headers on every response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1711324800
X-Monthly-Remaining: 99847
Billing Errors¶
| Code | HTTP | Meaning | Fix |
|---|---|---|---|
stripe_not_configured | 500 | Stripe keys not set on the server | Server admin: set STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET |
webhook_verification_failed | 400 | Invalid Stripe webhook signature | Ensure STRIPE_WEBHOOK_SECRET matches your Stripe dashboard |
invalid_plan | 422 | Requested plan tier doesn't exist | Valid tiers: free, indie, pro |
Common Patterns¶
"I keep getting 429 throttled"¶
If you're sending observations faster than 1/second without caller-controlled timestamps:
# Fix: use explicit timestamps
from datetime import datetime, timezone, timedelta
base = datetime.now(timezone.utc)
for i in range(10):
result = client.engine.process(
instance_id=inst.id,
mode_target=Mode.EXPLORATION,
signal_strength=0.7,
timestamp=(base + timedelta(seconds=i*2)).isoformat()
)
"Instance not found after server restart"¶
If using the memory backend (default for local dev), all data is lost on restart. For persistent data:
# Use PostgreSQL
docker compose up -d
export IDENTITY_OS_DB_BACKEND=supabase
export IDENTITY_OS_SUPABASE_URL=postgresql+asyncpg://...
"Auth error but I set the API key"¶
Check the header format — must be exactly:
Not ApiKey, not Token, not Basic. Bearer only.