---
metadata: '{"name":"clawproxy","version":"1","description":"Gateway proxy that issues signed receipts (proof-of-harness) for LLM model calls.","endpoints":[{"method":"POST","path":"/v1/proxy/:provider"},{"method":"POST","path":"/v1/chat/completions"},{"method":"POST","path":"/v1/responses"},{"method":"POST","path":"/v1/messages"},{"method":"GET","path":"/v1/receipt/:nonce"},{"method":"GET","path":"/v1/did"},{"method":"POST","path":"/v1/verify-receipt"}]}'
---

# clawproxy

Proxy requests to supported LLM providers and receive a signed receipt for each call.

## HTTP API

- POST /v1/proxy/:provider
- POST /v1/chat/completions (OpenAI-compatible)
- POST /v1/responses (OpenAI Responses API)
- POST /v1/messages (Anthropic-compatible)
- GET /v1/receipt/:nonce
- GET /v1/did
- POST /v1/verify-receipt

## Authentication

### Proxy auth (CST)
- `X-CST: <CST>` (recommended)
- `X-Scoped-Token: <CST>` (alternate)
- `Authorization: Bearer <CST>` (legacy fallback; only when `STRICT_AUTH_HEADERS=false`)
- A valid CST token is required for proxy calls when `PROXY_REQUIRE_CST=true` (default fail-closed).
- Canonical chain claims are required when `PROXY_REQUIRE_CANONICAL_CST=true` (default fail-closed): `owner_did`, `controller_did`, `agent_did`, `token_lane=canonical`.
- The gateway recomputes and verifies `token_scope_hash_b64u` from canonical token claims (including chain claims + `payment_account_did` when present) (fail-closed).

### BYOK provider keys
- Recommended (all providers): `X-Provider-API-Key: <provider api key>` (raw or `Bearer <key>`)
- Legacy provider-compatible headers (non-strict mode only):
  - `Authorization: Bearer <openai api key>` (OpenAI-compatible routes)
  - `x-api-key: <anthropic api key>` (or `anthropic-api-key`)
  - `x-goog-api-key: <gemini api key>` (Gemini OpenAI-compat upstream)
  - `Authorization: Bearer <provider api key>` (only when Authorization is not used for CST)

### Strict auth headers mode
When `STRICT_AUTH_HEADERS=true` (default):
- Rejects `Authorization` header entirely
- Rejects provider-compatible BYOK headers (`x-api-key`, `anthropic-api-key`, `x-goog-api-key`)
- Requires CST via `X-CST`/`X-Scoped-Token` and provider keys via `X-Provider-API-Key`

### Platform-paid funding precheck
For platform-paid calls (no provider BYOK key), clawproxy performs fail-closed payment account binding + funding checks before provider routing:
- Payment account DID request context is read from `X-Payment-Account-DID` (fallback: `X-Client-DID`, then CST `sub`)
- CST claim `payment_account_did` is authoritative when present
  - mismatch with request account context => deterministic `401` `PAYMENT_ACCOUNT_CLAIM_MISMATCH`
  - invalid claim format => deterministic `401` `PAYMENT_ACCOUNT_CLAIM_INVALID`
  - when `PLATFORM_PAID_REQUIRE_PAYMENT_ACCOUNT_CLAIM=true`, missing claim => deterministic `401` `PAYMENT_ACCOUNT_BINDING_REQUIRED`
- Account must be bound in clawledger and have enough available balance (default minimum: `1` minor unit)
- If unbound or unfunded, clawproxy returns deterministic `402` with code `PAYMENT_REQUIRED`
- Successful platform-paid receipts include signed payment binding + funding context in:
  - `_receipt.payment.accountBinding`
  - `_receipt.payment.fundingCheck`
  - `_receipt_envelope.payload.metadata.payment_account_binding`
  - `_receipt_envelope.payload.metadata.payment_funding_check`

## Receipt Binding Headers

Harnesses SHOULD send these headers when routing LLM calls through the proxy to bind receipts to runs and events:

| Header | Description | Example |
|--------|-------------|---------|
| X-Run-Id | Run identifier correlating receipts to a specific agent run | `run_abc123` |
| X-Event-Hash | Base64url hash of the event-chain entry that triggered this call | `dGVzdA` |
| X-Idempotency-Key | Unique nonce to prevent duplicate receipt issuance | `nonce_xyz` |

Binding fields are embedded in the signed receipt and are tamper-proof. The proxy also injects:
- `policy_hash`: Work Policy Contract hash (when a WPC is enforced)
- `token_scope_hash_b64u`: CST token scope hash (when a scoped token is validated)

See: receipt_binding.v1.json schema for the full specification.

## Notes

- Receipts are signed with the proxy Ed25519 key; retrieve the public key from /v1/did.
- Google/Gemini: call `POST /v1/proxy/google` with an OpenAI-compatible body (`{ model, messages, ... }`).
- OpenRouter (via fal): set `model` to `openrouter/...` and call `POST /v1/chat/completions` (or `POST /v1/proxy/openai`) with `X-Provider-API-Key: $FAL_KEY`. The proxy sends `Authorization: Key ...` upstream.
- When X-Client-DID is set, a scoped token (CST) may be required, depending on deployment config.
