Provider gateway
Point an OpenAI or Anthropic client at Tracehatch and keep every capture feature from any language.
On this page
The gateway is a proxy in front of OpenAI and Anthropic. Point your existing client's base URL at it and add one header. It parses the traffic with the same parser the Node SDK uses, so you get the full picture — runs, generations, tool steps, sessions, streams, token usage and cost — from any language.
- OpenAI base URL
https://api.tracehatch.com/gateway/openai/v1- Anthropic base URL
https://api.tracehatch.com/gateway/anthropic- Credential
- X-Tracehatch-Key: th_live_… or th_test_…
- Provider key
- Passes through untouched
Your provider credential is forwarded as you sent it. It is never stored or logged.
Point your client at it
import OpenAI from "openai"
// Keep your provider key; add the Tracehatch key as a header and swap the base URL.
const client = new OpenAI({
baseURL: "https://api.tracehatch.com/gateway/openai/v1",
defaultHeaders: {
"X-Tracehatch-Key": process.env.TRACEHATCH_API_KEY!,
},
})import os
from openai import OpenAI
# Keep your provider key; add the Tracehatch key as a header and swap the base URL.
client = OpenAI(
base_url="https://api.tracehatch.com/gateway/openai/v1",
default_headers={"X-Tracehatch-Key": os.environ["TRACEHATCH_API_KEY"]},
)For Anthropic, use the /anthropic path with your existing Anthropic client:
import os
from anthropic import Anthropic
# Keep your provider key; add the Tracehatch key as a header and swap the base URL.
client = Anthropic(
base_url="https://api.tracehatch.com/gateway/anthropic",
default_headers={"X-Tracehatch-Key": os.environ["TRACEHATCH_API_KEY"]},
)An unknown provider segment is rejected: the only two upstreams are
/gateway/openai/… and /gateway/anthropic/….
Headers
| Header | Purpose |
|---|---|
X-Tracehatch-Key | Required. Your ingest key. Selects the project and environment. |
X-Tracehatch-Session-Id | Group this call into a conversation. |
X-Tracehatch-User-Id | Name the end user. |
X-Tracehatch-Agent | Name the agent on the run. |
X-Tracehatch-Release | Name the release on the run. |
All of them are stripped before the request reaches the provider, along with hop-by-hop, proxy and platform headers, cookies and forwarding headers. Nothing about Tracehatch is visible upstream.
Without a session header, sessions are derived exactly as they are in the SDK —
from the OpenAI Responses conversation id or previous_response_id, otherwise
a fingerprint of the system prompt and first user message. Derived ids are
identical across processes, restarts and the SDK, so a conversation split
between a Node service and a Python worker still lands in one session.
What is recorded
Everything in Automatic capture: chat completions, the Responses API including background polls, embeddings and Anthropic messages; streams assembled as they pass through; token usage, finish reasons, time to first token, provider error types and tool steps paired across calls.
Bodies are redacted server-side before storage, since there is no SDK in your process to do it first.
Limits
| Limit | Value |
|---|---|
| Requests per minute, per key | 600 |
| Request body | 8 MB — larger is rejected with 413 |
| Captured response body | 8 MB — larger non-streaming responses are forwarded uncaptured |
| Waiting for response headers | 120 seconds |
| Silence on a stream | 120 seconds |
The proxy streams and never re-encodes: content-encoding, content-length,
transfer-encoding and set-cookie are not passed back to you.
Failure behaviour
- An error before the provider answered is returned as
application/problem+json— a missing or revoked key, an unknown provider, a body that is too large, or rate limiting. - An error after the provider started answering closes the connection rather than injecting a body into a partly-delivered response.
- If Tracehatch cannot reach the provider, you get
503 upstream_unavailable.
Gateway or log endpoint?
| Gateway | Log endpoint | |
|---|---|---|
| In your request path | Yes | No |
| Records streams and time to first token | Yes | No |
| Pairs tool calls across requests | Yes | You send them |
| Derives sessions from the conversation | Yes | From chat-style messages |
| Works with any provider | OpenAI and Anthropic only | Any |
| Code change | Base URL and a header | One request per model call |
Self-hosted
The gateway is mounted on the API host outside the versioned prefix, so a
self-hosted installation swaps only the origin — the /gateway/<provider> path
is the same.