Skip to navigation

Management API keys

Provision, restrict, budget, and track API keys through the Management API

The Management API issues, rotates, restricts, and caps your organization’s API keys from code, such as one key per customer or employee. It authenticates with a management key that can never make model calls.

Management keys

Create management keys under API keys → Management keys in the dashboard, the only place they’re made. The raw mgmt_ key is shown once, acts on one organization, returns 401 on model endpoints, and should stay server-side.

A new management key gets the dashboard permissions its creator holds, so it can do through the API what that person can do in the dashboard. Scopes are those permission names. A key keeps the scopes it was minted with: if your permissions change, mint a new key. These scopes cover the keys API:

ScopeGrants
manage_api_keysCreate, update, and delete API keys, and read them
view_api_keysRead API keys
view_billingRead API keys and usage
manage_projectsThe Projects API
manage_routingOrganization routing policies

Keys minted before scopes became permission names hold manage_keys and read_usage, which still work as manage_api_keys and view_billing. The other areas of the API use their own dashboard permissions; see scopes.

Send it to https://api-gateway.merge.dev as Authorization: Bearer mgmt_....

Create a key

POST /v1/keys returns 201 with the raw mg_ key, exactly once. All body fields are optional.

FieldMeaning
nameLabel shown in the key list and usage views, such as customer-acme
limit, limit_resetSpend limit in USD (greater than 0) and its window: daily, weekly, or monthly (the default)
project_idAttributes every request to that project. Can’t change after creation
allowed_modelsModel allowlist
routing_policy_idRouting policy binding
disabledtrue creates the key paused. Defaults to false
expires_atWhen the key stops working, as an ISO 8601 timestamp in the future. A value without an offset is UTC. Omitted means it never expires

Creation returns 403 payment_method_required when your organization has no payment method on file, except on the Free plan, and 409 org_api_key_limit_reached once the organization holds 1,000 keys.

curl -X POST https://api-gateway.merge.dev/v1/keys \
-H "Authorization: Bearer $MERGE_GATEWAY_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "customer-acme", "limit": 50, "limit_reset": "monthly"}'

The response is a key object plus key. hash is the key’s ID for every other call: the SHA-256 hash of the raw key as 64 hex characters, safe to log.

{
"hash": "9f2c4e81b7a05d3c6e1f8a2b4d7c9e0f3a6b8d1c5e7f9a2b4c6d8e0f1a3b5c7d",
"name": "customer-acme",
"label": "mg_8Kx2pQr",
"disabled": false,
"limit": 50,
"limit_reset": "monthly",
"usage": 0,
"limit_remaining": 50,
"usage_daily": 0,
"usage_weekly": 0,
"usage_monthly": 0,
"byok_usage": 0,
"byok_usage_daily": 0,
"byok_usage_weekly": 0,
"byok_usage_monthly": 0,
"created_at": "2026-06-02T17:04:00Z",
"updated_at": "2026-06-02T17:04:00Z",
"expires_at": null,
"project_id": null,
"allowed_models": null,
"routing_policy_id": null,
"budget_group_id": null,
"creator_user_id": null,
"key": "mg_8Kx2pQrS..."
}

usage is the USD spend in the current limit_reset window. usage_daily, usage_weekly, and usage_monthly are the spend today, since Monday, and since the 1st of the month (UTC), whatever the window. Each byok_usage field is the part of the matching usage field that ran on your own provider credentials. creator_user_id is null for keys created through the Management API.

Manage keys

EndpointDoes
GET /v1/keysLists keys newest first as {object, data, has_more}, at most 100 per page. Page with offset and limit while has_more is true. Filter with project_id, or with disabled (true for paused keys, false for active ones)
GET /v1/keys/{hash}Returns one key with its current usage
PATCH /v1/keys/{hash}Updates name, disabled, limit, limit_reset, allowed_models, routing_policy_id, or expires_at
DELETE /v1/keys/{hash}Revokes the key immediately and returns 204. Its past spend stays in usage reporting

On PATCH, omitted fields are left alone. null removes the limit ("limit": null), the allowlist, the routing policy binding, or the expiry. project_id returns 400, since a key’s project can’t change. Pause a key with "disabled": true. Full schemas: API reference.

Restrict which models a key can call

allowed_models limits a key you hand to a team or customer to listed models.

cURL
curl -X PATCH https://api-gateway.merge.dev/v1/keys/$KEY_HASH \
-H "Authorization: Bearer $MERGE_GATEWAY_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{"allowed_models": ["openai/gpt-5.4-mini", "anthropic/claude-haiku-*"]}'
RuleDetail
EntriesCanonical provider/model IDs. A bare name such as gpt-5.4-mini returns 400
WildcardsOne trailing * matches a prefix, such as anthropic/claude-opus-*. A leading or interior * returns 400
Aliases@alias/ entries return 400. List the models the policy routes to instead
SizeUp to 200 entries, duplicates collapsed
[]Denies every model
Omitted or nullUnrestricted

Pinning a disallowed model returns 403 model_not_allowed. Under a routing policy, the allowlist filters candidates instead, failing only when none is allowed. It applies on every endpoint, alongside your organization’s blocklist.

Bind a routing policy to a key

routing_policy_id gives one key its own routing without a project or per-request field. Rebinding needs no rotation; null unbinds.

cURL
curl -X PATCH https://api-gateway.merge.dev/v1/keys/$KEY_HASH \
-H "Authorization: Bearer $MERGE_GATEWAY_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{"routing_policy_id": "3f0a9c1e-5b7d-4a2f-8c61-9d4e2b7a0f13"}'

A policy named on the request beats the binding, which beats customer, project, and organization defaults (precedence). POST /v1/embeddings ignores bindings.

Binding toResult
A policy in another organization404
An inactive policy400
A policy scoped to a different project or customer than the key400. Bind a policy scoped to the key’s project, or an organization policy

Per-key spend limits

A key with limit and limit_reset returns 402 api_key_limit_exceeded once the current window’s spend reaches the limit. Windows reset at midnight UTC (weekly on Monday, monthly on the 1st). Each key object reports the window’s usage and limit_remaining for showing a customer their balance. See how this combines with other scopes in Budgets.

Per-key usage

Usage & spend → By attribution → API key lists each key’s requests, tokens, and spend. Management API keys record no creating user, so give each a descriptive name, such as customer-acme or alice@acme.com.

Next steps