Pre-check request before LLM call
Gateway Mode Step 1: Call this endpoint before making your own LLM API call.
The Agent validates the request against policies and returns:
- verdict - the canonical allow | deny, the same vocabulary POST /api/v1/decide uses. Read this one. Since v11 the pre-check never holds a request: a require_approval policy is a deny.
- approved: true if the request is allowed (retained)
- decision_id — the decision identifier. Use it for the subsequent audit call, AND for GET /api/v1/decisions/{decision_id}/explain, which is keyed on it.
- context_id — a deprecated alias of decision_id, same value
- Optional approved_data from MCP connectors
- Rate limit information
approved_data is only prefetched for clean approvals (#2868): when the request is blocked, requires HITL approval, or requires redaction, connector prefetch is skipped and approved_data is never populated — governed data is not fetched for a request that may not proceed.
Context expires after 5 minutes.
Example Flow
1. SDK calls pre-check → gets context_id, approved=true
2. SDK makes direct LLM call (OpenAI, Anthropic, etc.)
3. SDK calls audit with context_id and response metadata
Request
- Base URLhttps://agent.getaxonflow.com
- Authnone declared. Required headers: Authorization
- TypeScriptA function with typed inputs. Its response is checked against the schema.
Headers
OAuth2-style Basic authentication header. Format: Basic base64(clientId:clientSecret)
- clientId: Your organization identifier (required)
- clientSecret: Authentication credential (optional for community mode)
Not required when DEPLOYMENT_MODE=community.
base64url (padding optional) of the PEPHandshake document.
The ADR-065 PEP capability handshake: base64url of a compact JSON document in which an external enforcement point declares what it is and which obligations it can discharge. See PEPHandshake for the document.
Absent is the default and changes nothing. A caller that omits the header takes byte-for-byte the path it took before this header existed.
What an absent header means for a redaction depends on the plane, by design (PRD v11 section 1 item 16, #4257). The MCP passes discharge a redaction of the content they hand back: the request pass (check-input, check_policy) masks the statement, and a redaction that masks nothing in the statement is refused unsupported_obligation to every caller, and one that masks a request parameter to every caller that has not declared field_redact at version 2 (on Community, to every caller) (#4264); the response passes (check-output, the MCP server's check_output) mask the rows or the message. /api/v1/decide and the gateway pre-check return a decision rather than content, so a required redaction is a field_redact obligation for the enforcement point, and a caller that has not declared field_redact is refused unsupported_obligation. A caller that declares NO redaction (capabilities: []) is refused on each of these planes; on Community the MCP passes still return a checksum validator's masked content to it (reachable only through a directly inserted detection_action_overrides row) until #4122.
A header that is PRESENT and cannot be read is refused, never treated as absent: degrading a malformed declaration to "legacy caller" would go on handing an enforcement point obligations it had just said it cannot discharge. The refusal is 400 and its message names this header, which matters on /api/v1/access/evaluation where the refusal is rendered through that surface's existing incomplete_evaluation code and the message is the only thing distinguishing a malformed HEADER from a malformed body ENVELOPE.
Present more than once is refused: RFC 7230 permits an intermediary to join repeated field lines with a comma, and a comma is outside the base64 alphabet, so a joined pair can only decode to malformed. That is why the document is base64 rather than raw JSON, which would join into something a lenient parser might accept.
When a decision carries a mandatory obligation the declared set does not cover, the request is answered 200 with verdict: deny and the reason unsupported_obligation (ADR-065 invariant 8) - a decision about the request, not a transport error. That holds on every edition. An Enterprise deployment adds a second reason beginning pep_capability_unsupported naming the gap, and refuses a checksum validator's mask on the MCP passes; a Community deployment hands that masked content over (#4257 split 2, #4122).
Request body
Response
Pre-check result
Example response
{
"trace_id": "b3a1f1f3a8c6e0d791bc3e7a8c2d5f4a"
}Changes
No recorded changes to this operation across all 1 revision of this API.