Skip to content

Proxy

The proxy is the core of Codecosts. It sits between your Claude client and the Anthropic API, forwarding requests transparently while logging usage.

Your app → POST /proxy/:slug/v1/messages → Anthropic API
Usage log created
(tokens, cost, bodies, timing)
  1. You set ANTHROPIC_BASE_URL to your proxy endpoint URL
  2. Your Claude client sends requests to the proxy instead of api.anthropic.com
  3. Codecosts forwards the request unchanged, including your API key
  4. The response is returned to your client — streaming and non-streaming both work
  5. Usage is logged asynchronously (tokens, cost, duration, full request/response)

Before making proxied calls, create an endpoint in Settings or via the API:

Terminal window
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"
}

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).

Terminal window
export ANTHROPIC_BASE_URL=https://codecosts.com/proxy/my-project
claude "explain quicksort"

Claude Code reads ANTHROPIC_BASE_URL automatically. No other changes needed.

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).

Terminal window
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?"}]
}'

Every proxied request to /v1/messages creates a usage log entry with:

FieldDescription
modelThe model used (from the response, not the request)
input_tokensInput tokens consumed
output_tokensOutput tokens generated
cache_creation_input_tokensTokens used for prompt cache creation
cache_read_input_tokensTokens read from prompt cache
cost_centsCalculated cost based on model pricing
duration_msRound-trip time to Anthropic
status_codeHTTP status from Anthropic
request_bodyFull JSON request (model, messages, tools, system)
response_bodyFull response — JSON for non-streaming, raw SSE for streaming

Failed requests (4xx, 5xx from Anthropic) are also logged with the error body.

GET /api/proxy-endpoints

Returns a paginated list of proxy endpoints for the authenticated user’s organization.

Query parameters:

ParameterTypeDescription
cursorstringPagination cursor from previous response
limitnumberItems 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
}
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 /api/proxy-endpoints/:id
{ "ok": true }