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 + pathSurfacePurpose
POST /{provider}/{org}/v1/chat/completionschatChat completions, streaming or not
POST /{provider}/{org}/v1/responsesresponsesThe OpenAI Responses API (Codex)
POST /{provider}/{org}/v1/messagesmessagesThe Anthropic Messages API (Claude Code, Claude Desktop)
POST /{provider}/{org}/v1/messages/count_tokensmessagesToken counting
GET /{provider}/{org}/v1/modelsanyThe model catalog, filtered by your policy
GET /healthzLiveness. No auth.
GET /readyzReadiness. No auth.

{provider} is a provider slug. {org} is your organisation UUID.

Warning

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

LimitValue
Request body8 MiB — exceeded returns 413 request_too_large
Upstream timeout120s 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:

  • Authorization and x-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.