> This page is for Gateway.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.merge.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.merge.dev/_mcp/server.

# Customer keys

> Add, rotate, and remove a customer's own bring-your-own-key vendor credential, and choose which credentials may serve that customer.

A customer key is a customer's own vendor credential, such as their OpenAI key, that you hold for them. Add one when a tenant wants its traffic billed to its own vendor account.

> **Info**
>
> To give the customer a Gateway key of its own, see [Customer API keys](/merge-gateway/embedded-routing-stack/customer-api-keys).

## Key usage modes

Set the mode with `key_usage_default` on the [customer](/merge-gateway/embedded-routing-stack/customers); unset inherits your organization's default.

| Mode            | Credentials that can serve a vendor, in order                                            |
| --------------- | ---------------------------------------------------------------------------------------- |
| `USE_ANY`       | The customer's key, then your organization's key, then Merge-managed credentials         |
| `PREFER_BYOK`   | A customer or organization key, falling back to Merge-managed credentials                |
| `BYOK_ONLY`     | The customer's key, then your organization's key. Merge-managed credentials never serve. |
| `CUSTOMER_ONLY` | The customer's key only                                                                  |

`BYOK_ONLY` and `CUSTOMER_ONLY` fail closed, returning `404` `provider_credentials_missing` when no allowed credential exists for the vendor. Use `CUSTOMER_ONLY` when each tenant must run strictly on its own vendor account.

## Add or rotate a key

`POST /v1/customers/{customer_id}/keys` with the vendor slug (`openai`, `anthropic`). Gateway test-calls the vendor and returns `400` if the key is rejected, the slug is unknown, or the vendor doesn't accept BYOK.

**`cURL`**

```bash title="cURL"
curl -X POST https://api-gateway.merge.dev/v1/customers/{customer_id}/keys \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "vendor": "openai", "api_key": "sk-..." }'
```

A customer holds one key per vendor. The first `POST` returns `201`; a later `POST` for the same vendor rotates the key in place and returns `200`. Secrets are never returned. `DELETE /v1/customers/{customer_id}/keys/{key_id}` removes a customer-owned key.

## List keys

`GET /v1/customers/{customer_id}/keys` returns the credential that would serve each vendor under the customer's mode, omitting vendors with no allowed credential. The customer's own API key sees only `CUSTOMER` entries.

| Field                       | Description                                                |
| --------------------------- | ---------------------------------------------------------- |
| `id`                        | Credential ID. Pass it to `DELETE` for a `CUSTOMER` entry. |
| `vendor`                    | Vendor slug                                                |
| `key_ownership`             | `CUSTOMER`, `ORGANIZATION`, or `MERGE`                     |
| `created_at`, `modified_at` | Timestamps. `null` for `MERGE` entries.                    |

## Next steps

#### [Customer API keys](/merge-gateway/embedded-routing-stack/customer-api-keys)

Give a customer its own scoped Gateway key

#### [Usage](/merge-gateway/embedded-routing-stack/usage)

See spend split by who supplied the credential