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.

  • Version 0.1.1
  • FastAPI + React
  • Python 3.11+
  • Apache-2.0

Authentication

API clients have three options, evaluated in this order:

MethodHeader / cookieUse case
Bearer JWTAuthorization: Bearer <token>Service-to-service, scripts, the SDKs
User cookieuser_token (console session)Browser calls from the same origin
Anthropic keyx-api-keyUnmodified 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:

  1. X-Provider-Id: <uuid> selects a provider stored in the admin console (encrypted API key, endpoint, default model, response length limit).
  2. Otherwise the global LLM_BACKEND_TYPE/LLM_BACKEND_URL/LLM_BACKEND_API_KEY settings apply.
  3. The model entity in the database can override max_tokens, temperature and 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

StatusMeaning
200Success. Output-policy blocks are indicated by blocked: true.
401Missing or invalid credentials.
403Tool calling not permitted, or input blocked by scanning / jailbreak / policy.
422Malformed request body.
429RATE_LIMIT_PER_MINUTE exceeded.
502Upstream provider error (message includes the provider response).
500Internal 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.