Skip to main content

Base URL

Health check

GET /health

Check API status. No authentication required.
Response:

Verification endpoints

POST /verify/natural_language

Main entry point for verifying natural language queries. Routes through the QWED Control Plane with multi-tenancy support. Request:
Response: The response follows the VerificationResult schema. For math queries, the top-level status is INCONCLUSIVE because the LLM translation step is not formally verified — see Trust boundary for details.
Status values for natural language math verification:
Previous versions set the status field to the inner engine result (e.g., VERIFIED). It now returns INCONCLUSIVE when the inner engine returns VERIFIED or CORRECTION_NEEDED, because the natural language pipeline involves a non-deterministic LLM translation step. Use the trust_boundary object to inspect the detailed verification breakdown. For fully deterministic results, use POST /verify/math directly.
trust_boundary fields:

Mandatory attestation admission

The control plane treats attestation as an admission gate, not a decoration:
  • The final status and trust_boundary.overall_status are set by enforce_trust_decision(..., require_attestation=True) after signing, not by the raw verifier verdict. A VERIFIED math result is only surfaced once create_verification_attestation() returns ISSUED.
  • If attestation signing fails for any reason, the response is downgraded to BLOCKED (fail-closed). The attestation error code is echoed under trust_boundary.attestation_error and the top-level response omits the attestation token.
  • The attestation qwed.query_hash binds to the translated expression that the deterministic engine actually evaluated — not to the natural-language user_query. This matches the disclosed verification_scope: "translated_expression_only": the natural-language query still appears in response.user_query for display, but downstream consumers verifying the attestation should hash the translated expression, not the user prose.
See Cryptographic attestations for the full AttestationResult contract and Trust boundary for the math-engine discussion.

POST /verify/math

Updated in v5.1.0: verify_identity() numerical sampling fallback now returns BLOCKED with is_equivalent: false instead of UNKNOWN. This fail-closed behavior ensures that sampling-only agreement is never mistaken for a verified identity.
Verify mathematical expressions or equations using SymPy symbolic computation. Request:
Response (equation):
Response (expression):
Symbolic expressions that cannot be evaluated to a numeric value include is_symbolic: true. Expressions involving complex numbers include is_complex: true. Ambiguous expressions: Expressions with implicit multiplication after division (e.g., 1/2(3+1)) are rejected with is_valid: false, result: false, and status: "BLOCKED". The response includes warning: "ambiguous" and a message explaining why. Rewrite the expression with explicit parentheses or a * operator to remove the ambiguity.
Error cases: Division by zero, log(0), and square root of negative numbers in the real domain return is_valid: false with a descriptive error and message. Tolerance bounding: When verifying an expression against an expected value with a tolerance parameter, the engine enforces a deterministic upper bound on the tolerance. The maximum allowed tolerance is max(0.01, abs(calculated_value) * 0.01). If the requested tolerance exceeds this bound, the request returns a BLOCKED status. Invalid tolerance values (negative, NaN, Infinity, or non-numeric) are also rejected with BLOCKED. Response (tolerance exceeded):

POST /verify/logic

Verify logical constraints. Routes through the QWED Control Plane. Request:
Response:
The provider_used field indicates which LLM provider handled the translation step. This field is included in both success and error responses, which helps with debugging provider routing issues. Error response:

POST /verify/code

Updated in v7.0.0 (breaking)
Check code for security vulnerabilities using AST analysis. Returns the unified DiagnosticResult shape plus a separate admission decision. Request:
Response (unsafe code — proven unsafe, not admitted):
Breaking change (v7.0.0): proven-unsafe code now returns HTTP 200 with status: "VERIFIED" (previously BLOCKED). VERIFIED answers “was the code checked?”, not “is it safe to execute?”. Consumers that gated on status for safety must switch to the admission field or developer_fields.is_valid.

POST /verify/sql

Updated in v7.0.0 (breaking)
Validate SQL queries against a provided schema. Returns the unified DiagnosticResult shape plus a separate admission decision. Request:
Response (safe query):
A proven-malicious query returns status: "VERIFIED" with developer_fields.is_valid: false, developer_fields.malicious_classification: true, and admission: "BLOCKED" — proving malice is a successful proof, so the truth verdict is preserved while admission is denied. BLOCKED status is reserved for verification failures: sql_verifier.parse_error, sql_verifier.schema_parse_error, sql_verifier.complexity_limit_exceeded, and sql_verifier.execution_error. See the SQL engine page for the full contract.

POST /verify/fact

Verify a factual claim against a provided context. Request:
Response:

POST /verify/consensus

New in v4.0.0 · Updated in v5.0.0
Multi-engine consensus verification. Runs the query through multiple verification engines and requires agreement above a confidence threshold. This endpoint is rate-limited per API key. Mathematical expressions are parsed and compared using Decimal arithmetic internally, which avoids floating-point drift when engines cross-check results.
The fact engine is excluded from automatic engine selection during consensus verification. Fact-based verification requires external context and will return an error if invoked without it, preventing self-referential consensus loops.
Request:
Verification modes: Response:
Only unanimous VERIFIED engine outcomes can produce a VERIFIED consensus. Advisory-only sub-engines (statistical computation, code execution) always return UNVERIFIABLE, so a query answered solely by those paths never satisfies meets_requirement. See the Consensus engine page for the full sub-engine contract.

POST /verify/image

Verify claims about image content. Accepts multipart form data with an image file (max 10 MB). Supported formats: PNG, JPEG, GIF, WebP. Request:
Response:

POST /verify/stats

Verify statistical claims against CSV data. Accepts multipart form data with a CSV file. Statistical code execution requires the secure Docker sandbox. If Docker is unavailable, the endpoint returns HTTP 503. If the verification is blocked by a security policy, it returns HTTP 403. Request:
Response (execution succeeded):
Breaking change (v7.0.0): the endpoint returns the unified DiagnosticResult shape instead of the legacy {"status": "SUCCESS" | "ERROR" | "BLOCKED", "result": ..., "code": ...} shape. Successful execution now reports status: "UNVERIFIABLE" with the observed value in developer_fields.observed_result — execution success alone is never presented as a proven claim, so VERIFIED is not emitted from this endpoint.
Failure states return status: "BLOCKED" with a constraint_id of stats_verifier.validation_error (translation or security validation failed), stats_verifier.execution_failure (sandbox execution failed), or stats_verifier.runtime_unavailable (Docker unavailable). Blocked results carry no proof_ref.
Statistical verification requires a running Docker daemon. If Docker is unavailable, the endpoint returns HTTP 503 instead of falling back to in-process execution. See the Stats engine page for details.

POST /verify/process

New in v4.0.1
Verify the structural integrity of LLM reasoning traces. Supports IRAC structural compliance checking and custom milestone validation with decimal scoring. Request (IRAC mode):
Request (milestones mode):
Response (IRAC mode):
Response (milestones mode):

POST /verify/rag

New in v4.0.1
Verify that retrieved RAG chunks originate from the expected source document. Prevents Document-Level Retrieval Mismatch (DRM) hallucinations in RAG pipelines. Request:
max_drm_rate accepts only string values for symbolic precision. Use fraction notation like "1/10" instead of 0.1.
Response:

POST /verify/batch

Verify multiple items in a single request. Processes all items concurrently and returns aggregated results. Maximum 100 items per batch. Request:
Response: Each entry in items is a per-item response. For math items the verdict is the DiagnosticResult record nested under the item’s result — the same three-layer verdict shape used by POST /verify/math — so batch and single-item math verifications share one contract:
  • result.statusVERIFIED, UNVERIFIABLE, or BLOCKED.
  • result.agent_message — short human-readable summary safe to surface to the caller.
  • result.developer_fields — engine detail (including the legacy is_valid flag for backward compatibility).
  • result.proof_ref — cryptographic hash of the retained proof artifact. Present only when result.status == VERIFIED; null otherwise. This is the authority bit — downstream gates must reject any item whose proof_ref is null.

Math items: proof vs. simplification

Math items are routed through the trust boundary (enforce_trust_decision(require_attestation=True) on VERIFIED, with a signed attestation issued via create_verification_attestation). Three outcomes are possible: If attestation signing fails on an otherwise-verified identity, the item is downgraded to UNVERIFIABLE with developer_fields.constraint_id = "api.attestation.signing_error" — a math result is never returned as VERIFIED without a signed proof.
Bare expressions (no =) always return UNVERIFIABLE. A successful symbolic simplification is not a verified claim. To get a VERIFIED outcome from a math item, submit an equality (e.g., x + x = 2*x).
The pre-v6.0 top-level is_valid field is preserved inside developer_fields.is_valid for backward compatibility, but new code should gate on result.status == "VERIFIED" and the presence of result.proof_ref. The batch response does not include a pass/fail aggregate because a boolean cannot represent the three-status verdict — count items[].result.status == "VERIFIED" entries directly if you need a success ratio.

GET /verify/batch/

Get the status and results of a batch verification job. Use this to poll results when processing large batches. Response:

Verification Context endpoints

New in v7.1.0
These endpoints work with Verification Context v1.0 documents — the standardized JSON record of a verification. All three require an API key and are rate-limited per key.

POST /verification-context/from-diagnostic

Convert a DiagnosticResult into a schema-valid Verification Context document. Use this when you have an engine verdict and need the standardized VC record for auditing or downstream gating. Request:
Response: the full Verification Context document (spec_version, object, context, verdict). Fail-closed behavior:
  • A malformed diagnostic payload is converted to a BLOCKED document instead of being rejected, so the audit trail records the failure.
  • A VERIFIED diagnostic without a valid attestation_token is demoted to UNVERIFIABLE. Attestation is enforced through the same trust boundary as /verify/*.

POST /verification-context/validate

Validate a Verification Context document against the v1.0 JSON Schema, including the verdict/proof_ref invariants. Request:
Response:
An invalid document returns {"valid": false, "error": "validation_failed"} with HTTP 200. Gate on the valid field.

POST /verification-context/resolve

Resolve the proof_ref evidence commitment of a Verification Context document. The server removes the stored proof_ref, re-derives the SHA-256 commitment over the canonical (RFC 8785) bound payload, and compares it to the stored value. Request:
Response:
resolved is true only when the document has verdict: "VERIFIED", validates against the schema, and the stored proof_ref matches the re-derived commitment. Any other outcome (non-VERIFIED verdict, schema failure, mismatched or missing commitment) returns {"resolved": false} — a proof_ref that cannot be resolved confers no authority.

Agent endpoints

POST /agents/register

Register a new AI agent with QWED for verified agentic workflows. Request:
Agent types: Response:
Store the agent_token immediately — it cannot be retrieved again after registration.

POST /agents//verify

Updated in v5.0.0
Verify a claim using an agent token. Creates an auditable record tied to the agent. Security checks are enforced server-side — exfiltration detection always runs, and MCP poisoning detection runs automatically when a tool_schema is provided.
Breaking change (v5.0.0): The security_checks request field has been removed. Security checks are now mandatory and enforced server-side. You no longer need to (or can) opt in to exfiltration or MCP poison checks.
Breaking change (v5.0.0): The context field with conversation_id and step_number is now required for all agent action verification requests. Requests without these fields are rejected with error code QWED-AGENT-CTX-001. See conversation controls for details.
Request:
Headers:
Security behavior:
  • Exfiltration check: Always runs on every agent verification request. If the query payload is flagged, the request is rejected with a 403.
  • MCP poison check: Runs automatically when tool_schema is present. If the tool definition is flagged, the request is rejected with a 403.
Error responses:

POST /agents//tools/

Submit an agent tool call for risk evaluation before execution. Unknown tools (not on the safe or dangerous operations list) are denied by default, regardless of risk score. See tool approval policy for details. Request:
Possible outcomes:

GET /agents//activity

Retrieve the audit log for a specific agent. Provides a full audit trail of all agent actions. Headers:
Query params: Response:

Attestation endpoints

GET /attestation/

Get an attestation by ID.

POST /attestation/verify

Verify an attestation JWT. Request:

Observability endpoints

GET /metrics

Returns global system metrics and per-tenant breakdowns. This is a cross-tenant, platform-operator capability: the caller must be a user ID listed in QWED_METRICS_OPERATOR_USER_IDS (comma-separated, fail-closed when unset). Organization roles (owner / admin) do not grant access — they are scoped to a single organization. Headers (one of):
An API key resolves through its owning user, so the key must belong to an active user on the allowlist. Expired or revoked keys are not usable credentials; if a request carries both an API key and a JWT, the JWT can still authorize the read. Response:

GET /metrics/

Returns metrics scoped to a specific organization. Tenants can only view their own metrics.

GET /metrics/prometheus

Returns metrics in Prometheus text format for scraping by monitoring infrastructure. Requires the same platform-operator authentication as GET /metrics. Headers (one of):

GET /logs

Returns verification logs for the authenticated tenant, ordered by most recent first. Query params: Response:

Admin endpoints

New in v4.0.0
These endpoints require the admin:all API key scope.

GET /admin/compliance/export/csv

Export the full audit trail as a CSV file.

GET /admin/compliance/verify/

Cryptographically verify a specific audit log entry using HMAC-SHA256 and hash-chain validation. The response reports three independent checks: payload hash, HMAC signature (compared in constant time), and chain linkage to the prior entry within the same organization. Genesis entries must have a null previous_hash; non-genesis entries must link to a non-empty prior entry hash. Entries with malformed stored result payloads cause verification to fail closed with SecurityError instead of returning "valid": true. Hash matching accepts either the current canonical payload (which includes raw_llm_output) or the legacy canonical payload, so entries written before that field was covered remain verifiable after the upgrade. Response:
AuditLogger requires QWED_AUDIT_SECRET_KEY to be set. If the key is missing or persisted chain continuity cannot be loaded, initialization raises SecurityError and verification endpoints fail closed.

GET /admin/compliance/report/soc2/

Generate a SOC 2 Type II compliance report for an organization.

GET /admin/security/threats/

Returns a real-time threat summary for an organization, including blocked injection attempts and anomalous patterns.

POST /admin/keys/rotate

Rotate an API key. Available to admin and member roles. Request:

Badge endpoints

All badge endpoints return SVG images (image/svg+xml). You can embed them directly in Markdown or HTML.

GET /badge/verified

Get a verified or failed badge SVG.

GET /badge/status/

Get a badge for any verification status (e.g., VERIFIED, FAILED, CORRECTED, BLOCKED, PENDING, ERROR).

GET /badge/attestation/

Get a badge for a specific attestation by ID.

GET /badge/engine/

Get a badge for a specific verification engine.

GET /badge/custom

Generate a custom badge with configurable label, message, color, and logo.