API Keys
API keys are the primary authentication mechanism for the PolySimulator API. Each key is tied to a user account, has configurable permissions, and can be revoked instantly.
Create a Key
curl -X POST https://api.polysimulator.com/v1/keys \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-trading-bot",
"permissions": ["read", "trade"],
"tier": "free"
}'
Response (201 Created):
{
"id": 1,
"raw_key": "ps_live_kJ9mNx2pQrStUvWxYz01Ab3CdEfGhI4j...",
"key_prefix": "ps_live_kJ9mNx2p",
"name": "my-trading-bot",
"rate_limit_tier": "free",
"permissions": ["read", "trade"],
"created_at": "2026-02-06T12:00:00Z"
}
The raw_key field is shown exactly once. Store it securely — it cannot
be retrieved again. Only the SHA-256 hash is stored in the database.
| Field | Description |
|---|
id | Numeric key ID (used for revocation) |
raw_key | Full API key — save this immediately |
key_prefix | First 16 chars (used for identification in listings) |
name | Your label for this key |
rate_limit_tier | free, pro, or enterprise |
permissions | Array of granted permissions |
created_at | ISO 8601 timestamp |
List Keys
Returns all keys for your account. Only prefixes are shown — never the full key.
curl -H "X-API-Key: $API_KEY" https://api.polysimulator.com/v1/keys
[
{
"id": 1,
"key_prefix": "ps_live_kJ9mNx2p",
"name": "my-trading-bot",
"permissions": ["read", "trade"],
"rate_limit_tier": "free",
"is_active": true,
"created_at": "2026-02-06T12:00:00Z",
"expires_at": null
}
]
Revoke a Key
Permanently deactivates a key. This action cannot be undone.
curl -X DELETE -H "X-API-Key: $API_KEY" \
https://api.polysimulator.com/v1/keys/1
{
"message": "Key revoked successfully"
}
Key Limits
| Constraint | Value |
|---|
| Max keys per user | 5 |
| Key format | ps_live_<64 hex chars> |
| Storage | SHA-256 hash only |
| Expiration | Optional expires_at field |
Error Handling
| Status | Endpoint | Meaning |
|---|
201 | POST /v1/keys | Key created — save raw_key immediately |
400 | POST /v1/keys | Max 5 keys reached, or unknown tier |
400 | POST /v1/keys/bootstrap | You already have key(s) — use POST /v1/keys with X-API-Key |
401 | Any | Invalid, expired, or deactivated API key |
401 | POST /v1/keys/bootstrap | Invalid or expired Supabase JWT |
403 | POST /v1/keys | API access restricted (allowlist) |
# Robust key creation with error handling
resp = requests.post(
f"{BASE_URL}/v1/keys",
headers={"X-API-Key": API_KEY},
json={"name": "my-bot", "permissions": ["read", "trade"]},
)
if resp.status_code == 201:
key_data = resp.json()
print(f"Save this key NOW: {key_data['raw_key']}")
elif resp.status_code == 400:
err = resp.json()
print(f"Cannot create key: {err.get('message', err.get('error'))}")
elif resp.status_code == 401:
print("API key is invalid or expired — re-authenticate")
else:
print(f"Unexpected error: {resp.status_code}")
Next Steps