Public records via REST.
Programmatic access to supported public-record surfaces across healthcare, procurement, sanctions and watchlists, enforcement, and company registers. Source URL, observation time, confidence, methodology, coverage, and limitations fields vary by route and source; inspect the endpoint contract and actual response before relying on them.
Base URL: https://api.fonteum.com/v1 · OpenAPI: https://api.fonteum.com/v1/openapi.json · Status: https://api.fonteum.com/v1/health
/api/v1/health and /api/v1/status share one canonical operational state. It reports transport uptime, pipeline freshness, source completeness, and incidents separately; the source-report findings_state is detail, not a second service headline. The raw /api/health endpoint remains an HTTP-200 transport-liveness probe even when its body reports a non-operational state. The non-versioned /api/statusendpoint powers the public status board; its dataset telemetry is auxiliary diagnostic detail and never changes the canonical headline.
GET /v1/health
{
"data": {
"status": "degraded",
"operational_state": {
"overall": "degraded",
"transport": { "state": "operational", "uptime_24h_pct": 100 },
"pipeline_freshness": { "state": "degraded" },
"source_completeness": { "state": "incomplete" },
"incidents": { "state": "active", "highest_severity": "error" }
}
}
}
GET /v1/status
{
"data": {
"summary": { "overall": "degraded", "findings_state": "attention" },
"operational_state": { "overall": "degraded" }
}
}Quickstart
- Run the live read-only sample request below.
- Confirm the synthetic NPI fixture and decrementing rate headers.
- For account-specific limits, create a developer account at /account/signup, accept the API Terms, and open the account dashboard.
- Create your API key (format:
fnt_…) in the dashboard. Copy it immediately — it is shown once and stored only as a hash.
curl https://api.fonteum.com/v1/npi/1234567893 \ -H "Authorization: Bearer fnt_DEMO_PUBLIC_V1"
This NPI is a deterministic synthetic onboarding fixture. The sample key is limited to 20 requests/minute and 100 requests/day per trusted source IP.
Authentication
Every metered data endpoint requires a Bearer token in the Authorization header:
Authorization: Bearer fnt_YOUR_KEY
The exact public-operation allowlist is enforced as a build gate. It covers health/status, source and bulk manifests, quality, chain, provenance, transparency, identity, billing-onboarding, and press-conversion operations. Public discovery endpoints including /health, /openapi.json, and GET /billing/checkout do not require authentication. Browser/account endpoints can instead require the developer-session cookie documented below. Every other v1 operation requires the Bearer credential. Missing keys return 401 with code missing_api_key; unknown, revoked, or expired keys return 401 with invalid_api_key.
Account billing and browser Checkout
GET /api/v1/billing/checkout describes the Checkout contract. POST /api/v1/billing/checkout creates an account-bound hosted Stripe Checkout Session for a signed-in developer account and returns { "url": "https://checkout.stripe.com/…" }. POST uses the HttpOnly __fnt_dev developer-session cookie from the account login flow; it does not accept a Bearer API key and is not a metered data endpoint.
fetch("/api/v1/billing/checkout", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "same-origin",
body: JSON.stringify({ planId: "b-builder", interval: "month" })
}).then((response) => response.json())Self-serve Checkout covers Builder, Scale, and Business API subscriptions plus the one-time $129 signed certificate. Recurring healthcare-monitoring plans are not published or accepted until their separate fulfillment exists. Checkout returns 503 unless both Stripe Checkout and signed webhook fulfillment are configured; certificate Checkout additionally requires the established signing key. Successful payment issues a working API key and shows its cleartext once on the signed return flow.
Rate limits
The public sample uses:
- 100 requests / 24h rolling window per trusted source IP
- 20 requests / minute rolling window per trusted source IP
Issued account keys use the minute/day limits configured on that key. The example below shows a 60/minute, 1,000/day account key.
Every authenticated response after key resolution (200 and 429 alike) carries:
X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 982 X-RateLimit-Reset: 1778056214 X-RateLimit-Reset-At: 2026-05-06T08:30:14.123Z X-RateLimit-Window: 1d (rolling) X-RateLimit-Limit-Minute: 60 X-RateLimit-Remaining-Minute: 42 X-RateLimit-Limit-Day: 1000 X-RateLimit-Remaining-Day: 982
A 429 response includes retry guidance when the endpoint supports it. Back off rather than retrying immediately.
Source and capture context
Provenance coverage varies by endpoint and source. Where a response schema exposes it, metadata appears at one or both of these levels:
- Per-field — supported fields can carry source, source URL, loaded or checked date, confidence (where applicable), attribution, and limitations. Any element can be null or unavailable.
- Per-response — supported endpoints can carry a
metaenvelope with request, version, source-date, methodology, limitations, documentation, or geographic-scope fields. Consult that endpoint's schema.
A source cadence is not a loaded date, and a file digest or snapshot attestation does not establish deterministic fact-to-signature linkage. Retain the source and date fields actually returned and follow the linked methodology and limitations. This context is not a risk score, endorsement, or clearance.
Sample response shape (illustrative only); actual fields and nullability are defined per endpoint:
{
"data": { "field": { "value": "...", "source": "...", "source_date": null } },
"meta": {
"request_id": "...",
"methodology_url": "...",
"limitations_url": null,
"limitations": ["Provenance fields may be unavailable for a source or field."]
}
}MCP and REST-bridge output contract
Hosted MCP 1.1.0 exposes nine read-only tools. Every MCP success and error contains JSON text plus matching structuredContent, with four top-level citation-context keys: source_file, as_of_date, snapshot_digest, and verifiable_url. The first three are nullable. A null value must remain null when one retained file, source date, or snapshot does not represent the response.
Successful responses from /api/v1/mcp/search-records, /api/v1/mcp/recheck, and /api/v1/mcp/dataset-infoexpose the same fields alongside their data and provenance. REST validation errors retain each endpoint's documented error schema; the MCP adapter normalizes those failures into the four-key tool contract.
Illustrative composite response; placeholders are not observations.
{
"data": { "...": "..." },
"provenance": { "...": "..." },
"source_file": null,
"as_of_date": null,
"snapshot_digest": null,
"verifiable_url": "https://fonteum.com/methodology"
}A populated snapshot_digest commits only to the identified retained snapshot object. It is not a signature over each returned fact and must not be substituted with the live chain-head hash.
Shared freshness envelope
Endpoints using the shared response envelope expose one source block or an array of source blocks at meta.data_freshness. last_refreshed is required but nullable: it names only the most recent proved content change in canonical snapshot evidence. When that proof is absent, invalid, conflicted, or unreadable, the field is null. Release dates, generated artifacts, coverage periods, workflow checks, and repeated observations never advance it.
source_release_dateis the publisher-issued release date represented by the response.artifact_snapshot_datedates a Fonteum or static aggregate artifact;coverage_datedates the source-data period represented.last_checked_atis the latest workflow or source check;last_observed_atis the latest snapshot-ledger observation. Neither establishes a content change.timestamp_basis: "content_change"accompanies a proved, non-nulllast_refreshed.evidence_statusexplains why the timestamp is present or withheld:proved,unavailable,invalid,conflicted, orerror.
Illustrative shape; placeholders below are not observations.
{
"meta": {
"data_freshness": [{
"source": "CMS Care Compare",
"last_refreshed": null,
"source_release_date": "<publisher release timestamp>",
"artifact_snapshot_date": "<artifact snapshot timestamp>",
"coverage_date": "<coverage timestamp>",
"last_checked_at": "<workflow check timestamp>",
"last_observed_at": "<ledger observation timestamp>",
"evidence_status": "unavailable"
}]
}
}LLM-ready export freshness headers
/api/v1/exports/{dataset}/llm-ready keeps the same axes separate in response headers. X-Last-Refreshed is deprecated and remains empty when canonical content-change evidence is unavailable; X-Source-Release-Date is empty when the exporter has no publisher release evidence; X-Artifact-Snapshot-Date carries the export artifact date when available. Artifact snapshots never populate either the refreshed or source-release header.
X-Last-Refreshed: X-Source-Release-Date: X-Artifact-Snapshot-Date: <artifact snapshot timestamp>
Platform truth endpoints
Three public, credential-less reads expose the dated platform observation, stored OpenTimestamps operational state, and append-only chain corrections:
/api/v1/platform-stats— latest stored coverage metrics; its observation date is not an upstream source-refresh date./api/v1/chain/anchors— stored anchor fields, explicitly separated from independent mainnet validation./api/v1/chain/corrections— append-only correction records and any snapshot-attestation references that exist.
The platform-stats response publishes independently usable metrics.sources_integrated counts active production registry rows,sources_with_data counts distinct snapshot IDs with any positive record count, sources_fresh counts those whose latest positive-data snapshot date is within 45 days, andsources_complete is nullbecause Fonteum publishes no platform-wide complete-source count. Completeness is evaluated against each named source's expected scope. states_covered counts distinct state values in the state-exclusions serving table and is a separate jurisdiction measure, not national coverage. Snapshot recency does not prove a content change or public display rights.
The fragment below uses the same shared platform_coverage builder as the route and includes its observation envelope. Every numeric value in that object is bound to its as_of_date; every metrics[].value is bound to the response as_of. The full response also includes groups, metrics, and _note; use the live OpenAPI document for that complete response schema.
Every platform count value shown here is as of .
{
"as_of": "2026-07-22",
"captured_at": "2026-07-22T07:30:43.695+00:00",
"from_fallback": false,
"platform_coverage": {
"as_of_date": "2026-07-22",
"captured_at": "2026-07-22T07:30:43.695+00:00",
"sources_integrated": 111,
"sources_with_data": 90,
"sources_fresh": 79,
"sources_complete": null,
"states_covered": 13,
"definitions": {
"sources_integrated": "Active rows in the production source registry; integrated does not imply loaded or fresh.",
"sources_with_data": "Distinct source snapshot IDs with at least one positive record count.",
"sources_fresh": "Distinct source snapshot IDs whose latest positive-data snapshot date is between the platform snapshot date minus 45 days and the platform snapshot date.",
"sources_complete": "No platform-wide source-completeness count is published. Completeness is source-specific and must be evaluated against the named source's expected scope.",
"states_covered": "Distinct state values represented in the state Medicaid exclusions serving table."
},
"provenance": {
"source": "Fonteum production platform-stats snapshot",
"source_url": "https://fonteum.com/api/v1/platform-stats",
"dataset_id": "public.platform_stats_snapshots",
"snapshot": "2026-07-22",
"last_checked": "2026-07-22T07:30:43.695+00:00",
"methodology": "fonteum/platform-stats/v3",
"limitations": "Integrated, data-bearing, and fresh-observation counts are separate. No aggregate source-completeness count is computed. State coverage is a separate jurisdiction measure. Snapshot data and recency do not establish public display rights or a proved content transition."
}
}
}/api/v1/sources, /api/v1/bulk/manifest.json, and /api/v1/mcp/dataset-info expose the same dated values in a nullable platform_coverage object. It is null when the snapshot is a fallback or any required query-derived coverage metric is unavailable; no compile-time, job-time, or partial count substitutes for it. captured_at dates the platform-stats observation, not an upstream source refresh. /api/v1/statusreports whether the crosswalk read succeeded as data.availability.crosswalk and uses that mapping for registry-to-snapshot status joins. Its summary.overallmatches the canonical operational headline; itssummary.findings_state retains the narrower source-report assessment.
Complete chain-link manifest
GET /api/v1/chain/manifest is a public, no-store read of the complete chain_linkssequence in ascending index order, including genesis. Each non-genesis link includes the snapshot attestation it references and that snapshot's row count. Attestation rows that are not referenced by a chain link are not chain members and are not exported.
Use links, returned_links, head_link_index, and head_link_hash for the current contract. latest_hash, latest_snapshot, returned, and snapshots remain deprecated compatibility fields derived only from linked attestations. An incomplete read or failed snapshot join returns 503 and never returns a partial manifest.
{
"complete": true,
"total_links": "<integer>",
"head_link_index": "<integer>",
"head_link_hash": "<64-character hex chain-link hash>",
"returned_links": "<integer>",
"links": [{
"link_index": 0,
"attestation_id": null,
"content_hash": "<64-character hex chain-link hash>",
"attestation": null
}]
}CMS QPP MIPS scores by NPI
GET /api/v1/qpp-mips/{npi} requires a Bearer API key and returns the loaded CMS-published final score, four nullable category scores, and participation type for each available performance year, newest first. The current serving table has no populated per-clinician payment-adjustment percentage, so the endpoint does not advertise or emit that field.
{
"data": {
"npi": "<10-digit NPI>",
"found": true,
"latest": {
"performance_year": 2023,
"final_score": "<number or null>",
"category_scores": {
"quality": "<number or null>",
"cost": "<number or null>",
"improvement_activities": "<number or null>",
"promoting_interoperability": "<number or null>"
},
"participation_type": "<string or null>"
},
"history": [{
"performance_year": 2023,
"final_score": "<number or null>",
"category_scores": {
"quality": "<number or null>",
"cost": "<number or null>",
"improvement_activities": "<number or null>",
"promoting_interoperability": "<number or null>"
},
"participation_type": "<string or null>"
}]
}
}found: false means only that Fonteum has no loaded row for that NPI. It does not establish non-participation. Re-confirm consequential use at qpp.cms.gov.
Exclusion screens fail closed on stale coverage
Every exclusion-bearing response — /exclusions/{npi}, /npi/{npi}, /npi/{npi}/risk, sanctions questions on /ask, and /procurement/screen— compares its serving exclusion tables with comparable attested source artifacts. A negative is returned only when coverage is current and reconciled. When a zero-match screen trails or cannot reconcile, the API returns a first-class coverage_stale or indeterminate state, determination: "indeterminate", nullable negative booleans, exact serving/attested dates, and Cache-Control: no-store. Direct screening endpoints return that state with 503; composite responses preserve it in their exclusion block instead of converting it to a clean result. Positive matches remain available with their coverage status. An indeterminate response is not a clearance.
{
"error": { "code": "coverage_stale", "message": "...not a clearance..." },
"data": {
"npi": "1689095580",
"excluded": null,
"coverage_status": "coverage_stale",
"determination": "indeterminate",
"coverage": {
"sources": {
"oig-leie": {
"serving_as_of": "2026-05-08",
"attested_as_of": "2026-07-01",
"attestation_snapshot_id": 906
}
}
}
}
}Subspecialty filter (§193)
/specialties/{code}/by-state and /specialties/{code}/by-county accept an optional ?subspecialty=<NUCC code> query parameter. When supplied, counts, per_100k, rank_density, and quartile are recomputed against NPPES providers whose taxonomy_codes array includes the requested code.
# Procedural Dermatology / MOHS slice of the dermatology supply data: curl "https://api.fonteum.com/v1/specialties/dermatology/by-state?subspecialty=207NS0135X" \ -H "Authorization: Bearer fnt_YOUR_KEY"
Supported codes per primary specialty are listed in the OpenAPI spec under each endpoint's description. Unknown codes return 400 invalid_subspecialty with the supported list.
Coverage caveat. Three primary specialties have multiple distinct taxonomies in the cache and produce meaningful filter results — dermatology, obgyn, pediatrics. The other 9 specialties have a single-taxonomy cache; on those, ?subspecialty= either matches the parent code or returns zero rows. The next NPPES re-ingest will widen the scope.
Underserved threshold note. The parent study's underserved threshold (per study) does not transfer to a subspecialty slice — filtered rows always emit underserved: false. Use per_100k + rank_density for relative comparisons within the slice.
When a filter is applied, meta.subspecialty_filter reports the applied code, display name, and matched record count.
Error reference
All errors follow the same envelope:
{
"error": { "code": "rate_limit_exceeded", "message": "...", "details": {...} },
"meta": { "request_id": "req_...", "api_version": "v1" }
}For GET /api/v1/npi/{npi}, an explicit zero-result response from CMS NPPES returns 404 provider_not_found. If NPPES cannot answer reliably or returns an invalid payload, the route returns 503 nppes_unavailable. That lookup is indeterminate, not a not-found result.
| Status | Code | When |
|---|---|---|
400 | invalid_npi | NPI must be 10 digits. |
400 | missing_state | Required `state` query param missing on a county-scoped endpoint. |
400 | missing_county_fips | Required `county_fips` query param missing. |
400 | state_county_mismatch | FIPS doesn't belong to the supplied state. |
400 | invalid_subspecialty | Subspecialty code not registered for the primary specialty (§193). |
401 | missing_api_key | Authorization header absent. |
401 | invalid_api_key | Key unknown, revoked, or expired. |
404 | specialty_not_found | Unknown specialty slug. |
404 | county_not_found | Unknown county FIPS. |
404 | provider_not_found | CMS NPPES returned an explicit zero-result response for the NPI. |
404 | methodology_not_found | Unknown methodology dataset slug. |
404 | state_not_found | No specialty data for this state. |
429 | rate_limit_exceeded | Per-minute or per-day quota exhausted. |
503 | coverage_stale | A zero-match exclusion screen trails its latest comparable attested source artifact. |
503 | coverage_indeterminate | Exclusion coverage cannot be reconciled; no negative determination was made. |
503 | nppes_unavailable | CMS NPPES did not answer reliably; the provider lookup is indeterminate, not not-found. |
500 | internal_error | Unhandled server error. Reference request_id in support. |
Changelog
- v1.6 source-ledger contract — 2026-07-18. The production source-ledger contract replaces the overloaded
sources_livefield with three source-lifecycle query results: active registry rows, snapshot IDs with data, and fresh positive-data observations within 45 days. Represented state Medicaid jurisdictions are a separate coverage result. Human pages,llms.txt, and AI JSON artifacts read those dated results from the database. Aggregate source completeness remains unreported and source-specific. - v1.6 accuracy contract — 2026-07-16. Added the complete linked-attestation contract for
/chain/manifestand documented/qpp-mips/{npi}. The MIPS response no longer advertises or emits an unpopulated payment-adjustment percentage. - v1.6 contract sync — 2026-07-15. Documented the shared freshness timestamp axes and LLM-ready export headers, aligned health and quality response states, and added the public attested
/as-of/{source_id}v2 contract (browsable at the point-in-time as-of view). As-of selection windows choose stored observations; they are not upstream change intervals. - v1.6 coverage contract — 2026-07-14 (historical). This release introduced the earlier live, integrated, and state-jurisdiction fields from the dated stats snapshot. Source, bulk-manifest, and dataset-info responses exposed those values through nullable
platform_coverage. The 2026-07-18 source-ledger contract above supersedes its overloaded live field. - v1.6 — 2026-07-12. Standardized protected operations on
Authorization: Bearer fnt_..., activatedfnt_DEMO_PUBLIC_V1, and moved minute/day admission pluslast_used_atstamping to one atomic Postgres limiter. Added the dated/api/v1/platform-statsobservation and/api/v1/chain/anchorsto the root OpenAPI catalog, and documented/api/v1/chain/correctionsas a separate reference. The corrections endpoint is not yet listed in the root OpenAPI document, and a stored anchor status is not independent mainnet validation. Provenance and retained-history fields remain source-specific and nullable. - v1.2 — 2026-07-12. Added the account-bound browser Checkout contract at
/billing/checkout, documented its developer-session cookie authentication separately from Bearer data-API authentication, and replaced the pilot/manual-email key flow with self-serve account signup and one-time dashboard key display. - v1.1 — 2026-07-12. Exclusion-bearing screens, NPI composite/risk responses, sanctions questions, and procurement screens now fail closed when serving coverage trails or cannot reconcile to the latest comparable attested artifact. Direct zero-match screening responses become
503withcoverage_stale/indeterminate, nullable negative booleans, coverage evidence, andCache-Control: no-store; composite responses preserve the same indeterminate state. Exclusion attestations move toexclusion-attestation/v2. Positive matches remain reportable. - Initial pilot release — 2026-05-06. Introduced the v1 REST surface, issued Bearer credentials, source and capture context, and the OpenAPI reference.
OpenAPI reference
Rendered from /api/v1/openapi.json via Redoc. Click any endpoint for request/response details and try-it samples.