API
API Keys
Mint, list, revoke, and rotate API keys without ever leaving the API surface. Every key is hashed at rest — the raw value appears in the response of the create + rotate endpoints EXACTLY ONCE. Save it immediately.
Authentication
Every /v1/* request requires Authorization: Bearer sk_(live|test)_<64hex>. See Authentication for the full handshake.
Creating an API key
POST creates require an Idempotency-Key header (UUID) per CLAUDE.md API hard rules. Re-sending the same payload + key returns the cached response with the same raw key.
curl -X POST https://api.simulix.com/v1/api-keys \
-H "Authorization: Bearer $SIMULIX_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "production-frontend",
"scopes": ["simulations:read", "simulations:write"],
"is_test": false
}'is_test true mints sk_test_* (sandbox tier); false mints sk_live_* (live tier). The calling key's tier governs which database the new key lands in.
Listing keys
Cursor-paginated. Pass ?limit=N&cursor=<next_cursor>. Maximum 100 per page; default 50. The response meta block carries "next_cursor", "has_more", and "returned".
Revoking a key
Revocation is immediate — the next request using the revoked key gets 401 "invalid_or_revoked_api_key". Re-revoking an already-revoked key is 409, not 200, so the operator UI can distinguish a fresh revoke from a no-op.
curl -X DELETE https://api.simulix.com/v1/api-keys/<key_id> \ -H "Authorization: Bearer $SIMULIX_KEY"
Rotating a key
Atomic: a single transaction creates the new key and revokes the old one. No grace period — the old key is invalid the instant the response goes out. Plan your deploy window accordingly. The new key inherits the old key's scopes + expiry.
curl -X POST https://api.simulix.com/v1/api-keys/<key_id>/rotate \ -H "Authorization: Bearer $SIMULIX_KEY" \ -H "Idempotency-Key: $(uuidgen)"
Scopes
Six scopes available via the public API. Use the least-privilege scope set for each key — separate read-only keys for analytics vs. full-write keys for ingestion.
| Scope | Use |
|---|---|
| simulations:read | Read simulations + per-agent transcripts. |
| simulations:write | Create simulations. |
| case_studies:read | Read calibrated workflow catalog. |
| case_studies:write | Operator-only — promote workflows. |
| keys:read | List API keys. |
| keys:write | Create, revoke, rotate API keys. |
Security
- The raw key appears in the response of create_api_key + rotate_api_key EXACTLY ONCE. Persist it immediately — Simulix only stores SHA-256 hashes.
- Sandbox keys (
sk_test_*) and live keys (sk_live_*) live in physically separate databases per ADR-005. Sandbox traffic never consumes prod quota. - Cross-organization isolation is enforced at every query — knowing another org's key UUID returns 404 (not 403) so existence never leaks.
- Recommended rotation cadence: every 90 days for live keys, on every employee offboarding for ops keys.
Endpoint reference
| Method | Path | Scope | Status | Summary |
|---|---|---|---|---|
| POST | /v1/api-keys | keys:write | 201 | Mint a new key. Raw value returned ONCE. |
| GET | /v1/api-keys | keys:read | 200 | Cursor-paginated list (max 100/page). |
| DELETE | /v1/api-keys/{key_id} | keys:write | 200 / 404 / 409 | Soft-revoke. Re-revoking is 409. |
| POST | /v1/api-keys/{key_id}/rotate | keys:write | 201 | Atomic create-new + revoke-old. No grace period. |
Bootstrap (ops only)
To mint the very first key for a new environment (before any key exists to authenticate with), use the scripts/seed-org-and-key.py CLI. It writes directly to the matching tier's database. The bootstrap key carries the wildcard scope and should be replaced by least-privilege keys via POST /v1/api-keys as soon as possible.