xeroctl keys
Mint, rotate, and revoke project API keys from the terminal. The key value prints once at create or rotate; everything after that is metadata.
One look only. The full key value prints once at create and once at rotate. Save it before you close the terminal. The router cannot show it again.
Keys carry permission scopes, an optional endpoint pin, an optional expiration,
optional IP allow/block rules, and a per-key rate quota. The action is selected
by the action flag (--create, --delete, --rotate,
--ip-filter, --quota); one action per invocation.
Base URL and authenticating key are read from the active xeroctl deployment. The project is taken from the deployment's base_url (the /<project>/v1 path segment), not supplied separately. Use --frontend-url to override for a single invocation. The global --dry-run flag prints the planned request for every write action without sending it.
Wire surface
| Method | Path | Action |
|---|---|---|
GET | /v1/management/api-keys | list |
POST | /v1/management/api-keys | create |
GET | /v1/management/api-keys/<id> | get |
DELETE | /v1/management/api-keys/<id> | revoke (soft, is_active=false) |
POST | /v1/management/api-keys/<id>/rotate | rotate (opens grace window) |
PUT | /v1/management/api-keys/<id>/ip-filter | ip-filter, whole-object replace |
PUT | /v1/management/api-keys/<id>/quota | quota, whole-object replace |
Placeholders used below: key_abc123 is an example key id, 11111111-2222-3333-4444-555555555555 is an example endpoint UUID, INTERNAL_IP stands in for a literal address like 198.51.100.7. Substitute real values.
Usage Pattern
xeroctl keys # List API keys
xeroctl keys <id> # Show key details
xeroctl keys --create --name <n> --scopes <s> # Create a new key
xeroctl keys <id> --delete # Revoke a key
xeroctl keys <id> --rotate # Rotate a key
xeroctl keys <id> --ip-filter --allow <ip> # Update IP filter
xeroctl keys <id> --quota --quota-requests <n> --quota-window <s> # Update quota
list
List all API keys for the project. This is the default action when no ID or action flag is given.
xeroctl keys
xeroctl keys --include-inactive
Options
| Option | Description |
|---|---|
--include-inactive |
Include revoked (inactive) keys in the listing. Maps to query ?include_inactive=true. |
Output columns: ID, NAME, PREFIX, SCOPES, ACTIVE, LAST_USED, EXPIRES.
get
Show full details of a specific API key.
xeroctl keys key_abc123
xeroctl keys key_abc123 -o json
The default (text) renderer prints the following fields:
IDProject IDUser ID(or(machine key)when unset)NamePrefixScopesActiveQuota RequestsQuota Window(seconds)Total RequestsLast UsedExpiresCreatedAllow List(only when non-empty)Block List(only when non-empty)Endpoint(UUID; only when the key is endpoint-scoped)
create
Create a new API key. Both --name and --scopes are required.
# Basic key for inference access
xeroctl keys --create --name "Production App" --scopes inference
# Key scoped to a specific endpoint (UUID, not slug)
xeroctl keys --create \
--name "CI Pipeline" \
--scopes inference \
--endpoint-id 11111111-2222-3333-4444-555555555555
# Key with expiration
xeroctl keys --create \
--name "Temporary Key" \
--scopes inference \
--expires 2026-12-31T00:00:00Z
# Full options (multiple scopes, endpoint pin, expiration)
xeroctl keys --create \
--name "Data Pipeline" \
--scopes inference,research \
--endpoint-id 11111111-2222-3333-4444-555555555555 \
--expires 2027-01-01T00:00:00Z
Options
| Option | Description |
|---|---|
--name <name> |
Human-readable key name (required) |
--scopes <scopes> |
Comma-separated scopes (required). See Scopes. |
--endpoint-id <uuid> |
Restrict key to a specific endpoint UUID (not a slug). |
--expires <date> |
Expiration date in ISO 8601 format (e.g., 2026-12-31T00:00:00Z) |
Two MCP-related fields, catalog tier and Allow destructive XEM tools, are not set from this CLI. They live on the Scopes reference and the frontend key edit form.
delete / revoke
Revoke an API key. The key is immediately deactivated (the underlying row is marked is_active=false; it is not hard-deleted). Revoked keys remain visible to xeroctl keys --include-inactive. A confirmation prompt is shown by default.
# With confirmation prompt
xeroctl keys key_abc123 --delete
# Skip confirmation
xeroctl keys key_abc123 --delete --force
# Dry run
xeroctl keys key_abc123 --delete --dry-run
Options
| Option | Description |
|---|---|
--force |
Skip the confirmation prompt |
--dry-run |
Show what would be deleted without making changes |
rotate
Rotate an API key, generating a new key value. Rotation opens a grace window during which the previous key value also continues to authenticate; update consumers within the grace window. A confirmation prompt is shown by default.
# With confirmation prompt
xeroctl keys key_abc123 --rotate
# Skip confirmation
xeroctl keys key_abc123 --rotate --force
# Rotate and set a new expiration on the rotated key
xeroctl keys key_abc123 --rotate --expires 2027-01-01T00:00:00Z
Options
| Option | Description |
|---|---|
--expires <date> |
Optional new expiration (ISO 8601) for the rotated key. |
--force |
Skip the confirmation prompt |
--dry-run |
Show what would happen without making changes |
Response fields
The new key value prints once. Grace metadata prints alongside it: Prefix, Previous Prefix, Grace Expires, Grace Remaining (s). Match Previous Prefix against in-flight client logs to find consumers still presenting the old key, and roll them before the grace window closes.
ip-filter
Update IP filter rules for a key. Specify allowed and/or blocked IP addresses and CIDR ranges. Both --allow and --block are repeatable.
# Allow only private network traffic
xeroctl keys key_abc123 --ip-filter \
--allow 10.0.0.0/8 \
--allow 192.168.0.0/16
# Block specific IP addresses
xeroctl keys key_abc123 --ip-filter \
--block 203.0.113.5 \
--block 203.0.113.6
# Allow a range and block a specific IP
xeroctl keys key_abc123 --ip-filter \
--allow 10.0.0.0/8 \
--block INTERNAL_IP
# Clear the allow list (leaves the block list as-is)
xeroctl keys key_abc123 --ip-filter --clear-allow
# Clear both lists
xeroctl keys key_abc123 --ip-filter --clear-allow --clear-block
This endpoint is a PUT, the request is a whole-object replacement of the field(s) you send. Omitting --allow / --block leaves that list unchanged; passing --clear-allow or --clear-block explicitly sends an empty list.
Options
| Option | Description |
|---|---|
--allow <ip> |
Allowed IP address or CIDR range (repeatable) |
--block <ip> |
Blocked IP address or CIDR range (repeatable) |
--clear-allow |
Replace the allow list with an empty list (removes all allow rules). |
--clear-block |
Replace the block list with an empty list (removes all block rules). |
--dry-run |
Show what would be updated without making changes |
quota
Update rate quota settings for a key. The quota is expressed as a request count over a window of N seconds; there is no implicit per-minute meaning. Defaults are quota_requests=60 and quota_window=60.
# 1000 requests per 60 second window (default window)
xeroctl keys key_abc123 --quota --quota-requests 1000
# 500 requests per 120 second window
xeroctl keys key_abc123 --quota --quota-requests 500 --quota-window 120
# Dry run
xeroctl keys key_abc123 --quota --quota-requests 200 --dry-run
This endpoint is a PUT, the request is a whole-object replacement. Omitted fields are left unchanged on the key.
Options
| Option | Description |
|---|---|
--quota-requests <n> |
Maximum number of requests allowed per quota window. |
--quota-window <n> |
Quota window length in seconds. |
--dry-run |
Show what would be updated without making changes |
Scopes
Scopes control which API operations the key is authorized to perform. The router accepts exactly four scope values; any other value is rejected with HTTP 400 unknown scope. Pass multiple scopes as a comma-separated list to --scopes. See also Authentication for the canonical scope reference.
| Scope | Description |
|---|---|
inference |
Baseline inference dispatch (chat completions, Responses API, embeddings, and other model-serving routes). |
management |
Administrative management-plane access (keys, projects, endpoints, quotas). |
execution |
XEM execution surface (x_exec and per-tool execution gates). Implies the per-tool research gates as well. |
research |
Research-surface tools (e.g. deep_think) that need gated access without full XEM execution rights. |
Catalog tier and destructive XEM tools
Each API key also carries two MCP-related fields that scopes alone do not express:
- Catalog tier (
core,exec,intel,all), trims the MCPtools/listsurface to a fixed subset of wire names.allis the inclusive default.corepublishes the read-only baseline (workspace lookup, memory recall / save / search, calculator, session init, web research / fetch / inspect).execadds the governed XEMxerotier.exec.*family.inteladds the intelligence surface (decisions, milestones, relations, graph, artifact lifecycle, code / repo tools). - Allow destructive XEM tools, a per-key opt-in toggle that lets the key invoke XEM adapters tagged as destructive.
The xeroctl keys CLI does not currently expose either field; both are configured on the frontend API key edit form. See MCP for the catalog-tier definitions and Authentication for the destructive opt-in semantics.
Examples
Create a Production Key
# Create key with multiple scopes
xeroctl keys --create \
--name "Production API" \
--scopes inference,research
# The full key value is printed once, save it immediately
Secure a Key with IP Filtering
# Allow only your datacenter CIDR
xeroctl keys key_abc123 --ip-filter --allow 203.0.113.0/24
Apply Rate Limits
# Limit to 100 requests per 60 second window
xeroctl keys key_abc123 --quota --quota-requests 100 --quota-window 60
Rotate a Compromised Key
# Immediately rotate (no prompt)
xeroctl keys key_abc123 --rotate --force
# New key value is printed, update your systems before proceeding
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
401 on a rotated key |
Consumer still presenting the pre-rotate value; grace window expired. | Match Previous Prefix from --rotate output against client logs; roll the consumer to the new value. |
403 not authorized |
Key missing the scope for the route (e.g. management for key admin). |
See Scopes; recreate or rotate with the correct --scopes. |
400 unknown scope |
Scope value outside inference / management / execution / research. |
Use one of the four documented values; multiple as a comma-separated list. |
403 from an allowed IP |
Allow list set but request egress IP not covered, or block list shadows allow. | xeroctl keys <id> -o json to inspect allow/block; re-run --ip-filter with the correct CIDR. |
429 spike after key swap |
New key inherited the default quota (60 / 60s). |
Resize with --quota --quota-requests <n> --quota-window <s>; see Error handling for retry guidance. |
| Lost key value | Not saved at create or rotate. | Cannot be recovered. --rotate the key and capture the new value. |