{
 "openapi": "3.1.0",
 "info": {
  "title": "denialfacts.com free machine endpoints",
  "version": "2026-09-05",
  "x-dataset-fixity": "sha256-70fcef553523e50058a299023fafac57763341dfadc1bbd86b956b6fe1079dd3",
  "description": "Measured US health-insurance claim-denial data computed from the CMS Transparency in Coverage Public Use File (CMS Transparency in Coverage Public Use File (PY2026 release, PY2024 claims), data.healthcare.gov — US Government public domain). Every free endpoint carries a top-level `cite` (axion-cite/v1), a Link rel=canonical header, an ETag and a Last-Modified, and answers If-None-Match / If-Modified-Since with 304. Free with attribution and a link to https://denialfacts.com.",
  "contact": {
   "name": "Andrew at Axion Labs",
   "email": "hello@getaxionlabs.com",
   "url": "https://denialfacts.com/about"
  },
  "license": {
   "name": "Free to use, including commercially, with attribution and a link",
   "url": "https://denialfacts.com/llms.txt"
  }
 },
 "servers": [
  {
   "url": "https://denialfacts.com"
  }
 ],
 "x-axion-passport": "https://denialfacts.com/.well-known/agent-door.json",
 "x-axion-changes": "https://denialfacts.com/changes.json",
 "x-axion-last-modified": "2026-09-06",
 "paths": {
  "/api/answer": {
   "get": {
    "summary": "Composed answer: denial rate, external-review route and deadlines, federal appeal rights, citation, signed receipt",
    "description": "All three parameters optional and combinable. One object: the insurer and state records, the state's external-review route with deadlines and any active federal-process notice, the four ERISA claims-procedure rights with CFR citations, the national baseline, attribution and the citation object.",
    "parameters": [
     {
      "name": "insurer",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "Insurer-state record slug, e.g. blue-cross-and-blue-shield-of-alabama--al. Index: /api/insurers. Given alone, the insurer's own state resolves the external-review route."
     },
     {
      "name": "state",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "Two-letter state code (GA) or slug (georgia). Index: /api/states."
     },
     {
      "name": "reason",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "Denial-reason slug, e.g. not-medically-necessary. Index: /api/reasons."
     }
    ],
    "responses": {
     "200": {
      "description": "Always 200. A parameter that does not resolve is reported in the body's `unresolved` block with the index URL to consult, never as a 4xx.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": true,
    "x-axion-receipt": true
   }
  },
  "/api/verify-receipt": {
   "get": {
    "summary": "How to verify an /api/answer receipt (GET: the recipe and the public key; POST: a verdict)",
    "description": "POST the whole signed /api/answer body, unchanged, and get {valid, checks}: key_id_known, payload_sha256_matches, signed_message_consistent, signature_valid. Stateless; re-derives everything from the posted bytes and the published Ed25519 public key.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "The key document with the offline verification recipe.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": false
   },
   "post": {
    "summary": "Verify a signed /api/answer body",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "{valid: boolean, checks: {...}}",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "No body, not JSON, or no receipt field"
     }
    }
   }
  },
  "/.well-known/answer-key": {
   "get": {
    "summary": "The Ed25519 public key that signs /api/answer receipts, with the signed-message and policy formats",
    "parameters": [],
    "responses": {
     "200": {
      "description": "key_id, alg, public_key_spki_b64, public_key_pem, signed_message_format, policy_format, offline_recipe.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": false
   }
  },
  "/api/insurers": {
   "get": {
    "summary": "Index of every insurer-state record with its answer URL",
    "description": "CMS denial rates per insurer-state record.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Always 200. A parameter that does not resolve is reported in the body's `unresolved` block with the index URL to consult, never as a 4xx.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": true
   }
  },
  "/api/states": {
   "get": {
    "summary": "Index of every state with its external-review route and answer URL",
    "description": "External-review route (state or federal) per state, with the FERP status.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Always 200. A parameter that does not resolve is reported in the body's `unresolved` block with the index URL to consult, never as a 4xx.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": true
   }
  },
  "/api/reasons": {
   "get": {
    "summary": "Index of denial reasons with national volumes",
    "description": "Denial-reason categories with national claim counts and share of categorized denials.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Always 200. A parameter that does not resolve is reported in the body's `unresolved` block with the index URL to consult, never as a 4xx.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": true
   }
  },
  "/api/procedures": {
   "get": {
    "summary": "Per-insurer appeal procedure facts, quoted from each insurer's own published policy",
    "description": "Brand-level: which denial scenarios the member appeals versus the provider, filing windows, submission routes; every fact quoted, dated and sourced.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Always 200. A parameter that does not resolve is reported in the body's `unresolved` block with the index URL to consult, never as a 4xx.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-cite": true
   }
  },
  "/api/bulk": {
   "get": {
    "summary": "Priced door, dormant: the whole corpus in one response ($25 per pull)",
    "description": "Answers 402 with an x402 v2 PaymentRequired body, a real preview and a contact address until a payment rail opens. Every record is also free, one at a time, at the endpoints above.",
    "parameters": [],
    "responses": {
     "402": {
      "description": "Payment required (x402 v2 envelope; x-payment-status header)",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-priced": true,
    "x-axion-cite": true,
    "x-payment-info": {
     "intent": "charge",
     "method": "stripe",
     "amount": 25,
     "currency": "USD",
     "description": "The whole corpus in one response: every insurer-state record, every state route, every reason and procedure; USD 25 per pull, paid through a Stripe Payment Link named in the 402 envelope; credit rides on a key from https://denialfacts.com/api/key/checkout"
    },
    "security": [
     {
      "axionKey": []
     },
     {
      "axionOAuth": [
       "read",
       "bulk",
       "changes"
      ]
     }
    ]
   }
  },
  "/api/changes": {
   "get": {
    "summary": "Priced door, dormant: what moved since a date ($0.03 per call)",
    "description": "Answers 402 until a payment rail opens. The free /changes.json below carries the dated change list.",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "format": "date"
      },
      "description": "ISO date YYYY-MM-DD; anything else is treated as absent."
     }
    ],
    "responses": {
     "402": {
      "description": "Payment required (x402 v2 envelope; x-payment-status header)",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    },
    "x-axion-priced": true,
    "x-axion-cite": true,
    "x-payment-info": {
     "intent": "charge",
     "method": "stripe",
     "amount": 0.03,
     "currency": "USD",
     "description": "Records that changed since a date, newest first; USD 0.03 per call, paid through a Stripe Payment Link named in the 402 envelope; credit rides on a key from https://denialfacts.com/api/key/checkout"
    },
    "security": [
     {
      "axionKey": []
     },
     {
      "axionOAuth": [
       "read",
       "bulk",
       "changes"
      ]
     }
    ]
   }
  },
  "/changes.json": {
   "get": {
    "summary": "What moved, when, from where (axion-changes/1)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Newest first, max 100 items; kinds data | shape | page.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/changes.atom": {
   "get": {
    "summary": "The same change list as an Atom 1.0 feed",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Atom 1.0",
      "content": {
       "application/atom+xml": {
        "schema": {
         "type": "string"
        }
       }
      }
     }
    }
   }
  },
  "/llms.txt": {
   "get": {
    "summary": "Plain-text orientation for language models, generated from the live dataset on every request",
    "parameters": [],
    "responses": {
     "200": {
      "description": "text/plain; line 2 is the dated Checked line",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     }
    }
   }
  },
  "/.well-known/agent-door.json": {
   "get": {
    "summary": "Door passport (agent-door/v0)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Provider, capabilities, data required/retained, pricing, trust, dispute contact.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/for-agents.json": {
   "get": {
    "summary": "Machine-first orientation, one fetch",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Everything callable here, trust blocks, gateway, fair use.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  }
 },
 "x-service-info": {
  "name": "Denial Facts",
  "provider": "Axion Labs",
  "categories": [
   "data",
   "health-insurance",
   "appeals",
   "public-records"
  ],
  "contact": "hello@getaxionlabs.com",
  "auth": "https://denialfacts.com/auth.md",
  "a2a": "https://denialfacts.com/.well-known/agent-card.json"
 },
 "components": {
  "securitySchemes": {
   "axionKey": {
    "type": "http",
    "scheme": "bearer",
    "description": "An API key from https://denialfacts.com/agent/identity or https://denialfacts.com/api/key/free. Every free operation answers without one."
   },
   "axionOAuth": {
    "type": "oauth2",
    "flows": {
     "clientCredentials": {
      "tokenUrl": "https://denialfacts.com/oauth/token",
      "scopes": {
       "read": "every free endpoint (they answer without a token too)",
       "bulk": "/api/bulk, the whole corpus in one pull",
       "changes": "/api/changes, what moved since a date"
      }
     }
    }
   }
  }
 }
}