Skip to content

POST /v1/keys

Call POST /v1/keys
Price free
Scope keys:manage
Operation id createKey

Create a scoped key with optional rate limit, daily spend cap, IP allowlist and expiry. The secret is in the response once and never again. Audited. Free. Scope: keys:manage.

Copy it as curl. Set VERDICT_API_KEY first; uuidgen makes a fresh Idempotency-Key.

Request
curl -X POST 'https://api.askverdict.io/v1/keys' \
-H "Authorization: Bearer $VERDICT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{
"name": "outbound-agent prod",
"scopes": [
"decisions:write",
"index:read",
"outcomes:write"
],
"daily_spend_cap_usd": 25
}'

201: The key, with its secret shown once.

201 response
{
"id": "key_01JC3Z4Y8R9K2M5N7P1Q3S5T7V",
"project_id": "prj_01JC3Z4Y8R9K2M5N7P1Q3S5T7V",
"name": "outbound-agent prod",
"environment": "live",
"prefix": "vd_live_Ab12Cd",
"scopes": [
"decisions:write",
"index:read",
"outcomes:write"
],
"status": "active",
"rate_limit_per_minute": 600,
"daily_spend_cap_usd": 25,
"ip_allowlist": [],
"expires_at": null,
"last_used_at": null,
"created_at": "2026-11-07T14:00:00Z",
"secret": "vd_live_<shown-once>"
}
Name In Type Required Description
idempotency-key header string (uuid) yes A UUID you generate per logical request. Required on every POST. Repeating it within 24 hours returns the stored response and bills nothing; reusing it with a different body returns 409 idempotency_conflict.
x-verdict-version header string no API version to use, a date. Defaults to the version current when the key was created. The current version is 2026-11-01.

Schema CreateKeyRequest. The key to create.

Field Type Required Description
name string yes Name, for example outbound-agent prod.
project_id string no Project; defaults to the calling key’s project.
environment enum: “live”, “test” no live (default) or test.
scopes array of enum: “decisions:write”, “index:read”, “outcomes:write”, “watches:manage”, “vendors:call”, “account:read”, “account:manage”, “keys:manage” no Scopes; default decisions:write, index:read, outcomes:write.
expires_at string (date-time) no Expiry; default none.
rate_limit_per_minute integer no Requests per minute; default 600.
daily_spend_cap_usd number no Daily spend cap; default none. US dollars, up to 6 decimals.
ip_allowlist array of string (ipv4-cidr) or string (ipv6-cidr) no CIDR blocks the key may be used from; default anywhere.

Schema CreatedApiKey.

Field Type Required Description
id string yes The key id.
project_id string yes Project the key belongs to.
name string yes Name.
environment enum: “live”, “test” yes live or test.
prefix string yes The key’s first characters, to recognize it.
scopes array of enum: “decisions:write”, “index:read”, “outcomes:write”, “watches:manage”, “vendors:call”, “account:read”, “account:manage”, “keys:manage” yes Scopes granted.
status enum: “active”, “rotating”, “revoked”, “expired” yes Lifecycle status.
rate_limit_per_minute integer yes Requests per minute allowed.
daily_spend_cap_usd number or null yes Daily spend cap, or null for none. US dollars, up to 6 decimals.
ip_allowlist array of string yes CIDR blocks the key may be used from; empty means anywhere.
expires_at string or null (date-time) yes Expiry, or null for none.
last_used_at string or null (date-time) yes Last successful use, or null.
created_at string (date-time) yes When the key was created.
secret string yes The API key: vd_live_ or vd_test_ plus a base62 body. Shown once; store it now.

Errors are RFC 9457 problem details and are never billed. Branch on type. See Errors.

Status Meaning
400 Invalid request: malformed JSON, an unknown field, a failed constraint or a size limit (invalid_request).
401 Missing, malformed, revoked or expired API key, or a bad webhook signature (unauthorized).
403 The key lacks the scope this operation needs (forbidden_scope).
404 The resource does not exist in this organization (not_found).
409 The Idempotency-Key was reused with a different request, or the first request is still running (idempotency_conflict).
429 Rate limited (rate_limited). Wait Retry-After seconds.
500 Unexpected server error (internal). Not billed; retry with the same Idempotency-Key.

Open the interactive reference to send this request from the browser. The full document is at /openapi.json.