OpenAI
Point any OpenAI-shaped client at Sentisec. The OpenAI SDKs, Cursor, opencode, custom clients — all work with one base-URL change.
Sentisec speaks the OpenAI Chat Completions API natively. Any client built against OpenAI — the Python and TypeScript SDKs, Cursor, opencode, LangChain, your own client — points at Sentisec with a base-URL change and no code change.
Model ids beginning gpt-, o1, or o3 route to OpenAI
automatically, so there is nothing else to configure.
Setup
Get an OpenAI key from platform.openai.com/api-keys.
Add it to your workspace. In the dashboard, open Settings → Providers. Under Provider keys, choose Add OpenAI key, paste the key, and click Save credential.
Mint a Sentisec API key. Settings → API keys → Issue key.
Format: sk_sentisec_<8>_<32>. This is the key your client sends;
your OpenAI key stays in the workspace.
Point your client at Sentisec. Two environment variables:
export OPENAI_BASE_URL=https://api.sentisec.ch/ws/<your-workspace-id>/v1
export OPENAI_API_KEY=$SENTISEC_API_KEYRunning Sentisec yourself? Substitute your own base URL — see enterprise access.
The /v1 suffix belongs on the OpenAI-shaped base URL — the SDKs expect
to append paths like /chat/completions to it.
First call
curl -X POST https://api.sentisec.ch/ws/<your-workspace-id>/v1/chat/completions \
-H "Authorization: Bearer $SENTISEC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-terra",
"messages": [{"role": "user", "content": "hi"}]
}'You get back the standard OpenAI Chat Completions body. The session appears under Sessions in the dashboard.
OpenAI SDKs
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.sentisec.ch/ws/<your-workspace-id>/v1",
api_key=os.environ["SENTISEC_API_KEY"],
)
resp = client.chat.completions.create(
model="gpt-5.6-terra",
messages=[{"role": "user", "content": "hi"}],
)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.sentisec.ch/ws/<your-workspace-id>/v1",
apiKey: process.env.SENTISEC_API_KEY!,
});
const resp = await client.chat.completions.create({
model: "gpt-5.6-terra",
messages: [{ role: "user", content: "hi" }],
});Streaming ("stream": true) works on the same route, and tool calls are
gated on both the streaming and non-streaming paths.
Model ids
| Model id | Notes |
|---|---|
gpt-5.6-terra | Current-generation balanced default. The id used in every sample on this site. |
gpt-5.6-sol | Current-generation flagship — the top of the GPT-5.6 line. |
gpt-5.6-luna | Current-generation cost tier. |
gpt-4o, gpt-4o-mini | Multimodal workhorses. |
gpt-4-turbo | Previous generation. |
o1, o1-mini | Reasoning models. |
These are the ids surfaced in model discovery
(GET .../v1/models). Any id starting with gpt-, o1, or o3 is
forwarded to OpenAI, which is the source of truth for what your key can
call.
Embeddings
POST .../v1/embeddings works against OpenAI through your workspace
endpoint:
curl -X POST https://api.sentisec.ch/ws/<your-workspace-id>/v1/embeddings \
-H "Authorization: Bearer $SENTISEC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "text-embedding-3-small", "input": "hello"}'Embeddings relay verbatim and are recorded for usage; there is no tool call in an embedding to gate.
Which endpoint is inspected
Sentisec exposes three OpenAI-shaped endpoints on your workspace URL. Both of the ones that carry tool calls are inspected.
| Endpoint | What Sentisec does with it |
|---|---|
POST .../v1/chat/completions | Inspected. Every tool call the model returns is evaluated against your workspace policy before your client sees it — on both the streaming and the non-streaming path. A blocked call is withheld and explained in the message text, so it never reaches your tool. |
POST .../v1/responses | Inspected. Same evaluation, on both the streaming and the non-streaming path. A blocked call is withheld and explained, so your tool never runs it. This endpoint is OpenAI-only and writes no per-request usage record. |
POST .../v1/embeddings | Relayed. An embedding contains no tool call to evaluate. The body goes upstream unchanged and every call is recorded for usage. |
Chat Completions is what the OpenAI SDKs use by default and what every
framework on this site drives, so for most readers it is already the
path in use. gpt-5.6-terra is served on both Chat Completions and the
Responses API, so the choice between them is about client shape and
usage accounting, not about protection.
Full detail on both: Responses and Embeddings.
Tools OpenAI runs on its own side
The Responses API can execute web_search, file_search,
computer_use, and remote MCP tools inside OpenAI's infrastructure
before the response reaches Sentisec. Their arguments and results never
cross your wire, so there is nothing for the integrity engine to
inspect. Where one appears, Sentisec records it on the session timeline
as observed-but-not-inspectable — it does not claim to have checked a
call it never saw, and it cannot stop one.
What you get
On /v1/chat/completions, every call runs through the integrity engine
before it reaches OpenAI, and every tool call the model asks for is
evaluated before your tools run it. Verdicts and forensic evidence land
in the dashboard. Function calling, structured
outputs, vision, and streaming are all forwarded untouched.
If something goes wrong
| Response | What it means |
|---|---|
401 no_upstream_credential | No OpenAI key is stored on this workspace. Add it under Settings → Providers, in Provider keys — the request's row under Requests offers Add OpenAI key, which opens that page with OpenAI selected. |
A 401 from OpenAI | Your OpenAI key was revoked or is out of quota at the vendor. |
400 upstream_provider_header_invalid | You sent an X-Sentisec-Upstream-Provider value that is not a known provider name. |
More: Provider unavailable.
More
- Quickstart — cURL — minimal HTTP example
- Quickstart — Python SDK
- Quickstart — TypeScript SDK
- Dashboard — sessions, verdicts, forensic evidence
- Providers — every provider Sentisec carries