API key management
These endpoints let an admin key see every inference key in the organization, rename keys, change their network restrictions, and switch them off and on. Use them for scheduled key hygiene (disable keys that have not been used in 90 days), for incident response (switch off every key a departing employee created), and for inventory reports.
Creating keys stays in the Console. A new secret should be shown to one person, once, not passed through scripts. See Managing API keys.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /v1/organizations/api_keys | List inference keys. |
GET | /v1/organizations/api_keys/{api_key_id} | Read one key. |
PATCH | /v1/organizations/api_keys/{api_key_id} | Change name, status or restrictions. |
Authenticate with an admin key and send syntic-beta: admin-2026-11-01. Keys created by Owners and Administrators see and change every key.
The API key object
{
"id": "apikey_01JB7C9E1G3J5L7N9Q1S",
"type": "api_key",
"name": "billing-worker-prod",
"kind": "private",
"prefix": "sk_live_3f9c",
"hint": "…a71e",
"status": "active",
"workspace_id": "wrkspc_01JC0A2C4E6G8J0L2N4Q",
"created_by": { "id": "user_01J9Y0A2C4E6G8J0L2N4", "email": "dana@example.com", "status": "active" },
"allowed_origins": [],
"allowed_ips": ["203.0.113.0/24"],
"pinned_version": "2026-11-01",
"expires_at": null,
"created_at": "2026-03-02T09:30:00Z",
"last_used_at": "2026-11-05T10:02:11Z",
"last_used_ip": "203.0.113.40",
"use_count": 1841220
}| Field | Description |
|---|---|
kind | private (sk_live_), public (pk_live_) or syntic_code (sk_syntic_). |
prefix, hint | The first and last few characters, enough to match a key against a leaked or logged value. The secret itself is never returned. |
status | active, inactive (switched off, can be switched back on), revoked (permanent) or expired. |
created_by.status | If the creator is not active, the key does not work even when its own status is active. |
allowed_origins, allowed_ips | Network restrictions. See Allowed origins and IP allowlists. |
pinned_version | The syntic-version the key uses by default. See Versioning. |
last_used_at, last_used_ip, use_count | Usage, updated at most once a minute. |
List keys
GET /v1/organizations/api_keys
| Query parameter | Notes |
|---|---|
status | active (default), inactive, revoked, expired or all. |
workspace_id | Keys in one workspace. |
created_by | Keys created by one member. |
unused_since | RFC 3339 time: keys whose last_used_at is earlier, or never used. |
limit, after_id, before_id | Cursor pagination. |
Update a key
PATCH /v1/organizations/api_keys/{api_key_id}
| Field | Notes |
|---|---|
name | 1 to 100 characters. |
status | active or inactive. Revoking (permanent) stays in the Console. |
allowed_origins | Replaces the list. |
allowed_ips | Replaces the list. |
pinned_version | Move the key’s default API version. |
A key switched to inactive fails with 401 authentication, code inactive_api_key, from the next request.
Example: disable keys unused for 90 days
CUTOFF=$(date -u -d '90 days ago' +%Y-%m-%dT%H:%M:%SZ)
curl -sS -G https://app.syntic.ai/v1/organizations/api_keys \
-H "Authorization: Bearer $SYNTIC_ADMIN_KEY" \
-H "syntic-beta: admin-2026-11-01" \
--data-urlencode "unused_since=$CUTOFF" --data-urlencode "limit=100" \
| jq -r '.data[].id' | while read -r ID; do
curl -sS -X PATCH "https://app.syntic.ai/v1/organizations/api_keys/$ID" \
-H "Authorization: Bearer $SYNTIC_ADMIN_KEY" \
-H "Content-Type: application/json" \
-H "syntic-beta: admin-2026-11-01" \
-d '{"status": "inactive"}' > /dev/null && echo "disabled $ID"
doneErrors
Errors use the error envelope.
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request_error | invalid_parameter | A bad origin, IP range or version; param names it. |
| 400 | invalid_request_error | read_only_field | Trying to set kind, workspace_id or the secret. |
| 404 | not_found_error | api_key_not_found | No such key in the organization. |
| 409 | conflict_error | key_revoked | Changing a revoked or expired key. |
Build notes for the platform team
- Wrap the existing key functions; add the
inactivestatus (reversible) alongsiderevoked(permanent). - Return prefix and hint only. The secret hash never leaves the database layer.
- Every
PATCHwritesapi_key.updatedwith the changed fields.