API reference
Base: https://guardrails.vulnetix.com
Authentication
Every inference and listing endpoint requires your organisation’s Vulnetix API key, in either header:
Authorization: Bearer <vulnetix-api-key>
x-api-key: <vulnetix-api-key>
Both are accepted on every route, so OpenAI SDKs (which send the first) and Anthropic SDKs (which send the second) both work without configuration.
This is not a provider key. Provider keys live in the vault and are injected by the gateway. Your credential is stripped before the request goes upstream.
Endpoints
| Method + path | Surface | Purpose |
|---|---|---|
POST /{provider}/{org}/v1/chat/completions | chat | Chat completions, streaming or not |
POST /{provider}/{org}/v1/responses | responses | The OpenAI Responses API (Codex) |
POST /{provider}/{org}/v1/messages | messages | The Anthropic Messages API (Claude Code, Claude Desktop) |
POST /{provider}/{org}/v1/messages/count_tokens | messages | Token counting |
GET /{provider}/{org}/v1/models | any | The model catalog, filtered by your policy |
GET /healthz | — | Liveness. No auth. |
GET /readyz | — | Readiness. No auth. |
{provider} is a provider slug. {org} is your
organisation UUID.
Anthropic clients use a base URL with no /v1 — the SDK appends it:
https://guardrails.vulnetix.com/anthropic/{orgUuid}
Everything else takes the /v1 form. See
base URLs.
A provider only serves the surfaces it supports. Asking for another is a 404
unsupported_api. See the provider catalog.
Request bodies
Bodies are passed through. The firewall types only the few fields it must reason
about — model, the messages, and stream — and preserves every other top-level
field verbatim. temperature, tools, response_format, max_tokens,
reasoning, cache_control, and anything a provider adds tomorrow all survive the
round trip untouched.
The only modification the firewall ever makes is a redaction rewriting matched text.
Streaming
Set stream: true (or the surface’s equivalent). The response is relayed as
Server-Sent Events, frame by frame, as it arrives. Nothing is buffered or
reassembled.
Streaming works on all three surfaces.
count_tokens
POST /{provider}/{org}/v1/messages/count_tokens runs the full guardrail
pipeline.
That is deliberate: the endpoint ships your entire prompt upstream, so exempting it
would be a trivial way to walk a block rule around the firewall. A prompt that would
be blocked on /v1/messages is blocked here too.
It is not an inference, so it is never written to the inference log, even with logging enabled.
GET /v1/models
Served from the model catalog, filtered by your organisation’s
model policy. It never calls the provider, so it
needs no stored provider key — only an explicit provider deny blocks it.
Rendered in the shape the provider’s surface implies. See the models endpoint.
Limits
| Limit | Value |
|---|---|
| Request body | 8 MiB — exceeded returns 413 request_too_large |
| Upstream timeout | 120s for non-streaming requests. Streams are not bounded by it. |
There are no rate limits and no quotas. See limitations.
Headers
Forwarded upstream: everything your client sends, except the ones below.
Never forwarded:
Authorizationandx-api-key— your Vulnetix credential. It authenticates you to us and must never reach a third party. The provider gets its own key from the vault instead.Accept-Encoding— stripped so the gateway can read the response to count tokens. Compression still happens; it is negotiated by the gateway.- Hop-by-hop headers, per RFC 7230.
Defaulted, not overridden: a provider’s credential may specify headers that carry
no key — anthropic-version, for instance. Those are defaults: the gateway sets them
only if you did not. If you deliberately request a newer API version, yours wins.
Legacy form
POST /{provider}/v1/chat/completions
X-Organisation-UUID: <org uuid>
The organisation may be supplied as a header instead of a path component. It still works, but the URL form is preferred because most LLM clients cannot send custom headers — which is the entire reason the org is in the path.
Errors
Full taxonomy, in both dialects: error reference.
Health
GET /healthz — the process is up.
GET /readyz — the process is up and the database is reachable. Returns 503
otherwise.
Neither requires authentication.