Docs · API tour
Docs · API tour
Check every AI draft before it leaves.
Attestiq is one API call after each draft. Your agent sends the draft and the records it was written from. Attestiq returns a verdict, the errors it found, the rule each one breaks, and signed evidence.
Access
Access is by pilot invitation; there is no self-serve signup. The production base URL, https://api.attestiq.ai, is planned. Pilot clients get keys and the current base URL from us. Write to pilot@attestiq.ai.
How it fits into your workflow
Take an agent that drafts chargeback responses. Today someone re-reads every draft. With Attestiq, the agent calls the API after each draft and your workflow routes on the verdict. People review only what is held.
Your systems
Your agent drafts
A chargeback response, a dispute letter, a retry policy. Your case system holds the records.
Attestiq · POST /v1/validate/validations
- 1 Reject card numbers, redact names
- 2 Extract claims from the draft
- 3 Check them against records and rules
- 4 Code sets the verdict
- 5 Sign the evidence
Your systems act
- pass · send it
- pass_with_warnings · send, log notes
- hold · a reviewer decides
- fail · back to the agent
Core concepts
Code decides. Models read. Evidence proves. A person approves. Every verdict is computed by versioned code from the findings. Models are off unless you turn them on. When they are on, they can only add findings that quote the draft and cite a rule, and they never set a verdict, a deadline, or a dollar figure.
Every check is an object. Each call creates a Validation with an id like val_…. You can fetch it later, list it, recompute its evidence, and see who reviewed it.
A Validation has two states. status tracks the run: queued → running → completed (or failed). review_status tracks the people: not_required, or pending → released, blocked, or returned.
Rules are data. Each workload (for example disputes.representment) maps to a policy pack, such as disputes-us@0.2.0. Every finding names its rule, its citation, and whether an expert has reviewed that rule yet (citation.review_status).
Core objects
Six objects cover the whole integration. IDs are prefixed strings; timestamps are ISO-8601 UTC; money is integer cents.
Validation
val_…One check of one AI output against its records and a pinned policy pack. Carries the verdict, the score, the review status, and the findings.
Finding
fnd_…One typed error: a code such as FACT.AMOUNT_MISMATCH, a severity, expected and observed values, the record it was checked against, and the rule it breaks with a citation.
Evidence record
EV-…A signed record of one step: the input fingerprint, the extracted claims, each finding, the verdict. SHA-256 over canonical JSON; anyone can recompute it.
Audit event
seqWho did what, and when: submissions, reviews, setting changes. Each event hashes the one before it, so an edited event breaks the chain.
Eval run
evl_…Your agent's historical outputs run through the validator in one batch: precision and recall per error code, top failure patterns.
Webhook
whe_… / whd_…An endpoint you register, and the signed deliveries sent to it when a validation completes, is held, or is reviewed.
Request lifecycle
What happens between your request and the verdict:
- Intake. The output is fingerprinted (SHA-256). Records are checked for card numbers; any full card number rejects the request. Names and contact details are redacted before anything is stored.
- Claims. Code extracts the amounts, dates, reason codes, card digits, and outcomes the draft states, each with the sentence it came from.
- Checks. Fact, math, policy, and disclosure checks compare the claims with your records and the rules in the pinned policy pack.
- Verdict. Code computes the verdict and score from the findings' severities. A model, when enabled, may add cited findings; it never sets the verdict.
- Evidence. Each step is written as a signed evidence record; the submission lands on your tenant's audit chain.
- Delivery. Sync mode returns the validation in the response. Async mode returns 202 and sends a signed webhook when the verdict is ready.
- Review. Hold and fail verdicts wait for a person in your team to release, block, or return the draft. The decision is audited with its rationale.
The verdict follows from the most severe finding that counts (advisory findings never count): any critical finding gives fail; high gives hold; medium gives pass_with_warnings; otherwise pass. The score starts at 100 and loses 45, 20, 8, or 2 points per critical, high, medium, or low finding, down to 0.
status queued ──▶ running ──▶ completed
└──▶ failed (validator error; see "error")
verdict pass | pass_with_warnings | hold | fail
(set once, when status is completed)
review_status not_required (pass, pass_with_warnings)
pending ──▶ released (hold, fail)
├─▶ blocked
└─▶ returned (return_to_agent)Five-minute quickstart
Your first verdict
- Check your key.
GET /v1/meshows your role, your tenant, and whether the tenant is a synthetic sandbox. Your agent uses aservicekey: it can submit and read, nothing else. - Send a draft.
POST /v1/validate/validationswith the workload, your agent's id, the draft, and the records it was written from. The example is a synthetic Mastercard second presentment. - Route on the verdict. This draft is
hold, score 60: it was filed seven days after the 45-day window, and it encloses an invoice where a non-receipt dispute needs proof of delivery. Each finding points to the record field and the rule.
Using an MCP-capable agent framework? Add the attestiq-mcp server and the agent gets a validate_output tool. See MCP tools.
The full setup, including async mode, webhooks, and a go-live checklist, is in the quickstart.
curl https://api.attestiq.ai/v1/me -H "X-API-Key: $ATTESTIQ_API_KEY"
{
"key_id": "key_…", "name": "dispute-drafter agent", "email": "",
"role": "service", "kind": "service",
"permissions": ["authorize:read", "evidence:read", "policy:read",
"validate:read", "validate:submit"],
"tenant": {"id": "…", "name": "…", "kind": "processor", "synthetic": true},
"entitlements": {"validate": {"module": "validate", "plan": "pilot", "status": "active",
"quota": 10000, "period": "month", "used_this_month": 26, ...}},
"model_gateway": {"provider": "none", "models": {}, "mode": "deterministic"},
"version": "0.1.0"
}curl https://api.attestiq.ai/v1/validate/validations \
-H "X-API-Key: $ATTESTIQ_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"workload": "disputes.representment",
"agent": {"id": "chargeback-responder", "version": "0.9.0"},
"output": "Second presentment — Mastercard chargeback CB-77120\n\nMerchant: Lumen Travel Gear. Transaction amount: $249.00 on July 2, 2026, card ending in 8820. ...",
"records": [
{"type": "transaction", "id": "TXN-51007", "data": {
"amount_cents": 24900, "currency": "USD", "transaction_date": "2026-07-02",
"merchant_name": "Lumen Travel Gear", "network": "mastercard",
"card_type": "credit", "card_last4": "8820"}},
{"type": "chargeback", "id": "CB-77120", "data": {
"network": "mastercard", "reason_code": "4853", "category": "not_received",
"chargeback_date": "2026-07-28", "amount_cents": 24900}},
{"type": "representment", "id": "REP-77120", "data": {
"response_date": "2026-09-18", "evidence": ["invoice"]}}
],
"external_id": "CB-77120",
"idempotency_key": "CB-77120-draft-1"
}
JSONHTTP/1.1 201 Created
X-Request-ID: 3f9c1a7e2b6d4c80
{
"id": "val_01a0b7f8cd7cd4e8b76923ba",
"object": "validation",
"purpose": "production",
"workload": "disputes.representment",
"policy_pack": "disputes-us@0.2.0",
"agent": {"id": "chargeback-responder", "version": "0.9.0", "model": ""},
"external_id": "CB-77120",
"status": "completed",
"verdict": "hold",
"score": 60,
"counts": {"total": 2, "binding": 2, "advisory": 0,
"by_severity": {"high": 2},
"by_code": {"POLICY.MISSING_REQUIRED_EVIDENCE": 1, "POLICY.TIMELINE_VIOLATION": 1}},
"review_status": "pending",
"summary": "Hold — a reviewer must decide before this document is released. Score 60/100. ...",
"summary_source": "template",
"output_hash": "sha256:6f892b5aa2f165f537c46ad74ca8cd44a1a1f340d7dc3e0820faa4a8888d95a4",
"verdict_ref": "EV-2026-1M2VZHKBZWN8S6",
"evidence_refs": ["EV-2026-1M2VZHKBWYQD81", "EV-2026-1M2VZHKBXJKDCB", "EV-2026-1M2VZHKBYNYCTZ",
"EV-2026-1M2VZHKBYRGPYK", "EV-2026-1M2VZHKBZWN8S6"],
"usage": {"tokens_in": 0, "tokens_out": 0, "steps": 10, "latency_ms": 0, "llm_calls": 0,
"model_mode": "deterministic", "trace": {"ok": 7, "skipped": 3}},
"error": null,
"submitted_by": "service:key_demo_06",
"created_at": "2026-09-18T16:42:11Z",
"completed_at": "2026-09-18T16:42:11Z",
"reviewed_by": null,
"reviewed_at": null,
"review_rationale": null,
"storage_mode": "redacted",
"content_purged_at": null,
"findings": [
{ "id": "fnd_01a0b7f8cd803dbb97fe4400", "code": "POLICY.MISSING_REQUIRED_EVIDENCE", "...": "..." },
{
"id": "fnd_01a0b7f8cd8083258e369f36",
"code": "POLICY.TIMELINE_VIOLATION",
"family": "policy",
"severity": "high",
"validator": "policy",
"assurance": "deterministic",
"message": "Deadline missed by 7 day(s): Mastercard allows 45 calendar days to respond. Received 2026-07-28, due 2026-09-11, issued 2026-09-18.",
"quote": "",
"expected": "on or before 2026-09-11",
"observed": "2026-09-18",
"rule_id": "NET-REP-WINDOW",
"citation": {
"pack": "disputes-us@0.2.0",
"rule_id": "NET-REP-WINDOW",
"cite": "Visa Dispute Management Guidelines (dispute response); Mastercard Chargeback Guide (second presentment)",
"source": "Visa Core Rules and Visa Product and Service Rules; Visa Dispute Management Guidelines",
"url": "https://usa.visa.com/support/small-business/dispute-resolution.html",
"review_status": "unreviewed"
},
"record_ref": "chargeback:CB-77120#chargeback_date",
"confidence": 1.0,
"related": [],
"evidence_ref": "EV-2026-1M2VZHKBYRGPYK",
"label": null,
"label_note": null,
"labeled_by": null
}
]
}