Verify
The core endpoint for AI governance — send a prompt, receive a decision.
Every governance decision starts here. Send a prompt; Palveron runs it through policies, NGE, and (optionally) LLM-assist; you get back a decision and a fully-attributed trace.
POST /api/v1/verify
curl -X POST https://gateway.palveron.com/api/v1/verify \
-H "Authorization: Bearer pv_live_..." \
-H "Content-Type: application/json" \
-d '{
"prompt": "My social security number is 123-45-6789.",
"metadata": { "agent_id": "ckagent..." },
"context": { "tool_name": "customer-support-ui" }
}'Request
| Field | Required | Description |
|---|---|---|
prompt | ✅ | The text to evaluate |
metadata | — | Free-form JSON object. metadata.agent_id attributes the request to a registered agent (omit it and the trace is recorded without agent attribution). metadata.source: "browser" marks Browser-Guard traffic. |
attachments | — | Array of multi-modal payloads (see Multi-modal) |
context | — | Request-origin context: tool_name, MCP server, chain depth, source system — passed through to traces |
structured_input | — | Optional structured field decomposition for tools with routing metadata (e.g. email:send). When present and the tool is known to the field-role registry, the response carries modified_fields. |
extracted_text | — | Legacy: pre-extracted text from images/PDFs. Prefer attachments. |
Agent attribution lives in
metadata.agent_id— there is no top-levelagent_idfield. A top-levelagent_idis silently ignored and the trace stays agent-anonymous.
Response
{
"decision": "BLOCKED",
"output": "",
"reason": "PII detected: SSN",
"trace_id": "cktrace...",
"integrity_hash": "sha256:...",
"sequence_num": 1042,
"flare_status": "PENDING",
"should_anchor": true,
"content_type": "text"
}| Field | Description |
|---|---|
decision | The governance verdict (see below) |
output | The content to forward to your LLM. On MODIFIED this is the redacted/edited prompt; on PASSED the original. |
reason | Human-readable explanation (present when a policy fired) |
trace_id | Immutable trace record id — use it in the Trace Explorer, exports, and POST /api/v1/verify-proof |
integrity_hash | SHA-256 integrity hash of the trace |
sequence_num | Monotonic per-project trace sequence number |
flare_status | Blockchain anchoring status of the trace (e.g. PENDING), when Flare is active |
should_anchor | Whether this trace qualifies for blockchain anchoring |
content_type | Detected content type (text, image, audio, document, …) |
findings | Only on multi-modal requests: findings per attachment |
enforcement_action | Only on Browser-Guard requests: browser enforcement action (BLOCK, WARN, JUSTIFY, REDIRECT) |
action_config | Only with enforcement_action: its configuration (e.g. redirect target) |
error_class | Only on fail-closed/engine-error verdicts: machine-readable failure class (e.g. llm_4xx) |
modified_fields | Only on structured_input requests: per-field result map (ROUTING preserved, CONTENT masked) |
Optional fields are omitted from the JSON entirely when not applicable.
Per-policy NGE scores, detected entities, and match details are not part of the verify response — they are recorded on the trace. Retrieve them via the Traces API or the Trace Explorer.
Decisions
PASSED— Request allowed, original prompt inoutput.BLOCKED— Request rejected.reasonexplains why.MODIFIED— Request allowed with edits.outputcontains the redacted version.FLAGGED— Request allowed; aLOG_ONLYpolicy fired and the violation is recorded in the trace.PENDING_APPROVAL— Request queued for a human approver. Track the outcome viaGET /api/v1/approvals/status?trace_id=....POLICY_CHANGE— Request allowed; it triggered a governance/policy-change event rather than a content verdict.
HTTP status codes
The HTTP status code mirrors the decision field, so load balancers, observability tools, and HTTP-aware clients (e.g. MCP / OpenClaw consumers) get a faithful signal without having to parse the JSON body.
| Status | Decision | Meaning |
|---|---|---|
200 OK | PASSED / MODIFIED / FLAGGED / POLICY_CHANGE | Request allowed. Forward output to your LLM. |
202 Accepted | PENDING_APPROVAL | Human approval required. The trace is persisted; the approval is tracked via trace_id. |
403 Forbidden | BLOCKED | Request denied by policy, capability model, or per-agent budget cap. Do not retry — inspect reason. |
429 Too Many Requests | no decision | Tier rate-limit hit. Honour the Retry-After header. Body is the rate-limit error, not a verify response. |
400 Bad Request | no decision | Malformed request (e.g. missing prompt). Body: {"error": "<message>"}. |
503 Service Unavailable | no body | The gateway could not durably record the governance decision (DB and DLQ unavailable). Retry with backoff. |
The JSON body is the source of truth. A response with a decision field is a verify response regardless of status (200 / 202 / 403). Clients should branch on decision, not on response.ok. Reserve HTTP-status branching for 429 (rate limits) and 5xx (transport errors).
Resilience headers
Every governance response carries three headers:
| Header | Values |
|---|---|
X-Palveron-Status | healthy | degraded — platform health rollup |
X-Palveron-Trace-Persisted | db | dlq | none — where this request's trace landed |
X-Palveron-Degraded-Subsystems | Comma-separated list; omitted entirely when healthy (header absence is the fast "all good" probe) |
Errors
Distinct from a governance BLOCKED (which is a 403 with a verify-shaped body), transport/validation errors return a plain error object:
{ "error": "Prompt is required" }Error messages are localized (Accept-Language) and human-readable; there is no separate machine-readable error-code field on this endpoint.
Tip: distinguish a transport error from a governance block by checking for the
decisionfield. If it's present, the response is a verify outcome (parse the body). If it's absent, treat the status code as a transport/auth error.
Retry behavior
POST /verify is not idempotent — a retry creates a second trace. Retry only on transient failures (timeouts, 429 honouring Retry-After, 5xx) with exponential backoff and jitter, and treat 403/400 as final.