Customer API keys

Give each customer its own Merge Gateway key

A customer API key is a Merge Gateway access key bound to one customer. Every request it authenticates is scoped to that customer automatically: their routing policies, key-usage mode, budget, and usage attribution all apply, and no customer field is sent in the request body.

This is what you hand to each of your own tenants. Store it as that tenant’s credential, and a leaked key exposes exactly one tenant instead of your whole organization.

Not to be confused with Customer keys, which are a customer’s own provider credentials (OpenAI, Anthropic, and so on). Those are keys you hold for the customer; these are keys you give to the customer.

Path: /v1/customers/{customer_id}/api-keys. Requires an organization-level production key: a customer-scoped key cannot mint keys.

Fields

FieldDescriptionType
idKey identifier. Pass this to DELETEstring
customerThe customer this key is bound to (immutable)string
nameYour label for the keystring
key_prefixFirst characters of the key, for identifying it in a liststring
spending_limitPer-key spend cap over reset_period, independent of the customer’s budgetnumber
reset_perioddaily, weekly, or monthly. Requires spending_limitenum
rate_limit_rpm, rate_limit_tpmPer-key rate limitsinteger
created_at, expires_atTimestampsdatetime

Mint a key

The raw key comes back once, in the key field of the create response. It is stored hashed, so it can never be read again — a lost key is replaced, not recovered.

$curl -X POST https://api-gateway.merge.dev/v1/customers/{customer_id}/api-keys \
> -H "Authorization: Bearer mg_<your_production_key>" \
> -H "Content-Type: application/json" \
> -d '{ "name": "Acme production", "spending_limit": 100, "reset_period": "monthly" }'

A customer can hold up to 5 keys. Requests then need no customer field:

$curl -X POST https://api-gateway.merge.dev/v1/responses \
> -H "Authorization: Bearer mg_<the_customer_key>" \
> -H "Content-Type: application/json" \
> -d '{ "model": "openai/gpt-5.5", "input": "Hello" }'

Sending a customer that contradicts the key returns 400 customer_mismatch. Sending the matching value is accepted and ignored.

Rotate a key

Rotation is create-then-delete, so the customer never loses access mid-swap: mint the new key, move the customer onto it, then revoke the old one.

Python
1fresh = client.customers.api_keys.create(customer_id, name="Acme production 2")
2# ... move the customer onto fresh.key, then:
3client.customers.api_keys.delete(customer_id, old_key_id)

What a customer key can reach

A customer key is not a general-purpose organization key. On the management API it reaches only routes for its own customer, and requests for any other customer return 404 rather than 403, so one customer cannot discover the others.

AllowedNot allowed
Read its own customer, budget, routing policies, keys, and usageListing or creating customers, or reading org-wide usage
Rename itselfChanging its own key-usage mode or status
Manage its own routing policiesChanging or removing its own budget
Add and rotate its own provider (BYOK) keysDeleting itself, or minting API keys

Its usage response is also narrowed to customer_byok_spend and request_count: the spend breakdowns describe what you pay Merge, so they are organization-level figures and are not exposed to the customer. Its provider-key list likewise shows only the keys the customer supplied, not which vendors your organization holds keys for.

Revoke a key

cURL
$curl -X DELETE https://api-gateway.merge.dev/v1/customers/{customer_id}/api-keys/{key_id} \
> -H "Authorization: Bearer mg_<your_production_key>"

Deleting a customer revokes its keys automatically. Deactivating a customer stops its keys serving traffic (403) without deleting them, so reactivating restores access with the same keys.