Skip to main content

Base URL

https://api.qwedai.com/v1

Health check

GET /health

Check API status. No authentication required.
curl https://api.qwedai.com/v1/health
Response:
{
  "status": "healthy",
  "service": "QWED Platform",
  "version": "5.0.0",
  "timestamp": "2024-12-20T12:00:00Z"
}

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:
{
  "query": "What is 15% of 200?",
  "provider": "openai"
}
ParameterTypeRequiredDescription
querystringYesNatural language claim to verify
providerstringNoPreferred LLM provider (e.g., openai, anthropic)
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": "INCONCLUSIVE",
  "user_query": "What is 15% of 200?",
  "translation": {
    "expression": "0.15 * 200",
    "claimed_answer": 30.0,
    "reasoning": "15% as decimal is 0.15, multiply by 200",
    "confidence": 0.95
  },
  "verification": {
    "calculated_value": 30.0,
    "is_correct": true,
    "diff": 0.0
  },
  "trust_boundary": {
    "query_interpretation_source": "llm_translation",
    "query_semantics_verified": false,
    "verification_scope": "translated_expression_only",
    "deterministic_expression_evaluation": true,
    "formal_proof": false,
    "translation_claim_self_consistent": true,
    "provider_used": "openai_compat",
    "overall_status": "INCONCLUSIVE"
  },
  "final_answer": 30.0,
  "provider_used": "openai_compat",
  "latency_ms": 245.3
}
Status values for natural language math verification:
StatusMeaning
INCONCLUSIVEExpression evaluation succeeded, but the LLM translation step is non-deterministic so the result cannot be treated as a proven verdict on the original user query
ERRORThe translated expression had a syntax error or the engine could not evaluate it
NOT_MATH_QUERYThe query was not recognized as a mathematical question
BLOCKEDRequest blocked by security policy
The status field was previously set 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:
FieldTypeDescription
query_interpretation_sourcestringAlways "llm_translation"
query_semantics_verifiedbooleanAlways false — QWED cannot verify that the LLM correctly interpreted the user’s intent
verification_scopestringAlways "translated_expression_only"
deterministic_expression_evaluationbooleantrue when the inner engine status was VERIFIED or CORRECTION_NEEDED
formal_proofbooleanAlways false
translation_claim_self_consistentbooleanWhether the translated expression matched its own claimed answer
provider_usedstringLLM provider used for translation
overall_statusstringMirrors the top-level status field

POST /verify/math

New in v5.0.0: verify_identity() numerical sampling fallback now returns UNKNOWN instead of LIKELY_EQUIVALENT.
Verify mathematical expressions or equations using SymPy symbolic computation. Request:
{
  "expression": "x**2 + 2*x + 1 = (x+1)**2",
  "context": {
    "domain": "real"
  }
}
ParameterTypeRequiredDescription
expressionstringYesMathematical expression or equation. Use = for equations
contextobjectNoOptional context (e.g., {"domain": "real"} to restrict to real numbers)
Response (equation):
{
  "is_valid": true,
  "result": true,
  "left_side": "x**2 + 2*x + 1",
  "right_side": "(x + 1)**2",
  "simplified_difference": "0",
  "message": "Identity is true"
}
Response (expression):
{
  "is_valid": true,
  "value": 4.0,
  "simplified": "4",
  "original": "2 + 2"
}
Symbolic expressions that cannot be evaluated to a numeric value include is_symbolic: true. Expressions involving complex numbers include is_complex: true. Ambiguous expressions (e.g., implicit multiplication after division) return a warning: "ambiguous" field. 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.

POST /verify/logic

Verify logical constraints. Routes through the QWED Control Plane. Request:
{
  "query": "(AND (GT x 5) (LT y 10))",
  "provider": "openai"
}
ParameterTypeRequiredDescription
querystringYesLogical constraint in DSL or natural language
providerstringNoPreferred LLM provider
Response:
{
  "status": "SAT",
  "model": {"x": "6", "y": "9"},
  "provider_used": "openai_compat"
}
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.
StatusMeaning
SATSatisfiable — a solution exists
UNSATUnsatisfiable — no solution possible
BLOCKEDRequest blocked by security policy (returns HTTP 403)
ERRORInternal verification error
Error response:
{
  "status": "ERROR",
  "error": "Internal verification error",
  "provider_used": "openai_compat"
}

POST /verify/code

Check code for security vulnerabilities using AST analysis. Request:
{
  "code": "import os\nos.system('rm -rf /')",
  "language": "python"
}
ParameterTypeRequiredDescription
codestringYesSource code to analyze
languagestringNoProgramming language (default: python)
Response:
{
  "is_safe": false,
  "vulnerabilities": [
    {
      "type": "os.system",
      "severity": "critical",
      "line": 2,
      "message": "Shell command execution"
    }
  ]
}
FieldTypeDescription
is_safebooleanWhether the code passed all security checks
vulnerabilitiesarrayList of detected vulnerabilities with type, severity, line number, and message

POST /verify/sql

Validate SQL queries against a provided schema. Request:
{
  "query": "SELECT * FROM users WHERE id = 1",
  "schema_ddl": "CREATE TABLE users (id INT, name TEXT)",
  "dialect": "sqlite"
}
ParameterTypeRequiredDescription
querystringYesSQL query to validate
schema_ddlstringYesDDL schema definition (e.g., CREATE TABLE statements)
dialectstringNoSQL dialect (default: sqlite)
Response:
{
  "is_valid": true,
  "message": "Query is valid against the provided schema"
}

POST /verify/fact

Verify a factual claim against a provided context. Request:
{
  "claim": "Paris is the capital of France",
  "context": "France is a country in Western Europe. Its capital is Paris.",
  "provider": "anthropic"
}
ParameterTypeRequiredDescription
claimstringYesThe factual statement to verify
contextstringYesReference text to verify the claim against
providerstringNoPreferred LLM provider
Response:
{
  "verdict": "SUPPORTED",
  "confidence": 0.98,
  "reasoning": "The context explicitly states that the capital of France is Paris"
}
VerdictMeaning
SUPPORTEDClaim is supported by the context
REFUTEDClaim contradicts the context
INCONCLUSIVENot enough evidence in the context

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:
{
  "query": "The square root of 144 is 12",
  "verification_mode": "high",
  "min_confidence": 0.95
}
ParameterTypeRequiredDefaultDescription
querystringYesThe claim to verify
verification_modestringNosinglesingle, high, or maximum
min_confidencefloatNo0.95Minimum confidence threshold, 0–1
Verification modes:
ModeEnginesUse case
single1Fast, single engine verification
high2Higher confidence for important claims
maximum3+Critical domains (medical, financial)
Response:
{
  "final_answer": "12",
  "confidence": 98.5,
  "engines_used": 2,
  "agreement_status": "UNANIMOUS",
  "verification_chain": [
    {
      "engine": "math",
      "method": "symbolic",
      "result": "12",
      "confidence": 99.0,
      "latency_ms": 12.5,
      "success": true
    }
  ],
  "total_latency_ms": 45.2,
  "meets_requirement": true
}
FieldTypeDescription
confidencefloatConfidence as a percentage (0–100)
verification_chainarrayDetailed results from each engine
meets_requirementbooleanWhether confidence meets min_confidence
StatusDescription
400Invalid verification mode
422Consensus confidence below the requested min_confidence threshold
503Secure Docker sandbox unavailable — required for Python engine in high/maximum mode

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:
curl -X POST https://api.qwedai.com/v1/verify/image \
  -H "X-API-Key: qwed_your_key" \
  -F "image=@photo.jpg" \
  -F "claim=The image is 800x600 pixels"
ParameterTypeRequiredDescription
imagefileYesImage file (max 10 MB; PNG, JPEG, GIF, WebP)
claimstringYesThe claim about the image to verify
Response:
{
  "verdict": "SUPPORTED",
  "confidence": 0.95,
  "reasoning": "Image dimensions match the claimed resolution",
  "methods_used": ["metadata_analysis", "pixel_inspection"]
}
VerdictMeaning
SUPPORTEDClaim is confirmed by image analysis
REFUTEDClaim contradicts image analysis
INCONCLUSIVECannot determine from available methods
VLM_REQUIREDVisual Language Model needed for deeper analysis

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:
curl -X POST https://api.qwedai.com/v1/verify/stats \
  -H "X-API-Key: qwed_your_key" \
  -F "file=@data.csv" \
  -F "query=The average salary is above 50000"
ParameterTypeRequiredDescription
filefileYesCSV data file
querystringYesStatistical claim to verify
Response:
{
  "status": "SUCCESS",
  "computed_value": 52340.5,
  "message": "Statistical claim verified against dataset"
}
StatusDescription
403Verification blocked by security policy (e.g., generated code failed AST safety checks)
503Secure Docker sandbox unavailable — statistical verification requires Docker
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 AI reasoning traces. Supports IRAC structural compliance checking and custom milestone validation with decimal scoring. Request (IRAC mode):
{
  "trace": "The issue is whether the contract was breached. The rule is Article 2 of the UCC. Applying this rule, the defendant failed to deliver on time. In conclusion, breach occurred.",
  "mode": "irac"
}
Request (milestones mode):
{
  "trace": "Risk assessment complete. Compliance check passed. Implementation timeline defined.",
  "mode": "milestones",
  "milestones": ["risk assessment", "compliance check", "implementation"]
}
ParameterTypeRequiredDefaultDescription
tracestringYesThe AI reasoning trace to validate
modestringNoiracirac or milestones
milestonesstring[]ConditionalRequired when mode is milestones
Response (IRAC mode):
{
  "verified": true,
  "score": 1.0,
  "missing_steps": [],
  "mechanism": "Regex Pattern Matching (Deterministic)"
}
Response (milestones mode):
{
  "verified": true,
  "process_rate": 1.0,
  "missed_milestones": []
}
StatusDescription
400Invalid mode or missing milestones when mode is milestones

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:
{
  "target_document_id": "contract_nda_v2",
  "chunks": [
    { "id": "c1", "metadata": { "document_id": "contract_nda_v2" } },
    { "id": "c2", "metadata": { "document_id": "contract_nda_v1" } }
  ],
  "max_drm_rate": "0"
}
ParameterTypeRequiredDefaultDescription
target_document_idstringYesExpected source document ID
chunksobject[]YesArray of chunk objects with metadata
max_drm_ratestringNo"0"Maximum tolerable mismatch fraction as a Fraction-compatible string (e.g. "0", "1/10")
max_drm_rate accepts only string values for symbolic precision. Use fraction notation like "1/10" instead of 0.1.
Response:
{
  "verified": false,
  "risk": "DOCUMENT_RETRIEVAL_MISMATCH",
  "drm_rate": 0.5,
  "chunks_checked": 2,
  "mismatched_count": 1
}
StatusDescription
400Invalid request payload (empty target_document_id, empty chunks, or invalid max_drm_rate value)

POST /verify/batch

Verify multiple items in a single request. Processes all items concurrently and returns aggregated results. Maximum 100 items per batch. Request:
{
  "items": [
    {"query": "What is 2+2?", "type": "natural_language"},
    {"query": "(AND (GT x 5) (LT y 10))", "type": "logic"},
    {"query": "x**2 + 2*x + 1 = (x+1)**2", "type": "math"}
  ]
}
ParameterTypeRequiredDescription
itemsarrayYesArray of verification items (max 100)
items[].querystringYesThe claim to verify
items[].typestringNoVerification type: natural_language, logic, math, code, fact, sql (default: natural_language)
items[].paramsobjectNoAdditional parameters for the verification
Response:
{
  "job_id": "batch_abc123",
  "status": "completed",
  "results": [...],
  "summary": {
    "total": 3,
    "verified": 3,
    "failed": 0,
    "success_rate": 100.0
  }
}

GET /verify/batch/

Get the status and results of a batch verification job. Use this to poll results when processing large batches. Response:
{
  "job_id": "batch_abc123",
  "status": "completed",
  "results": [...]
}
StatusDescription
403Access denied — job belongs to a different organization
404Job not found

Agent endpoints

POST /agents/register

Register a new AI agent with QWED for verified agentic workflows. Request:
{
  "name": "FinanceBot",
  "agent_type": "semi_autonomous",
  "description": "Financial analysis agent",
  "permissions": ["math", "logic", "code"],
  "max_cost_per_day": 50.0
}
ParameterTypeRequiredDefaultDescription
namestringYesAgent display name
agent_typestringNoautonomousautonomous, semi_autonomous, or assistant
descriptionstringNoAgent description
permissionsarrayNo[]Allowed verification engine names (e.g., math, logic, code)
max_cost_per_dayfloatNo100.0Daily budget cap in USD
Agent types:
TypeDescription
autonomousFully autonomous agent (AutoGPT-style)
semi_autonomousRequires approval for critical actions
assistantHuman-in-the-loop
Response:
{
  "agent_id": 42,
  "agent_token": "qwed_agent_...",
  "name": "FinanceBot",
  "type": "semi_autonomous",
  "status": "active",
  "max_cost_per_day": 50.0,
  "message": "Agent registered successfully. Store the agent_token securely."
}
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:
{
  "query": "What is 15% of 200?",
  "provider": "openai",
  "context": {
    "conversation_id": "conv_abc123",
    "step_number": 1
  },
  "tool_schema": {
    "name": "fetch_report",
    "description": "Fetch quarterly report data"
  }
}
ParameterTypeRequiredDescription
querystringYesThe claim to verify
providerstringNoLLM provider preference
contextobjectYesAction context — see below
context.conversation_idstringYesUnique identifier for the conversation/session
context.step_numberintegerYesMonotonically increasing step counter (>= 1)
tool_schemaobjectNoMCP tool definition to scan. When provided, MCPPoisonGuard runs automatically
Headers:
X-Agent-Token: qwed_agent_...
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:
StatusDescription
401Invalid agent token
403Agent budget exceeded or request blocked by security checks
500Internal agent verification error

POST /agents//tools/

Submit an agent tool call for risk evaluation before execution. Request:
{
  "tool_params": {
    "query": "SELECT * FROM users",
    "dialect": "postgresql"
  }
}

GET /agents//activity

Retrieve the audit log for a specific agent. Provides a full audit trail of all agent actions. Headers:
X-Agent-Token: qwed_agent_...
Query params:
ParameterTypeDefaultDescription
limitinteger20Maximum number of activity records to return
Response:
{
  "agent_id": 42,
  "agent_name": "FinanceBot",
  "total_activities": 5,
  "current_cost_today": 0.05,
  "max_cost_per_day": 50.0,
  "activities": [
    {
      "type": "verification_request",
      "description": "Query: What is 15% of 200?",
      "status": "success",
      "cost": 0.01,
      "timestamp": "2026-03-20T12:00:00Z"
    }
  ]
}
StatusDescription
401Invalid agent token

Attestation endpoints

GET /attestation/

Get an attestation by ID.

POST /attestation/verify

Verify an attestation JWT. Request:
{
  "jwt": "eyJhbGciOiJFUzI1NiIs..."
}

Observability endpoints

GET /metrics

Returns global system metrics and per-tenant breakdowns. Requires admin authentication — you must provide either a JWT token for an active user with the owner or admin role, or an API key linked to an active owner or admin user. Headers (one of):
Authorization: Bearer <jwt_token>
X-API-Key: <api_key>
Response:
{
  "global": { "total_requests": 1250, "avg_latency_ms": 82.3 },
  "tenants": { "1": { "requests": 500 }, "2": { "requests": 750 } }
}
StatusDescription
401No authentication provided
403Authenticated but not an active admin or owner

GET /metrics/

Returns metrics scoped to a specific organization. Tenants can only view their own metrics.
StatusDescription
403You can only view metrics for your own organization

GET /metrics/prometheus

Returns metrics in Prometheus text format for scraping by monitoring infrastructure. Requires the same admin authentication as GET /metrics. Headers (one of):
Authorization: Bearer <jwt_token>
X-API-Key: <api_key>
StatusDescription
401No authentication provided
403Authenticated but not an active admin or owner

GET /logs

Returns verification logs for the authenticated tenant, ordered by most recent first. Query params:
ParameterTypeDefaultDescription
limitinteger10Maximum number of logs to return
Response:
{
  "organization_id": 1,
  "organization_name": "Acme Corp",
  "total_logs": 3,
  "logs": [
    {
      "id": 42,
      "query": "What is 2+2?",
      "is_verified": true,
      "domain": "MATH",
      "timestamp": "2026-03-20T12:00:00Z"
    }
  ]
}

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 and hash chain validation.

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:
{
  "key_id": "key_abc123"
}

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.
ParameterTypeDefaultDescription
verifiedbooleantrueWhether to show a verified or failed badge

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.
ParameterTypeDefaultDescription
verifiedbooleantrueWhether to show a verified or failed badge

GET /badge/custom

Generate a custom badge with configurable label, message, color, and logo.
ParameterTypeDefaultDescription
labelstringQWEDLeft side label
messagestringverifiedRight side message
colorstringHex color (e.g., #00C853)
logobooleantrueInclude QWED logo