Skip to content

Drop-in proxy

The proxy records each AI call and forwards it to the real provider, so you get request-level attribution without touching application logic. You change one thing: the provider SDK’s base URL. Substitute the <your-venturi-instance> placeholder below by the base-URL rule: https://api.venturi.systems on the SaaS tier, or your own instance host when self-hosted (see Deployment modes).

Fail-open guarantee

The proxy runs Venturi’s decision-time interceptor: a fast index lookup with a 50 ms P99 end-to-end budget (15 ms internal), enforced by a cooperative timeout against a cumulative deadline. If the lookup, the event stream, or any other Venturi dependency behind the proxy is slow, degraded, or unavailable, the request is forwarded to the provider unmodified. A slow or unavailable Venturi dependency never blocks or fails a proxied request. The one deliberate rejection is tenant admission, which fails closed: a provider key that is not registered to your tenant is rejected before anything is forwarded.

The proxy endpoint itself is on your request path

Fail-open covers the Venturi dependencies behind the proxy, not the proxy endpoint itself. When your SDK’s base URL points at the proxy, a request reaches the provider only if it first reaches the proxy: on the SaaS tier that is the shared api.venturi.systems host, and in self-hosted mode it is your own instance host. The serving-availability objective and support-tier commitments on SLAs & SLOs cover the dashboard, query API, and exports, not the proxy endpoint. For a workload that cannot accept that dependency, configure client-side failover that sends the request to the provider’s direct base URL when the proxy endpoint cannot be reached (calls that fail over carry no proxy capture), or capture the workload through the Ingestion API or a cloud connection, which do not route your AI requests through Venturi.

How it works

  1. Your app sends the AI request to the Venturi proxy using the proxy base_url.
  2. The proxy forwards the request unchanged to OpenAI, Anthropic, or Amazon Bedrock, then returns the provider response to your app.
  3. The proxy emits a metadata-only InvocationEvent to the attribution pipeline.

The proxy passes your request through unchanged (including your provider API key, which Venturi does not store), captures metadata (model, tokens, latency, cost) and emits an InvocationEvent. Request and response content exists only in memory while being forwarded and is never written to access logs, error logs, traces, queues, or exception payloads, including on error and timeout paths.

Tenant admission

The proxy binds each call to your tenant from server-side state, never from a client-supplied header: a tenant header you send is stripped and never becomes the event’s tenant. The binding comes from the provider API key the call carries. Each provider key you route through the proxy is registered to your tenant as a one-way fingerprint, never as the key itself, and on the shared SaaS hostname that fingerprint is also what routes the call to your dedicated data plane.

Situation Outcome
The key is registered to your tenant Admitted. The fail-open guarantee applies from here on.
The call carries no provider key Rejected 401 before anything is forwarded.
The key is not registered to an active tenant, such as a new or rotated key you have not registered yet Rejected 403 before anything is forwarded.
The lookup that resolves the key cannot answer in time Forwarded unmodified under the fail-open rule, with null attribution.

Register every provider key under Settings / Admin / Credentials before you send traffic with it, including each new or rotated key. Venturi reduces the key to its fingerprint at registration and does not retain the key itself. During a rotation, register the new key first, move traffic to it, and remove the old key once no traffic uses it.

Endpoints

Set your SDK’s base URL to the value for your provider, relative to your Venturi instance host:

Provider SDK base URL path Provider paths it serves
OpenAI /api/v1/proxy/openai/v1 /chat/completions and other OpenAI API paths
Anthropic /api/v1/proxy/anthropic /v1/messages
Amazon Bedrock /api/v1/proxy/bedrock Bedrock Runtime paths such as /model/{modelId}/converse

The OpenAI SDK appends paths such as /chat/completions to its base URL, so the OpenAI base URL ends in /v1. The Anthropic SDK appends /v1/messages itself, so the Anthropic base URL stops at /anthropic.

OpenAI example

Python
from openai import OpenAI

client = OpenAI(
    base_url="https://<your-venturi-instance>/api/v1/proxy/openai/v1",
    api_key="<your OpenAI key>",  # forwarded as-is; not stored by Venturi
)

client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
Bash
curl "https://<your-venturi-instance>/api/v1/proxy/openai/v1/chat/completions" \
  -H "Authorization: Bearer <your OpenAI key>" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'

Anthropic example

Python
from anthropic import Anthropic

client = Anthropic(
    base_url="https://<your-venturi-instance>/api/v1/proxy/anthropic",
    api_key="<your Anthropic key>",  # forwarded as-is; not stored by Venturi
)

client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)
Bash
curl "https://<your-venturi-instance>/api/v1/proxy/anthropic/v1/messages" \
  -H "x-api-key: <your Anthropic key>" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'

Amazon Bedrock example

Authenticate Bedrock calls through the proxy with a long-term Amazon Bedrock API key in the Authorization: Bearer header, registered to your tenant like any other provider key (see Tenant admission). The proxy forwards that header unchanged and does not re-sign requests, so AWS Signature Version 4 credentials, which are bound to the host they were signed for, do not work through the proxy. Requests go to the Bedrock Runtime regional endpoint configured for your instance during onboarding.

Short-term Bedrock API keys are not admitted: each one expires within 12 hours and cannot be registered in advance. AWS recommends short-term keys for production and long-term keys for exploration, so for production Bedrock workloads that use short-term keys or Signature Version 4, capture usage through the AWS cloud connection, which reads Bedrock invocation metadata, or emit events from your code through the Ingestion API. When you rotate a long-term key, for example with the IAM ResetServiceSpecificCredential action, register the new value before you move traffic to it.

Bash
curl -X POST "https://<your-venturi-instance>/api/v1/proxy/bedrock/model/us.anthropic.claude-sonnet-4-6/converse" \
  -H "Authorization: Bearer $AWS_BEARER_TOKEN_BEDROCK" \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":[{"text":"Hello"}]}]}'

The us. prefix in us.anthropic.claude-sonnet-4-6 names a US geographic cross-Region inference profile. Use the profile ID whose geography prefix matches the Bedrock Region configured for your instance. For this model those are us., eu., jp., and au., or global. for global cross-Region inference. The Claude Sonnet 4.6 model card lists the exact profile IDs and the source Regions each one serves; for other models, see Supported Regions and models for inference profiles.

Attributing the call

To attribute a call beyond “this API key”, add attribution headers to the request. The proxy records their values as metadata on the call’s InvocationEvent and removes them before it forwards the request, so the provider never receives them:

The last column gives the equivalent Ingestion API field.

Header Declares API field
X-Venturi-User The identity that made the call attributed_identity
X-Venturi-Service The service that made the call attributed_service
X-Venturi-Team The owning team, used as a direct team match None
X-Venturi-Cost-Center The cost center to attribute the call to None

Each value is an explicit declaration by the calling workload, so keep it to an identifier, never message content. A tenant header is not one of these: the proxy strips any tenant header you send and binds the call to your tenant from the provider key (see Tenant admission).

Streaming

OpenAI and Anthropic Server-Sent Events are forwarded incrementally, and token counts are derived from the stream. Amazon Bedrock binary event streams (ConverseStream and InvokeModelWithResponseStream) are forwarded frame by frame; the proxy parses the event-stream frames for the token counts Bedrock reports and preserves Bedrock’s token-count headers.

Confirm events are landing

Give feedback on this page

Sign in to send feedback. Opens in a new tab.

Copy page details
Docs feedback: Drop-in proxy
Page: https://docs.venturi.systems/ingestion/proxy/