How a machine asks

One question, one verdict, one authority.

Ask whether a specific proposition about a specific subject is supported. You get a state, the authority behind it, and the signature. You never get a guess.

Honest cannot-answer — when no authority publishes this field for this subject class
An unverifiable response carries HTTP 200 with the recorded reason. An absent answer is a real answer, never an error. The reason traces to a specific scope limitation of the consulted authorities.
$ GET /v1/verify?subject=practitioner:mo-dental:009507&proposition=accepting_patients
→ 200 OK { "provenance": "SCHEMA EXAMPLE — NOT A READING", "kind": "fact", "state": "UNVERIFIABLE", "reason": "no_authority_holds_predicate_for_subject_class", "authorities_consulted": ["mo-dental-board", "cms-nppes"], "checked_at": "—", "next_required_by": null, "next_required_by_note": "UNMEASURED — three monthly files needed before horizons are measured", "signature": "<the record's actual Ed25519 signature bytes>" }
provenance: SCHEMA EXAMPLE — NOT A READING
Clean verification — when an authority reading supports the proposition
A verified response names the authority whose published file supports it. The reading is attributed — the authority, not us, is the source. Freshness is UNMEASURED until three monthly reading cycles exist.
$ GET /v1/verify?subject=Missouri dental practitioner — board license 013494&proposition=address_of_record
→ 200 OK { "provenance": "LIVE READ · checked_at 2026-09-04T04:26:56.000Z", "kind": "fact", "state": "VERIFIED", "authority": "Missouri Dental Board (board roster artifact:artifact:mopro:mo-dental:cd7792d3a1a8411c)", "value": "2500 Castle Dr, Independence, Missouri, 64057", "checked_at": "2026-09-04T04:26:56.000Z", "next_required_by": "2026-11-30T06:00:00.000Z", "signature": "<the record's actual Ed25519 signature bytes>" }
provenance: LIVE READ · checked_at 2026-09-04T04:26:56.000Z
Real disagreement — two named authorities carry different readings for the same bound subject
Both readings are kept; neither is discarded. A disagreement requires two named authorities, a bound subject, a comparable field and time, and both readings non-empty. The "previous reading / current reading" empty-vs-date pattern is NOT a cross-authority conflict — it never renders here.
$ GET /v1/verify?subject=Missouri licence 015828 ↔ NPPES record 1275674715&proposition=licence_to_record_association
→ 200 OK { "provenance": "LIVE READ · checked_at 2026-09-18T20:07:45Z", "kind": "fact", "state": "CONTESTED", "subject": "Missouri licence 015828 ↔ NPPES record 1275674715", "field": "licence_to_record_association", "rule": "NAME-COMPARISON-1", "readings": [ { "authority": "mo-dental-board", "value": "CAMMIE L HOUSH" }, { "authority": "cms-nppes", "value": "MICHAEL HOUSH" } ], "resolution": "both readings kept; neither is discarded", "evidence": { "epoch_computed_at": "2026-09-18T20:07:45Z", "record": "/verify/crosswalk-epochs/epoch-20260918T200745Z.json", "board_roster_sha256": "9c17d20b14243445b6280c3617eef6bc5c4eaf0b6836a2dec56c63d3d43ff2fa", "nppes_pool_sha256": "0131fe216272dda200bff661ddb39ff22a03abaee34d21e6a4888d3d7b055e39" }, "signature": "<the record's actual Ed25519 signature bytes>" }
provenance: LIVE READ · checked_at 2026-09-18T20:07:45Z
Bounded proposition (field: licence-to-record-association): an NPPES record publishes an association with a licence whose board attribution is incompatible under the stated rule. The subject is the licence-to-record binding: Missouri licence 015828 ↔ NPPES record 1275674715. NPPES record 1275674715 cites Missouri licence 015828, and the board lists 015828 under a different name. The licence joined to NPPES record 1538207865, whose name matches.
rejected join candidate — NPPES 1275674715: MICHAEL HOUSH (kept as a finding; board listing: CAMMIE L HOUSH)
the record the licence joined to — NPPES 1538207865: whose name matches the board listing for licence 015828
Both are public registry facts read from the two authorities; nothing here says which reading is at fault, and neither person's name is called disputed.
evidence: the signed epoch record · computed 2026-09-18T20:07:45Z · board roster + NPPES pool of that epoch
Stale — the last reading is past its re-check deadline
A stale proposition retains its last supported reading (kept verbatim) and carries its re-check deadline as a real computed date — here the policy interval, 90 days after checked_at, and already passed. Re-observe before relying; until three monthly cycles exist the horizon is POLICY, never MEASURED.
$ GET /v1/verify?subject=Missouri dental practitioner — board license 013494&proposition=address_of_record
→ 200 OK { "provenance": "SCHEMA EXAMPLE — NOT A READING", "kind": "fact", "state": "STALE", "authority": "Missouri Dental Board (board roster artifact:artifact:mopro:mo-dental:cd7792d3a1a8411c)", "retained_reading": "2500 Castle Dr, Independence, Missouri, 64057", "checked_at": "2026-03-25T16:16:41Z", "next_required_by": "2026-06-23T16:16:41Z", "next_required_by_note": "POLICY — 90 days from checked_at until three monthly cycles allow a MEASURED horizon", "note": "re-check deadline passed — re-observe before relying", "signature": "<the record's actual Ed25519 signature bytes>" }
provenance: SCHEMA EXAMPLE — NOT A READING
Operation error — the check could not be attempted (here: no identifier supplied)
An operation error is distinct from a refusal: the check could not be attempted, so it carries NO fact state — the structured envelope says so explicitly (fact_state: null). Missing identifiers, transport failures, and upstream unavailability produce this shape — never a silent substitution of a VERIFIED or UNVERIFIABLE verdict.
$ GET /v1/verify?subject=&proposition=name_normalized
→ 200 OK { "provenance": "SCHEMA EXAMPLE — NOT A READING", "kind": "operation_error", "state": "operation-error", "error": { "code": "OPERATION_ERROR", "class": "missing_identifier", "message": "the check could not be attempted — no identifier was supplied", "retryable": false, "fact_state": null }, "checked_at": null }
provenance: SCHEMA EXAMPLE — NOT A READING

Honest cannot-answer

An unverifiable proposition returns a state and a reason with a 200. An absent answer is a real answer, never an error.

Freshness in the payload

Every response carries when it was checked, and the re-check horizon when one is measured. Unmeasured horizons say so — never a coerced date.

Re-derivable offline

The signature covers the canonical form. A caller can verify it with the published key without talking to us again.

How a fact gets hereTechnical documentation

This interface is a demonstration surface: no API keys are issued, and no integration is required to commission an engagement — the deliverable is signed findings with evidence, not an API contract. Response bodies are labeled LIVE READ or SCHEMA EXAMPLE by their own provenance tag; signature fields in examples are labeled illustrative. Each example carries exactly one provenance label — two labels on one example fails the build.