Gateway API Reference
The Curate-Me AI Gateway is an OpenAI-compatible reverse proxy that adds governance,
cost tracking, and observability to LLM requests. It runs on port 8002 and is available
at https://api.curate-me.ai.
Authentication
All requests require a Curate-Me API key. There are three ways to provide it:
| Method | Header / Parameter | Priority |
|---|---|---|
| Explicit header | X-CM-API-Key: cm_sk_your_key | 1 (highest) |
| Bearer token | Authorization: Bearer cm_sk_your_key | 2 |
| Query parameter | ?api_key=cm_sk_your_key | 3 (SSE/EventSource only) |
Key prefixes: API keys start with cm_sk_, cm_gw_, or cm_. Runner tokens use the
cm_rt_ prefix.
Provider key: The upstream provider’s API key can be sent via:
X-Provider-Key: sk-your-openai-key(preferred, explicit)Authorization: Bearer sk-your-openai-key(when the gateway key is inX-CM-API-Key)- Stored in the gateway (no provider key needed per-request)
Dashboard JWT fallback: The gateway also accepts dashboard JWTs via
Authorization: Bearer <jwt> for admin endpoints called from the dashboard UI.
Authentication errors
{
"error": {
"message": "Missing or invalid credentials.",
"type": "authentication_error",
"code": "invalid_api_key",
"gateway_error_code": "GW_AUTH_001"
}
}| Error Code | Status | Meaning |
|---|---|---|
GW_AUTH_001 | 401 | Missing or unrecognized credentials |
GW_AUTH_002 | 401 | Invalid, expired, or revoked API key |
GW_AUTH_003 | 401 | API key has been rotated; use the replacement |
GW_AUTH_004 | 403 | Client IP not in the key’s IP allowlist |
Proxy endpoints
These endpoints accept the same request format as the upstream provider and forward the request through the governance chain.
POST /v1/chat/completions
OpenAI-compatible chat completions. Works with OpenAI, DeepSeek, Groq, Mistral, xAI, Together, Fireworks, and any provider that uses the OpenAI format.
curl https://api.curate-me.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Authorization: Bearer sk-your-openai-key" \
-d '{
"model": "gpt-4o",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
],
"stream": false
}'Streaming:
curl https://api.curate-me.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Authorization: Bearer sk-your-openai-key" \
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "Tell me a joke"}],
"stream": true
}'The gateway passes SSE chunks through transparently. Token usage is extracted from the
final [DONE] chunk for cost recording.
POST /v1/messages
Anthropic-compatible messages endpoint.
curl https://api.curate-me.ai/v1/messages \
-H "Content-Type: application/json" \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "X-Provider-Key: sk-ant-your-key" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-4-20250514",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, Claude!"}
]
}'POST /v1/embeddings
OpenAI-compatible embeddings endpoint.
curl https://api.curate-me.ai/v1/embeddings \
-H "Content-Type: application/json" \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Authorization: Bearer sk-your-openai-key" \
-d '{
"model": "text-embedding-3-small",
"input": "The quick brown fox"
}'GET /v1/models
List available models from all configured providers. Returns an OpenAI-compatible model list.
curl https://api.curate-me.ai/v1/models \
-H "X-CM-API-Key: cm_sk_your_key"GET /v1/health
Gateway health check. Returns status and active provider count.
curl https://api.curate-me.ai/v1/health \
-H "X-CM-API-Key: cm_sk_your_key"Response headers
Every proxied response includes governance metadata headers:
| Header | Type | Description |
|---|---|---|
X-CM-Request-ID | string | Unique request identifier for tracing |
X-CM-Cost | float | Estimated cost for this request (USD) |
X-CM-Daily-Cost | float | Cumulative daily spend for the org (USD) |
X-CM-Daily-Budget | float | Daily budget limit for the org (USD) |
X-CM-Governance-Time-Ms | float | Time spent in governance checks (ms) |
X-RateLimit-Limit | int | Max requests per minute |
X-RateLimit-Remaining | int | Requests remaining in current window |
X-RateLimit-Reset | int | Unix timestamp when the window resets |
X-CM-Approval-ID | string | Approval ID (only when HITL triggers, status 202) |
Admin endpoints
Admin endpoints are prefixed with /gateway/admin/ and require an API key with admin scopes.
Policies
GET /gateway/admin/policies
List governance policies. Returns the policy for the authenticated org.
curl https://api.curate-me.ai/gateway/admin/policies \
-H "X-CM-API-Key: cm_sk_your_key"GET /gateway/admin/policies/{org_id}
Get the governance policy for a specific org.
curl https://api.curate-me.ai/gateway/admin/policies/org_abc123 \
-H "X-CM-API-Key: cm_sk_your_key"PUT /gateway/admin/policies/{org_id}
Create or replace a governance policy. Full document replacement (PUT semantics).
curl -X PUT https://api.curate-me.ai/gateway/admin/policies/org_abc123 \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Content-Type: application/json" \
-d '{
"rpm_limit": 100,
"daily_budget": 50.00,
"monthly_budget": 1000.00,
"max_cost_per_request": 2.00,
"pii_scan_enabled": true,
"pii_action": "block",
"allowed_models": [],
"hitl_cost_threshold": 10.00
}'DELETE /gateway/admin/policies/{org_id}
Delete a governance policy, reverting to tier defaults.
curl -X DELETE https://api.curate-me.ai/gateway/admin/policies/org_abc123 \
-H "X-CM-API-Key: cm_sk_your_key"POST /gateway/admin/policies/simulate
Simulate a draft policy against recent traffic. Returns how many requests would have been blocked and by which governance step.
curl -X POST https://api.curate-me.ai/gateway/admin/policies/simulate \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Content-Type: application/json" \
-d '{
"draft_policy": {"rpm_limit": 30, "daily_budget": 10.00},
"replay_hours": 24
}'API Keys
GET /gateway/admin/keys
List gateway API keys for the org. Returns metadata only — key secrets are never included.
curl https://api.curate-me.ai/gateway/admin/keys \
-H "X-CM-API-Key: cm_sk_your_key"POST /gateway/admin/keys
Create a new gateway API key. The plaintext key is returned only once in the response.
curl -X POST https://api.curate-me.ai/gateway/admin/keys \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "production-api",
"scopes": ["proxy", "admin"]
}'Secrets (stored provider keys)
POST /gateway/admin/secrets
Store a provider API key encrypted in the gateway. After storing, requests to that provider
no longer need an X-Provider-Key header.
curl -X POST https://api.curate-me.ai/gateway/admin/secrets \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"plaintext_key": "sk-your-openai-key",
"label": "Production OpenAI key"
}'GET /gateway/admin/secrets
List stored provider secrets (metadata only, never plaintext).
curl https://api.curate-me.ai/gateway/admin/secrets \
-H "X-CM-API-Key: cm_sk_your_key"POST /gateway/admin/secrets/rotate
Rotate a stored provider secret. The old key is revoked and the new one is encrypted.
curl -X POST https://api.curate-me.ai/gateway/admin/secrets/rotate \
-H "X-CM-API-Key: cm_sk_your_key" \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"plaintext_key": "sk-new-openai-key"
}'DELETE /gateway/admin/secrets/{provider}
Revoke a stored provider secret. After revocation, requests will need explicit
X-Provider-Key headers again.
curl -X DELETE https://api.curate-me.ai/gateway/admin/secrets/openai \
-H "X-CM-API-Key: cm_sk_your_key"Usage and Costs
GET /gateway/admin/usage
Get gateway usage records.
| Parameter | Type | Default | Description |
|---|---|---|---|
days | int | 7 | Look-back period (1-90) |
limit | int | 100 | Max records to return (1-1000) |
curl "https://api.curate-me.ai/gateway/admin/usage?days=7&limit=50" \
-H "X-CM-API-Key: cm_sk_your_key"GET /gateway/admin/usage/daily
Get daily cost breakdown.
| Parameter | Type | Default | Description |
|---|---|---|---|
days | int | 30 | Number of days to retrieve (1-90) |
curl "https://api.curate-me.ai/gateway/admin/usage/daily?days=30" \
-H "X-CM-API-Key: cm_sk_your_key"GET /gateway/admin/usage/{request_id}
Get a single usage record by request ID.
curl "https://api.curate-me.ai/gateway/admin/usage/gw_a1b2c3d4" \
-H "X-CM-API-Key: cm_sk_your_key"Latency
GET /gateway/admin/latency
Get request latency statistics (p50, p95, p99) broken down by provider and model.
curl https://api.curate-me.ai/gateway/admin/latency \
-H "X-CM-API-Key: cm_sk_your_key"Approvals (HITL)
GET /gateway/admin/approvals/{approval_id}
Check the status of a HITL approval request.
curl https://api.curate-me.ai/gateway/admin/approvals/apr_abc123 \
-H "X-CM-API-Key: cm_sk_your_key"Response:
{
"approval_id": "apr_abc123",
"status": "pending",
"estimated_cost": 12.50,
"model": "gpt-5.1",
"retry_after_seconds": 30,
"created_at": "2026-03-17T14:32:01Z"
}Possible status values: pending, approved, rejected, expired.
Provider Targets
GET /gateway/admin/provider-targets
List all configured provider targets for the org.
curl https://api.curate-me.ai/gateway/admin/provider-targets \
-H "X-CM-API-Key: cm_sk_your_key"POST /gateway/admin/provider-targets/{provider_id}/discover-models
Trigger model discovery on a provider. Returns discovered model IDs.
curl -X POST https://api.curate-me.ai/gateway/admin/provider-targets/openai/discover-models \
-H "X-CM-API-Key: cm_sk_your_key"Discovery
GET /gateway/admin/discovery/catalog
List discovered models across all providers.
| Parameter | Type | Default | Description |
|---|---|---|---|
provider_id | string | - | Filter by provider |
limit | int | 200 | Max results (1-1000) |
cursor | string | - | Pagination cursor |
curl "https://api.curate-me.ai/gateway/admin/discovery/catalog?limit=50" \
-H "X-CM-API-Key: cm_sk_your_key"GET /gateway/admin/discovery/history
List discovery run audit history.
curl "https://api.curate-me.ai/gateway/admin/discovery/history?limit=10" \
-H "X-CM-API-Key: cm_sk_your_key"Error response format
All gateway errors use the OpenAI-compatible error format:
{
"error": {
"message": "Human-readable description",
"type": "error_type",
"param": null,
"code": "error_code",
"gateway_error_code": "GW_XXX_NNN",
"remediation": "How to fix the issue"
}
}Error code reference
| Code | Status | Meaning |
|---|---|---|
GW_AUTH_001 | 401 | Missing credentials |
GW_AUTH_002 | 401 | Invalid or expired API key |
GW_AUTH_003 | 401 | Key has been rotated |
GW_AUTH_004 | 403 | IP not in allowlist |
GW_RATE_001 | 429 | Rate limit exceeded |
GW_PLAN_001 | 403 | Inactive subscription |
GW_PLAN_002 | 429 | Plan quota exceeded |
GW_PLAN_003 | 403 | Model not available on plan |
GW_COST_001 | 403 | Per-request cost exceeds limit |
GW_COST_002 | 403 | Daily budget exhausted |
GW_COST_003 | 403 | Monthly budget exhausted |
GW_PII_001 | 403 | PII detected in request |
GW_SAFETY_001 | 403 | Content safety violation |
GW_MODEL_001 | 403 | Model not in allowlist |
GW_SESSION_BUDGET_001 | 403 | Runner session budget exceeded |
GW_BUDGET_HIERARCHY_001 | 403 | Hierarchical budget exceeded |
Rate limit headers
Rate limit headers are included on every response (both allowed and denied):
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1708642860When rate-limited, the response also includes:
Retry-After: 18The Retry-After value is in seconds.
Supported providers
The gateway supports 50+ LLM providers. The provider is determined by the model name or by explicit routing via provider targets. Major providers include:
| Provider | Models | Format |
|---|---|---|
| OpenAI | GPT-4o, GPT-5.1, o1, o3 | OpenAI |
| Anthropic | Claude Sonnet 4, Opus 4, Haiku 3.5 | Anthropic Messages |
| Gemini 2.5 Pro, Flash | OpenAI-compatible | |
| DeepSeek | DeepSeek Chat, Reasoner | OpenAI-compatible |
| Groq | Llama, Mixtral | OpenAI-compatible |
| Mistral | Mistral Large, Medium | OpenAI-compatible |
| xAI | Grok | OpenAI-compatible |
| Together | Open-source models | OpenAI-compatible |
| Fireworks | Open-source models | OpenAI-compatible |
| Cohere | Command R+ | OpenAI-compatible |
| OpenRouter | Multi-provider routing | OpenAI-compatible |
See the full provider list at Gateway > Providers.