Proxy
The proxy is the core of Codecosts. It sits between your Claude client and the Anthropic API, forwarding requests transparently while logging usage.
How it works
Section titled “How it works”Your app → POST /proxy/:slug/v1/messages → Anthropic API ↓ Usage log created (tokens, cost, bodies, timing)- You set
ANTHROPIC_BASE_URLto your proxy endpoint URL - Your Claude client sends requests to the proxy instead of
api.anthropic.com - Codecosts forwards the request unchanged, including your API key
- The response is returned to your client — streaming and non-streaming both work
- Usage is logged asynchronously (tokens, cost, duration, full request/response)
Create a proxy endpoint
Section titled “Create a proxy endpoint”Before making proxied calls, create an endpoint in Settings or via the API:
curl -X POST https://codecosts.com/api/proxy-endpoints \ -H "Authorization: Bearer $CODECOSTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "my-project"}'Response:
{ "id": "...", "name": "my-project", "slug": "my-project", "url": "https://codecosts.com/proxy/my-project", "created_at": "2026-03-17T00:00:00Z"}Send requests through the proxy
Section titled “Send requests through the proxy”POST /proxy/:slug/v1/messages
Section titled “POST /proxy/:slug/v1/messages”Same interface as the Anthropic Messages API. Your existing code works unchanged — just set the base URL.
Authentication: Pass your Anthropic API key via x-api-key header or Authorization: Bearer — Codecosts forwards it to Anthropic as-is.
Headers forwarded: All anthropic-* prefixed headers (including anthropic-version and anthropic-beta), x-stainless-* headers (SDK telemetry), x-app headers, user-agent, accept, and accept-language.
Streaming: Fully supported. When stream: true, Codecosts buffers the SSE response, extracts usage from message_start and message_delta events, then returns the full stream.
Rate limit: 300 requests per minute per proxy endpoint (by slug).
export ANTHROPIC_BASE_URL=https://codecosts.com/proxy/my-projectclaude "explain quicksort"Claude Code reads ANTHROPIC_BASE_URL automatically. No other changes needed.
import anthropic
# Option 1: env var (recommended)# export ANTHROPIC_BASE_URL=https://codecosts.com/proxy/my-projectclient = anthropic.Anthropic()
# Option 2: explicitclient = anthropic.Anthropic( base_url="https://codecosts.com/proxy/my-project")
message = client.messages.create( model="claude-haiku-4-5-20251001", max_tokens=1024, messages=[{"role": "user", "content": "Hello"}])import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ baseURL: "https://codecosts.com/proxy/my-project",});
const message = await client.messages.create({ model: "claude-haiku-4-5-20251001", max_tokens: 1024, messages: [{ role: "user", content: "Hello" }],});curl https://codecosts.com/proxy/my-project/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-haiku-4-5-20251001", "max_tokens": 100, "messages": [{"role": "user", "content": "Hello"}] }'POST /proxy/:slug/v1/messages/count_tokens
Section titled “POST /proxy/:slug/v1/messages/count_tokens”Passthrough to the Anthropic Count Tokens API. Same authentication and header forwarding as the messages endpoint. No usage logging is performed.
Rate limit: 600 requests per minute per proxy endpoint (by slug).
curl https://codecosts.com/proxy/my-project/v1/messages/count_tokens \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-haiku-4-5-20251001", "messages": [{"role": "user", "content": "Hello, how are you?"}] }'What gets logged
Section titled “What gets logged”Every proxied request to /v1/messages creates a usage log entry with:
| Field | Description |
|---|---|
model | The model used (from the response, not the request) |
input_tokens | Input tokens consumed |
output_tokens | Output tokens generated |
cache_creation_input_tokens | Tokens used for prompt cache creation |
cache_read_input_tokens | Tokens read from prompt cache |
cost_cents | Calculated cost based on model pricing |
duration_ms | Round-trip time to Anthropic |
status_code | HTTP status from Anthropic |
request_body | Full JSON request (model, messages, tools, system) |
response_body | Full response — JSON for non-streaming, raw SSE for streaming |
Failed requests (4xx, 5xx from Anthropic) are also logged with the error body.
Proxy endpoints API
Section titled “Proxy endpoints API”List endpoints
Section titled “List endpoints”GET /api/proxy-endpointsReturns a paginated list of proxy endpoints for the authenticated user’s organization.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
cursor | string | Pagination cursor from previous response |
limit | number | Items per page (1–100, default 20) |
Response:
{ "items": [ { "id": "...", "name": "my-project", "slug": "my-project", "url": "https://codecosts.com/proxy/my-project", "created_at": "2026-03-17T00:00:00Z" } ], "nextCursor": null, "hasMore": false}Create endpoint
Section titled “Create endpoint”POST /api/proxy-endpoints{ "name": "production", "slug": "production" }slug is optional — if omitted, it’s generated from the name. Must be lowercase alphanumeric with hyphens.
Delete endpoint
Section titled “Delete endpoint”DELETE /api/proxy-endpoints/:id{ "ok": true }