PalveronPalveronDocs

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

FieldRequiredDescription
promptThe text to evaluate
metadataFree-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.
attachmentsArray of multi-modal payloads (see Multi-modal)
contextRequest-origin context: tool_name, MCP server, chain depth, source system — passed through to traces
structured_inputOptional 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_textLegacy: pre-extracted text from images/PDFs. Prefer attachments.

Agent attribution lives in metadata.agent_id — there is no top-level agent_id field. A top-level agent_id is 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"
}
FieldDescription
decisionThe governance verdict (see below)
outputThe content to forward to your LLM. On MODIFIED this is the redacted/edited prompt; on PASSED the original.
reasonHuman-readable explanation (present when a policy fired)
trace_idImmutable trace record id — use it in the Trace Explorer, exports, and POST /api/v1/verify-proof
integrity_hashSHA-256 integrity hash of the trace
sequence_numMonotonic per-project trace sequence number
flare_statusBlockchain anchoring status of the trace (e.g. PENDING), when Flare is active
should_anchorWhether this trace qualifies for blockchain anchoring
content_typeDetected content type (text, image, audio, document, …)
findingsOnly on multi-modal requests: findings per attachment
enforcement_actionOnly on Browser-Guard requests: browser enforcement action (BLOCK, WARN, JUSTIFY, REDIRECT)
action_configOnly with enforcement_action: its configuration (e.g. redirect target)
error_classOnly on fail-closed/engine-error verdicts: machine-readable failure class (e.g. llm_4xx)
modified_fieldsOnly 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 in output.
  • BLOCKED — Request rejected. reason explains why.
  • MODIFIED — Request allowed with edits. output contains the redacted version.
  • FLAGGED — Request allowed; a LOG_ONLY policy fired and the violation is recorded in the trace.
  • PENDING_APPROVAL — Request queued for a human approver. Track the outcome via GET /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.

StatusDecisionMeaning
200 OKPASSED / MODIFIED / FLAGGED / POLICY_CHANGERequest allowed. Forward output to your LLM.
202 AcceptedPENDING_APPROVALHuman approval required. The trace is persisted; the approval is tracked via trace_id.
403 ForbiddenBLOCKEDRequest denied by policy, capability model, or per-agent budget cap. Do not retry — inspect reason.
429 Too Many Requestsno decisionTier rate-limit hit. Honour the Retry-After header. Body is the rate-limit error, not a verify response.
400 Bad Requestno decisionMalformed request (e.g. missing prompt). Body: {"error": "<message>"}.
503 Service Unavailableno bodyThe 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:

HeaderValues
X-Palveron-Statushealthy | degraded — platform health rollup
X-Palveron-Trace-Persisteddb | dlq | none — where this request's trace landed
X-Palveron-Degraded-SubsystemsComma-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 decision field. 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.

On this page