Quick Start
- Register or log in at MeterLayer.
- Add your OpenAI key in Settings - Providers.
- Create a project in Projects.
- Copy the generated project API key.
- Use
baseURL: https://meterlayer.io/v1in OpenAI-compatible clients. - Run a low-token test in Dashboard Playground.
Machine-readable API spec: OpenAPI JSON.
Authentication
Proxy calls use a project API key, not a user session. Keep this key on your server. Do not expose it in browser JavaScript, mobile apps, or public repos.
Authorization: Bearer <project_api_key>
Content-Type: application/jsonOpenAI-Compatible Endpoint
Existing OpenAI clients can use the gateway by changing the base URL and API key. The project API key goes into the normal OpenAI SDK apiKey field.
POST https://meterlayer.io/v1/chat/completionsimport OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.AI_COST_GATEWAY_PROJECT_KEY,
baseURL: "https://meterlayer.io/v1"
});
const completion = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Reply with one word: OK" }],
max_tokens: 5,
temperature: 0.2,
metadata: {
feature: "first-smoke-test",
customerId: "internal-test"
}
});The endpoint accepts model,messages,max_tokens, generation options such as temperature and optionalmetadata. Streaming is not supported yet.
Gateway-Native Endpoint
The gateway validates the project key, checks project status, model allow-list, budget, rate limit and provider credential, then forwards the request to OpenAI.
{
"provider": "openai",
"model": "gpt-4o-mini",
"messages": [
{ "role": "user", "content": "Hello" }
],
"maxOutputTokens": 1024,
"temperature": 0.2,
"topP": 0.9,
"metadata": {
"userId": "optional-user-id",
"feature": "email-generator",
"customerId": "optional-customer-id"
}
}| Field | Type | Required | Notes |
|---|---|---|---|
provider | "openai" | "anthropic" | "gemini" | Yes | MVP forwards OpenAI requests. Other providers are reserved for the provider abstraction. |
model | string | Yes | Must be enabled in project settings. |
messages | array | Yes | 1-100 messages. Roles: system, user, assistant. |
maxOutputTokens | integer | No | Defaults server-side. Requests above the configured limit are rejected. |
metadata | object | No | Stored with logs. Use feature, userId, customerId, tenantId, or similar routing context. |
Response
On success, the body is the provider response. MeterLayer adds response headers with request ID, estimated cost and rate-limit information.
| Header | Meaning |
|---|---|
X-AI-Cost-Gateway-Request-Id | Request ID for finding the entry in logs. |
X-AI-Cost-Gateway-Cost | Estimated request cost in USD on successful provider responses. |
X-AI-Cost-Gateway-Remaining | Compatibility alias for remaining requests in the current rate-limit window. |
X-AI-Cost-Gateway-RateLimit-Remaining | Remaining requests in the current rate-limit window. |
X-AI-Cost-Gateway-RateLimit-Reset | ISO timestamp when the current rate-limit window resets. |
X-AI-Cost-Gateway-RateLimit-Backend | upstash, postgres, or memory. |
Rate-limit headers are included after the project API key is validated and the project rate-limit check has run.
{
"id": "chatcmpl_...",
"object": "chat.completion",
"model": "gpt-4o-mini",
"choices": [
{
"message": {
"role": "assistant",
"content": "Hello! How can I help?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 7,
"total_tokens": 16
}
}Examples
curl
curl -X POST https://meterlayer.io/api/proxy/chat \
-H "Authorization: Bearer $AI_COST_GATEWAY_PROJECT_KEY" \
-H "Content-Type: application/json" \
-H "X-Request-Id: demo-request-001" \
-d '{
"provider": "openai",
"model": "gpt-4o-mini",
"messages": [
{ "role": "system", "content": "You write concise product copy." },
{ "role": "user", "content": "Write one sentence about an AI cost dashboard." }
],
"maxOutputTokens": 200,
"metadata": {
"feature": "product-description",
"customerId": "customer-123"
}
}'TypeScript
const response = await fetch("https://meterlayer.io/api/proxy/chat", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AI_COST_GATEWAY_PROJECT_KEY}`,
"Content-Type": "application/json",
"X-Request-Id": crypto.randomUUID()
},
body: JSON.stringify({
provider: "openai",
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello" }],
metadata: {
userId: "user-123",
feature: "chat"
}
})
});
const data = await response.json();
if (!response.ok) throw new Error(data.error);
return data;First Customer Smoke
Use this sequence for the first production feature routed through MeterLayer. Keep the project API key in a backend secret manager, set a conservative project budget, and restrict allowed models before sending traffic.
- Add the customer OpenAI key in Settings - Providers and run the provider test.
- Create a project for the app or environment, for example
web-prod. - Copy the project API key once and store it server-side.
- Send one low-token smoke request with
metadata.feature. - Open Logs, Prompts, Models and Budgets.
- Record
X-AI-Cost-Gateway-Request-Idfor support.
const completion = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Reply with one word: OK" }],
max_tokens: 16,
metadata: {
feature: "first-customer-smoke",
customerId: "internal-test"
}
});Rollback is simple: restore the original OpenAI API key and base URL in the customer application. Support should ask for timestamp, project, model, feature and request ID, not provider keys, project keys, full prompts or personal data.
Request IDs
Send a unique X-Request-Id for retries and traceability. If the same project sends the same ID again, the gateway returns 409 Duplicate request ID.
Errors
Error responses include an error message andrequestId. Validation failures also include details.
{
"error": "Provider or model is not allowed for this project.",
"requestId": "req_..."
}| Status | Meaning |
|---|---|
400 | Invalid body, missing provider credential, or invalid proxy setting. |
401 | Missing or invalid project API key. |
402 | Monthly budget exceeded or projected output cost would exceed budget. |
403 | Project disabled, or provider/model is not allowed. |
409 | Duplicate X-Request-Id. |
413 | Request body is too large. |
429 | Project rate limit exceeded. |
502 | Provider response was invalid or missing usage data. |
504 | Provider request timed out. |
Pricing
| Model | Input per 1M | Output per 1M |
|---|---|---|
gpt-4o-mini | USD 0.15 | USD 0.60 |
gpt-4o | USD 5.00 | USD 15.00 |
inputCost = inputTokens / 1_000_000 * inputPer1M
outputCost = outputTokens / 1_000_000 * outputPer1M
totalCost = inputCost + outputCost