NullSpend Docs

proxy-endpoints

Proxy Endpoints

The NullSpend proxy sits between your agents and upstream providers. It authenticates requests, tracks costs, and enforces budgets transparently.

Base URL: https://proxy.nullspend.dev


Provider Routes

MethodPathProviderDefault Upstream
POST/v1/chat/completionsOpenAIhttps://api.openai.com
POST/v1/messagesAnthropichttps://api.anthropic.com
POST/v1/mcp/budget/checkMCPNone (local)
POST/v1/mcp/eventsMCPNone (local)

All provider routes require an X-NullSpend-Key header. Unsupported /v1/* paths return 404 not_found. Non-POST methods return 404.

OpenAI (/v1/chat/completions)

Forwards to https://api.openai.com/v1/chat/completions (or custom upstream). Headers forwarded to the upstream provider:

  • authorization — Your OpenAI API key
  • openai-organization
  • openai-project
  • traceparent, tracestate — W3C trace context

Supports both streaming and non-streaming responses.

Anthropic (/v1/messages)

Forwards to https://api.anthropic.com/v1/messages (or custom upstream). Headers forwarded:

  • x-api-key or authorization — Your Anthropic API key
  • anthropic-version — Defaults to 2023-06-01 if not provided
  • anthropic-beta
  • traceparent, tracestate

Supports both streaming and non-streaming responses.

MCP (/v1/mcp/budget/check, /v1/mcp/events)

Local endpoints for MCP server integrations. /budget/check performs a pre-request budget check. /events ingests cost events from MCP tool calls.


Health Endpoints

No authentication required.

MethodPathResponse
GET/health{ "status": "ok", "service": "nullspend-proxy" }
GET/health/metricsAnalytics Engine metrics (JSON or Prometheus, based on Accept header)
GET/health/ready{ "status": "ok", "service": "nullspend-proxy" } — simple readiness check

Internal Endpoints

These use shared secret authentication (not API keys) and are not for external use.

MethodPathPurpose
POST/internal/budget/invalidateInvalidate budget cache for a user
GET/internal/budget/velocity-stateQuery velocity limit state

Upstream Allowlist

When overriding the upstream provider with the X-NullSpend-Upstream header, only these URLs are accepted:

URLProvider
https://api.openai.comOpenAI (default)
https://api.groq.com/openaiGroq
https://api.together.xyzTogether AI
https://api.fireworks.ai/inferenceFireworks AI
https://api.mistral.aiMistral
https://openrouter.ai/apiOpenRouter

Invalid upstream URLs return 400 invalid_upstream. Perplexity is excluded because it doesn't use the /v1/ prefix in its URL structure.


Body Size Limit

Maximum request body: 1 MB (1,048,576 bytes).

Enforced in two places:

  1. Pre-readContent-Length header checked before reading the body
  2. Post-read — Actual byte count verified after reading

Exceeding either check returns 413 payload_too_large.

Response body logging (Pro/Enterprise) also caps at 1 MB. Streaming responses exceeding 1 MB are truncated in the stored body; the client receives the full response regardless.


Request Processing Pipeline

Every request follows this exact order:

  1. Trace ID resolution — Always runs, even on errors. Sets X-NullSpend-Trace-Id on the response.
  2. Health routes — No auth. Returns immediately for /health, /health/metrics, /health/ready.
  3. Internal routes — Shared secret auth. Returns immediately for /internal/*.
  4. Route lookup — POST only. Unknown /v1/* paths return 404.
  5. Rate limiting + API key authentication — Run in parallel via Promise.all. Rate limiting checks IP then key limits (Rate Limits). Auth does SHA-256 hash lookup (Authentication).
  6. Body parsing — JSON validation and size check. Runs sequentially after auth and rate limiting complete.
  7. Context construction — Resolves webhooks, API version, session ID, tags, and trace context.
  8. Route handler — Budget check → upstream call → cost tracking → reconciliation.

On this page