Skip to navigation

Embedded Routing Stack

For platforms reselling Gateway: give each end customer its own routing, keys, budget, and usage

Embedded Routing gives each of your end customers its own routing, vendor keys, and spend limits under your one organization. Use it when you resell Gateway to tenants without dashboard accounts. The /v1/customers endpoints take your organization-level key (Bearer mg_...), derive the organization from it, and use UUIDs for every ID. See the Embedded Routing API reference for schemas.

How the pieces fit

A request scoped to a Customer uses everything below it.

ObjectRole at request time
CustomerThe tenant. Its status and key usage mode apply to every request.
Routing policyPicks the model when the request doesn’t pin one
Customer keyThe customer’s own vendor credential. The key usage mode decides whether it, your key, or Merge-managed credentials serve.
Customer API keyA Gateway key you give the customer, which scopes its requests automatically
BudgetCaps the customer’s spend
GuardrailsPrompt injection and DLP overrides on your organization’s policy
UsageThe customer’s spend, split by whose credential served it

PUT /v1/customers/{customer_id}/controls sets per-customer vendor, region, and ZDR controls, which override organization settings and work like project-scoped controls: send only the fields you override, and DELETE to inherit again.

Sending requests

Set customer to the Customer’s id, send your own ID in the X-Merge-Customer-Origin-Id header (which creates the customer on first use), or use the customer’s API key. Routing then depends on model and routing_policy_id:

RequestRoutes via
customer, no modelThe customer’s default policy, else your organization’s default
customer and routing_policy_id, no modelThat policy
customer and modelThat model directly. Keys, budget, and usage still apply.
curl https://api-gateway.merge.dev/v1/responses \
-H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": "9f8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"routing_policy_id": "2a1b3c4d-5e6f-4708-9a0b-1c2d3e4f5a6b",
"input": [
{"type": "message", "role": "user", "content": "Summarize this ticket in one sentence."}
]
}'

The OpenAI, Anthropic, LangChain, and AI SDK surfaces accept both fields in the body; since those SDKs require a model, send default_routing to let the policy route. Any endpoint also accepts X-Merge-Customer and X-Merge-Routing-Policy-Id headers, which can’t override a customer API key’s scope. X-Merge-Customer is unrelated to the tracing tag X-Customer-ID.

Combining customer with a project scope (a project API key, X-Project-Id, or project_id) returns 400 customer_project_conflict. Non-streaming responses name the serving policy in x-merge-routing-policy-id.

Listing a customer’s allowed models

GET /v1/customers/{customer_id}/models returns what the customer can route to after its controls, key usage mode, and your organization’s vendor access apply, for use in a model picker.

{
"scope": "customer",
"scope_id": "9f8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"restrictions_active": true,
"key_usage_mode": "byok_only",
"models": [
{ "model": "openai/gpt-5.6-sol", "provider": "openai", "vendors": ["openai"] },
{ "model": "mistral/mistral-large-2512", "provider": "mistral", "vendors": ["mistral"] }
],
"gated_model_ids": []
}

vendors lists the hosts that can serve each model; gated_model_ids are allowed by the customer’s controls but not your organization’s vendor access. key_usage_mode is lowercase here, uppercase on the Customer. GET /v1/models with a customer API key or X-Merge-Customer returns the same list.

Status codes

Statustype or codeWhen
400customer_project_conflictThe request combines customer with a project scope
400customer_mismatch, routing_policy_mismatchA header conflicts with the body or with a customer API key
400invalid_customer, invalid_routing_policy_idA header value isn’t a UUID
400invalid_customer_origin_idX-Merge-Customer-Origin-Id is empty or longer than 255 characters
401authentication_errorMissing or invalid Gateway key
402budget_exceededThe customer’s HARD budget is exhausted
403permission_errorThe customer is inactive or deleted
403customer_scoped_key_forbiddenA customer API key called an organization-level endpoint
403customer_limit_reachedX-Merge-Customer-Origin-Id would create a customer past your organization’s limit
403customer_deletedMinting a key by origin_id for a customer that was deleted
404customer_not_foundNo customer in your organization has that UUID
404provider_credentials_missingBYOK_ONLY or CUSTOMER_ONLY left no credential for the vendor
409Duplicate origin_id, a second budget, or a sixth customer API key
422Validation, such as a customer body field that isn’t a UUID
503internal_errorThe customer’s configuration couldn’t be read. Retry.

Streaming requests get these as HTTP statuses when the failure precedes the first token, and as an in-band response.error frame (Streaming) after.

Next steps