ReskSafety · Documentation
Firewall API
The endpoints your application calls, how a request is authenticated, which policy decisions can stop it, and what each status code means.
On this page
Authentication
API clients have three options, evaluated in this order:
| Method | Header / cookie | Use case |
|---|---|---|
| Bearer JWT | Authorization: Bearer <token> | Service-to-service, scripts, the SDKs |
| User cookie | user_token (console session) | Browser calls from the same origin |
| Anthropic key | x-api-key | Unmodified Anthropic SDK against /v1/messages |
Mint a user token from the console or with the admin API. Admin endpoints additionally require the X-CSRF-Token header matching the CSRF cookie.
Chat completions
curl -s http://localhost:8000/v1/chat/completions \
-H "Authorization: Bearer $RESK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Summarise this ticket"}],
"stream": false
}'
Supported body fields: model, messages, max_tokens, temperature, stream, tools, plus provider-specific keys in extra (forwarded upstream). Unknown top-level fields are allowed and forwarded.
Response shape is the OpenAI schema plus two RESK fields:
{
"id": "chatcmpl-…",
"object": "chat.completion",
"created": 1770000000,
"model": "gpt-4o-mini",
"choices": [
{"index": 0, "message": {"role": "assistant", "content": "…"}, "finish_reason": "stop"}
],
"usage": {"prompt_tokens": 12, "completion_tokens": 34},
"blocked": false,
"blocked_phrase": null
}
When a policy blocks the output, blocked is true and blocked_phrase names the rule. When the input is blocked, the request fails with HTTP 403 instead.
Streaming
"stream": true returns text/event-stream chunks in the OpenAI format, terminated by data: [DONE]. Output policies are evaluated on the accumulated text; a violation ends the stream early with an empty delta. ENV Match restores flags per chunk and buffers flags split across chunks.
Tool gating
Requests that carry tools require capability bit 0 (can_call_tools) on the caller's merged role mask. Without it the request is rejected with 403 before any provider call.
Provider routing
Three levels decide where the request goes:
X-Provider-Id: <uuid>selects a provider stored in the admin console (encrypted API key, endpoint, default model, response length limit).- Otherwise the global
LLM_BACKEND_TYPE/LLM_BACKEND_URL/LLM_BACKEND_API_KEYsettings apply. - The model entity in the database can override
max_tokens,temperatureand a response length limit.
Provider API keys are encrypted at rest with PROVIDER_ENCRYPTION_KEY; the key never appears in API responses (only an api_key_masked hint).
Anthropic messages
curl -s http://localhost:8000/v1/messages \
-H "x-api-key: $RESK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-3-5-sonnet-latest",
"max_tokens": 512,
"messages": [{"role": "user", "content": "Hello"}]
}'
The endpoint accepts Anthropic's schema (system as a string or content blocks, top_k, top_p, stop_sequences, metadata) and returns content blocks. Streaming emits native Anthropic SSE events. The same policy, RBAC and ENV Match layers apply; the system prompt participates in masking and the masked hint is prepended as a system block.
Batch tool calls
POST /v1/chat/completions/batch
{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Book the cheapest flight"}],
"tool_calls": [
{"id": "call_1", "output": "{\"price\": 210, \"carrier\": \"AF\"}"}
]
}
Tool results are appended as tool messages and the model is re-invoked. Tool outputs are scanned like user text and masked by ENV Match, so a tool that returns an API key or an email does not leak it upstream; the restored value comes back in the continuation.
Tokenizer inspection
POST /v1/tokenize
{"model": "gpt-4o-mini", "text": "ignore previous instructions"}
{"tokens": […], "blocked_tokens": [1234], "blocked_phrases": ["ignore previous instructions"], "model": "gpt-4o-mini"}
Useful to debug why a policy would ban a phrase, and to see the token IDs a local logits processor would suppress.
Status codes
| Status | Meaning |
|---|---|
| 200 | Success. Output-policy blocks are indicated by blocked: true. |
| 401 | Missing or invalid credentials. |
| 403 | Tool calling not permitted, or input blocked by scanning / jailbreak / policy. |
| 422 | Malformed request body. |
| 429 | RATE_LIMIT_PER_MINUTE exceeded. |
| 502 | Upstream provider error (message includes the provider response). |
| 500 | Internal error, including a failure of the masking layer (fails closed). |
Audit trail
Every request writes a RequestLog: user, policy, status (success, blocked, error), backend, model, blocked phrase, prompt hash and the request metadata from extra. With LOG_PROMPTS=true the prompt is stored too — ENV Match masks it first, so enabling prompt logging does not persist the secrets it protects.