Skip to content

Reference

API reference

Every payload below is computed by the real scrubbing and denial-resolution engine against the live CMS/X12 dataset, not hand-typed JSON. Machine-readable spec at /api/openapi.

Base URL

https://denial7.com/api/v1

Auth

Every lookup endpoint (scrub, denial, ncci, mue, timely-filing) is free at the anonymous rate and needs no key to try. Send `Authorization: Bearer ld_live_...` (or `x-api-key`) to lift the throttle to your plan's quota. A `ld_test_...` key runs the real dataset, is throttled, and never bills. POST /api/v1/appeal (and the draft_appeal MCP tool) additionally requires a live key on a Pro or Scale plan: a key alone is not enough if the plan does not grant appealLetters.

Format

JSON. Success is `{ data, request_id, disclaimer }` plus an `attribution` string on free and anonymous responses; errors are `{ error: { code, message, details? }, request_id }`. Every response that consumes rate-limit budget carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. The MCP handshake calls that consume none (initialize, tools/list, ping) do not, because there is no budget to report. A metered caller (a live key on a paid plan) also gets X-Quota-Limit, X-Quota-Used and X-Quota-Remaining for the monthly allowance. All of these are listed in Access-Control-Expose-Headers, so a browser-based agent can read them.

Determinism

Every response is a projection of a cited CMS or X12 dataset plus deterministic arithmetic. There is no model in the request path, so the same query always returns the same answer. Every edit and code carries a `confidence` of "verified" or "verify" (render "verify" as Unverified, never as fact) and, where versioned, the CMS edit `quarter` it belongs to. Where the loaded dataset holds no edit for a code or pair, the response says `no_data` rather than reporting a pass: absence of data is never treated as a clean result. Procedure codes are referenced numerically only; CPT long descriptors are AMA-copyrighted and are never reproduced by this API.

Honesty semantics

A finding or lookup status of no_data means NOT CHECKED, not passed. Our NCCI PTP and MUE datasets are curated subsets of much larger CMS files; treat no_data as an instruction to check the full CMS file yourself, never as a clean result.

Success envelope

Every success is { data, request_id, disclaimer }, plus an attribution string on free and anonymous responses (paid responses omit it). This body is a real scrub of a real PTP pair, computed by the same engine the route calls, from curl -X POST https://denial7.com/api/v1/scrub \.

200 response

{
  "data": {
    "input": {
      "dateOfService": "2026-07-01",
      "payerSlug": null,
      "lines": [
        {
          "code": "80053",
          "modifiers": [],
          "units": 1
        },
        {
          "code": "80048",
          "modifiers": [],
          "units": 1
        }
      ]
    },
    "editQuarter": "2026 Q3",
    "datasetQuarter": "2026 Q3",
    "findings": [
      {
        "kind": "ptp",
        "status": "fail",
        "lineIndexes": [
          0,
          1
        ],
        "codes": [
          "80053",
          "80048"
        ],
        "summary": "80048 is bundled into 80053 and no modifier can unbundle it",
        "rule": "PTP edit with modifier indicator 0. CMS rationale: CPT Manual or CMS manual coding instruction. Indicator 0 means no modifier is permitted to bypass this edit under any circumstances.",
        "remedy": "Remove 80048 from this claim, or bill 80048 alone on a date of service where 80053 is not billed. Appending a 59 or X modifier here would be an incorrect use of the modifier.",
        "citation": {
          "source": "CMS Medicare NCCI Procedure to Procedure Edits, Practitioner Services",
          "url": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-procedure-procedure-ptp-edits",
          "quarter": "2026 Q3",
          "retrievedAt": "2026-07-18",
          "confidence": "verified"
        }
      },
      {
        "kind": "mue",
        "status": "pass",
        "lineIndexes": [
          0
        ],
        "codes": [
          "80053"
        ],
        "summary": "80053: 1 unit is within the MUE of 1",
        "rule": "MUE 1, adjudication indicator MAI 3. Date of service edit, clinical. Units above this limit are unlikely but not impossible. A higher count can be allowed on appeal when the medical record supports it.",
        "remedy": "",
        "citation": {
          "source": "CMS Medicare NCCI Medically Unlikely Edits, Practitioner Services",
          "url": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-medically-unlikely-edits",
          "quarter": "2026 Q3",
          "retrievedAt": "2026-07-18",
          "confidence": "verified"
        }
      },
      {
        "kind": "mue",
        "status": "pass",
        "lineIndexes": [
          1
        ],
        "codes": [
          "80048"
        ],
        "summary": "80048: 1 unit is within the MUE of 2",
        "rule": "MUE 2, adjudication indicator MAI 3. Date of service edit, clinical. Units above this limit are unlikely but not impossible. A higher count can be allowed on appeal when the medical record supports it.",
        "remedy": "",
        "citation": {
          "source": "CMS Medicare NCCI Medically Unlikely Edits, Practitioner Services",
          "url": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-medically-unlikely-edits",
          "quarter": "2026 Q3",
          "retrievedAt": "2026-07-18",
          "confidence": "verified"
        }
      }
    ],
    "summary": {
      "total": 3,
      "failures": 1,
      "bypassed": 0,
      "noData": 0,
      "clean": false
    },
    "coverage": {
      "ptpPairsLoaded": 40009,
      "mueCodesLoaded": 15162,
      "note": "Checked against 40009 PTP pairs and 15162 MUE values curated from the published CMS 2026 Q3 files. This is a subset of the full CMS files. Codes marked no data were not checked and may still be subject to an edit. PTP edits carry their own effective and deletion dates, so a date of service in an earlier quarter is checked against the edit that was genuinely in force then. The MUE table carries no dates, so it is only applied to a date of service inside the quarter we hold."
    }
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}

The citation shape

How to read a source and confidence

Every PTP pair, MUE limit, CARC, RARC and payer field carries the citation it came from, in this shape. There is no "reported" middle tier: a value is either verified against the cited page or it is not, and an unverified value must render as Unverified, never as fact.

keytypemeaning
sourcestringHuman label for the source, e.g. "CMS NCCI PTP Edits".
urlstringThe page the value was read from.
quarterstring (optional)The CMS edit quarter this value belongs to, when the source is versioned.
confidence"verified" | "verify""verified" was read directly off the cited page. "verify" renders as Unverified in every client; never presented as fact.

Errors

Structured, never silent

Every non-2xx response is JSON in the { error: { code, message }, request_id } envelope. The code is stable; build on it, not on the message text.

codestatusmeaning
invalid_request400A required parameter is missing or malformed: no carc, no code, an unparseable dateOfService, an empty lines array, or a pair lookup without a date. The message names the parameter and what it wanted.
invalid_json400The POST body is not valid JSON. Reported separately from invalid_request so a caller with a broken serialiser is not told its field names are wrong.
unauthorized401The key you sent is not valid or has been revoked. Only ever returned when you supply a key: a keyless call is allowed at the anonymous rate, never rejected as unauthorized.
upgrade_required402POST /api/v1/appeal (and the draft_appeal MCP tool) called anonymously or on the free plan. details carries upgrade_url and required_plan. You get this refusal rather than a fabricated or partial letter.
not_found404There is no endpoint at the path you called. details.endpoints lists the ones that exist. NOTE: this is about PATHS only. A CARC, RARC, code or payer we do not hold is never a 404: it returns 200 with found:false or status no_data, because a gap in our dataset is our coverage gap to report, not a claim that your code is invalid.
payload_too_large413The POST body exceeds the byte ceiling. The message names the exact limit. Split the claim across multiple calls.
rate_limited429You exceeded the anonymous rate, the test-key throttle, your plan's per-minute burst, or your plan's monthly allowance. Retry-After tells you how long to wait.
internal500An unexpected server error. Safe to retry; quote the request_id if it persists.

402 upgrade_required, POST /api/v1/appeal without a Pro or Scale plan

{
  "error": {
    "code": "upgrade_required",
    "message": "Appeal letter generation is a Pro capability. Anonymous calls and the free plan can scrub a claim and look up denial codes, NCCI edits, MUE limits and timely filing deadlines, but generating the appeal letter artifact needs a Pro or Scale plan.",
    "details": {
      "upgrade_url": "https://denial7.com/pricing",
      "required_plan": "pro"
    }
  },
  "request_id": "req_2f9c41a7b0e84d15"
}

200, a CARC we do not hold. Not a 404

{
  "data": {
    "found": false,
    "group": null,
    "carc": null,
    "rarc": [],
    "unknownRarc": [],
    "correctiveActions": [],
    "appeal": {
      "worthiness": "unknown",
      "note": "We do not hold this code, so we cannot judge whether an appeal is worthwhile.",
      "payer": null,
      "deadlineDays": null
    },
    "note": "We do not hold CARC 999 in our dataset. The full X12 Claim Adjustment Reason Code list is larger than the set we have verified, so this is a gap in our coverage rather than an invalid code."
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}

The second block is the one to build against. A CARC, RARC, procedure code or payer slug that is outside our dataset is not an error and never returns 404: you get a 200 with found: false (or status: "no_data") and a note naming the gap. A gap in our coverage is ours to report, not grounds for telling you your code is invalid. not_found is reserved for a path that does not exist under /api/v1, and its details.endpoints lists the paths that do.

Rate limits & quota

By key type

Every endpoint works with no key at the anonymous rate. Send a key to lift the throttle to your plan's quota. A free test key runs the real engine and never bills; a live key needs Pro or Scale.

TierBurstVolume
Anonymous (no key)4/min20/day per IP. Enough to run a call out of these docs, not enough to build on.
Test key (free on every plan)10/min200/day against the real engine and datasets. Never bills.
Pro (live key)60/min1,000 calls/mo. A hard ceiling, not a meter: past it the API returns rate_limited rather than billing you.
Scale (live key)300/min10,000 calls/mo. A hard ceiling, not a meter: past it the API returns rate_limited rather than billing you.

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, so an agent can back off before a 429. Full plans at /pricing or the machine-readable /api/v1/pricing.

Endpoints

Every route

POST

/api/v1/scrub

Key optional

Scrub a claim against the NCCI procedure-to-procedure (PTP) edits and medically unlikely edits (MUE) in force on the date of service. Deterministic: no model, so identical input always returns an identical verdict. Every finding is one of four statuses: pass (checked and clean), fail (an edit fires), bypassed (an edit fires but a modifier already on the line legitimately resolves it), or no_data (we hold no edit for this code or pair). no_data is NOT a pass: CMS may still deny it under an edit outside our loaded subset. The response echoes editQuarter (the CMS quarter the verdict was computed against) and coverage (how many PTP pairs and MUE codes are loaded), so you always know what was actually checked. Supports an `Idempotency-Key` header for keyed callers: replaying the same key returns the original result rather than a second billable call.

Can return: unauthorized (401), internal (500), invalid_json (400), payload_too_large (413), invalid_request (400), rate_limited (429). Accepts an Idempotency-Key request header: a keyed caller replaying the same key gets the original result back rather than a second billable call.

ParamInRequiredDescription
dateOfServicebodyyesISO yyyy-mm-dd. Drives which CMS edit quarter applies. Required, but note this endpoint reports a missing or unparseable date as a finding rather than a 400: you get 200 with editQuarter "unknown", a kind "input" finding at status fail, and summary.clean false. That is deliberate, so the answer is citable rather than a bare error, but it means you must read summary.clean and not treat HTTP 200 as a clean claim.
payerSlugbodynoOptional payer slug for context; does not change the PTP/MUE verdict.
linesbodyyesNon-empty array of { code, modifiers: string[], units }, at most 500 lines. code is a CPT/HCPCS code referenced numerically only.

request

curl -X POST https://denial7.com/api/v1/scrub \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: scrub-demo-1" \
  -d '{"dateOfService":"2026-07-01","lines":[{"code":"80053","modifiers":[],"units":1},{"code":"80048","modifiers":[],"units":1}]}'

response 200

{
  "data": {
    "input": {
      "dateOfService": "2026-07-01",
      "payerSlug": null,
      "lines": [
        {
          "code": "80053",
          "modifiers": [],
          "units": 1
        },
        {
          "code": "80048",
          "modifiers": [],
          "units": 1
        }
      ]
    },
    "editQuarter": "2026 Q3",
    "datasetQuarter": "2026 Q3",
    "findings": [
      {
        "kind": "ptp",
        "status": "fail",
        "lineIndexes": [
          0,
          1
        ],
        "codes": [
          "80053",
          "80048"
        ],
        "summary": "80048 is bundled into 80053 and no modifier can unbundle it",
        "rule": "PTP edit with modifier indicator 0. CMS rationale: CPT Manual or CMS manual coding instruction. Indicator 0 means no modifier is permitted to bypass this edit under any circumstances.",
        "remedy": "Remove 80048 from this claim, or bill 80048 alone on a date of service where 80053 is not billed. Appending a 59 or X modifier here would be an incorrect use of the modifier.",
        "citation": {
          "source": "CMS Medicare NCCI Procedure to Procedure Edits, Practitioner Services",
          "url": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-procedure-procedure-ptp-edits",
          "quarter": "2026 Q3",
          "retrievedAt": "2026-07-18",
          "confidence": "verified"
        }
      },
      {
        "kind": "mue",
        "status": "pass",
        "lineIndexes": [
          0
        ],
        "codes": [
          "80053"
        ],
        "summary": "80053: 1 unit is within the MUE of 1",
        "rule": "MUE 1, adjudication indicator MAI 3. Date of service edit, clinical. Units above this limit are unlikely but not impossible. A higher count can be allowed on appeal when the medical record supports it.",
        "remedy": "",
        "citation": {
          "source": "CMS Medicare NCCI Medically Unlikely Edits, Practitioner Services",
          "url": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-medically-unlikely-edits",
          "quarter": "2026 Q3",
          "retrievedAt": "2026-07-18",
          "confidence": "verified"
        }
      },
      {
        "kind": "mue",
        "status": "pass",
        "lineIndexes": [
          1
        ],
        "codes": [
          "80048"
        ],
        "summary": "80048: 1 unit is within the MUE of 2",
        "rule": "MUE 2, adjudication indicator MAI 3. Date of service edit, clinical. Units above this limit are unlikely but not impossible. A higher count can be allowed on appeal when the medical record supports it.",
        "remedy": "",
        "citation": {
          "source": "CMS Medicare NCCI Medically Unlikely Edits, Practitioner Services",
          "url": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-medically-unlikely-edits",
          "quarter": "2026 Q3",
          "retrievedAt": "2026-07-18",
          "confidence": "verified"
        }
      }
    ],
    "summary": {
      "total": 3,
      "failures": 1,
      "bypassed": 0,
      "noData": 0,
      "clean": false
    },
    "coverage": {
      "ptpPairsLoaded": 40009,
      "mueCodesLoaded": 15162,
      "note": "Checked against 40009 PTP pairs and 15162 MUE values curated from the published CMS 2026 Q3 files. This is a subset of the full CMS files. Codes marked no data were not checked and may still be subject to an edit. PTP edits carry their own effective and deletion dates, so a date of service in an earlier quarter is checked against the edit that was genuinely in force then. The MUE table carries no dates, so it is only applied to a date of service inside the quarter we hold."
    }
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}
GET

/api/v1/denial

Key optional

Explain a CARC (Claim Adjustment Reason Code) and any RARCs (Remittance Advice Remark Codes) from a remittance: what the denial means, ranked corrective actions, and whether an appeal is worth filing. found:false means we do not hold that CARC in our dataset (X12 publishes far more codes than we curate); unknownRarc reports, rather than silently drops, any RARC you passed that we do not hold. Passing payer additionally attaches that payer's appeal deadline where we hold one.

Can return: unauthorized (401), internal (500), invalid_request (400), rate_limited (429).

ParamInRequiredDescription
carcqueryyesCARC code, with or without a group prefix, e.g. "CO-45" or "45".
rarcquerynoOptional RARC code(s). Comma-separated, or repeat the parameter.
payerquerynoOptional payer slug, to attach a timely-filing appeal deadline.

request

curl "https://denial7.com/api/v1/denial?carc=CO-45&rarc=N290&payer=medicare"

response 200

{
  "data": {
    "found": true,
    "group": {
      "code": "CO",
      "meaning": "Contractual Obligation. The provider is responsible and the amount cannot be billed to the patient."
    },
    "carc": {
      "code": "45",
      "commonGroups": [
        "CO"
      ],
      "title": "Charge exceeds fee schedule/maximum allowable or contracted/legislated fee arrangement.",
      "plainMeaning": "The payer is telling you the billed charge is higher than the amount their fee schedule or contract allows for this service. The difference between what you billed and what the payer allows becomes a contractual write off, not something you can bill the patient for when an in network contract is in place.",
      "whyItFires": [
        "Billed charge exceeds the payer's fee schedule or contracted rate for the CPT/HCPCS code",
        "No modifier or documentation was included that could justify an exception to the fee schedule",
        "Fee schedule updated on the payer side (annual CMS or payer update) and the practice's charge master was not"
      ],
      "correctiveActions": [
        {
          "step": "Verify the contract rate",
          "detail": "Pull the current fee schedule or contract rate sheet for this payer and CPT code and confirm the allowed amount matches what was paid."
        },
        {
          "step": "Write off per contract",
          "detail": "If the allowed amount is correct per contract, adjust off the difference. This is a standard contractual adjustment, not an error."
        },
        {
          "step": "Check for a fee schedule update lag",
          "detail": "If the payer recently updated its fee schedule, confirm the correct effective date was applied to this date of service."
        }
      ],
      "appealWorthiness": "low",
      "appealNote": "Appeal only if you can show the payer used the wrong fee schedule, wrong contract year, or the code is not actually subject to that schedule. Otherwise this is a routine contractual write off and not appealable.",
      "relatedRarc": [],
      "sourceUrl": "https://x12.org/codes/claim-adjustment-reason-codes",
      "confidence": "verified"
    },
    "rarc": [
      {
        "code": "N290",
        "type": "informational",
        "title": "Missing/incomplete/invalid rendering provider primary identifier",
        "plainMeaning": "The claim is missing the NPI of the provider who actually performed the service, or the rendering provider NPI submitted does not match an enrolled provider.",
        "correctiveActions": [
          {
            "step": "Verify the rendering provider's NPI",
            "detail": "Confirm the individual rendering provider's NPI is correctly entered in the rendering provider loop, not just the billing/group NPI."
          },
          {
            "step": "Confirm the rendering provider is enrolled and credentialed",
            "detail": "Check that the rendering provider is credentialed with the payer and linked correctly to the billing group before resubmitting."
          }
        ],
        "relatedCarc": [
          "16"
        ],
        "sourceUrl": "https://docs.claim.md/docs/remittance-advice-remarks-codes",
        "confidence": "verify"
      }
    ],
    "unknownRarc": [],
    "correctiveActions": [
      {
        "step": "Verify the contract rate",
        "detail": "Pull the current fee schedule or contract rate sheet for this payer and CPT code and confirm the allowed amount matches what was paid."
      },
      {
        "step": "Write off per contract",
        "detail": "If the allowed amount is correct per contract, adjust off the difference. This is a standard contractual adjustment, not an error."
      },
      {
        "step": "Check for a fee schedule update lag",
        "detail": "If the payer recently updated its fee schedule, confirm the correct effective date was applied to this date of service."
      },
      {
        "step": "Verify the rendering provider's NPI",
        "detail": "Confirm the individual rendering provider's NPI is correctly entered in the rendering provider loop, not just the billing/group NPI."
      },
      {
        "step": "Confirm the rendering provider is enrolled and credentialed",
        "detail": "Check that the rendering provider is credentialed with the payer and linked correctly to the billing group before resubmitting."
      }
    ],
    "appeal": {
      "worthiness": "low",
      "note": "Appeal only if you can show the payer used the wrong fee schedule, wrong contract year, or the code is not actually subject to that schedule. Otherwise this is a routine contractual write off and not appealable.",
      "payer": {
        "payer": "Medicare (Original / Part B)",
        "slug": "medicare",
        "initialClaimLimitDays": 365,
        "limitText": "12 months (1 calendar year) from the date of service",
        "clockStartsFrom": "date of service",
        "appealLimitDays": 120,
        "notes": "Set by federal regulation at 42 CFR 424.44, not by contract, so this figure does not vary by Medicare Administrative Contractor. Claims denied for untimely filing carry no appeal rights for the timeliness issue itself; the 120-day figure is the standard redetermination (first-level appeal) deadline for a substantive denial, measured from the date of the initial determination.",
        "sourceUrl": "https://www.medicare.gov/providers-services/claims-appeals-complaints/claims",
        "confidence": "verified"
      },
      "deadlineDays": 120
    },
    "note": ""
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}
GET

/api/v1/ncci

Key optional

Look up NCCI procedure-to-procedure (PTP) edits. Two modes: pass column1 and column2 (either order) with dateOfService to check whether a specific pair bundles on that date, or pass code alone to list every pair in the dataset involving that code. In pair mode, status is no_data (we hold no edit for this pair; not confirmation CMS has none), not_applicable (we hold the edit but it does not govern this date, or its modifierIndicator is "9"), or applies. modifierIndicator "0" means no modifier may bypass the edit; "1" means a modifier may bypass it when the services were genuinely distinct.

Can return: unauthorized (401), internal (500), invalid_request (400), rate_limited (429).

ParamInRequiredDescription
column1querynoA CPT/HCPCS code. Pair mode: use with column2 and dateOfService.
column2querynoThe other code in the pair.
dateOfServicequerynoISO yyyy-mm-dd. Required in pair mode; NCCI edits are versioned quarterly.
codequerynoList mode: a single code. Returns every pair in the dataset involving it, in either column.

request

curl "https://denial7.com/api/v1/ncci?column1=80053&column2=80048&dateOfService=2026-07-01"

response 200

{
  "data": {
    "column1": "80053",
    "column2": "80048",
    "dateOfService": "2026-07-01",
    "editQuarter": "2026 Q3",
    "found": true,
    "appliesOnDate": true,
    "status": "applies",
    "edit": {
      "column1": "80053",
      "column2": "80048",
      "modifierIndicator": "0",
      "effectiveDate": "2000-07-01",
      "deletionDate": null,
      "rationale": "CPT Manual or CMS manual coding instruction",
      "note": "",
      "sourceUrl": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-procedure-procedure-ptp-edits",
      "confidence": "verified"
    }
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}
GET

/api/v1/mue

Key optional

Look up the medically unlikely edit (MUE) unit limit for a single CPT/HCPCS code. status is found or no_data; no_data means we hold no MUE value for this code, not that CMS publishes none. When found, mai (the adjudication indicator: "1" line edit, "2" date-of-service absolute, "3" date-of-service clinical) governs what happens above the limit, explained in maiMeaning.

Can return: unauthorized (401), internal (500), invalid_request (400), rate_limited (429).

ParamInRequiredDescription
codequeryyesCPT/HCPCS code, e.g. 36415.

request

curl "https://denial7.com/api/v1/mue?code=36415"

response 200

{
  "data": {
    "code": "36415",
    "status": "found",
    "limit": {
      "code": "36415",
      "mueValue": 2,
      "mai": "3",
      "maiMeaning": "Date of service edit, clinical. Units above this limit are unlikely but not impossible. A higher count can be allowed on appeal when the medical record supports it.",
      "serviceType": "Practitioner",
      "note": "CMS published rationale for this limit: CMS Policy.",
      "sourceUrl": "https://www.cms.gov/medicare/coding-billing/national-correct-coding-initiative-ncci-edits/medicare-ncci-medically-unlikely-edits",
      "confidence": "verified"
    }
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}
POST

/api/v1/appeal

Pro or Scale plan

Generate an appeal letter for a denial, assembled deterministically from cited facts. REQUIRES A PRO OR SCALE PLAN: an anonymous or free-plan call returns an upgrade_required error naming the pricing page, never a fabricated or partial letter. Any fact only the practice holds (provider name, claim number, date of service, procedure codes, signature) that is not supplied is rendered as an explicit [TO BE COMPLETED BY PRACTICE] placeholder and listed in placeholders. grounded is true only when we hold the CARC supplied and could argue it specifically. Supports an `Idempotency-Key` header, the same as /scrub.

Can return: unauthorized (401), internal (500), invalid_json (400), payload_too_large (413), invalid_request (400), upgrade_required (402), rate_limited (429). Accepts an Idempotency-Key request header: a keyed caller replaying the same key gets the original result back rather than a second billable call.

ParamInRequiredDescription
carcbodyyesCARC code from the remittance, e.g. "CO-45" or "45".
rarcbodynoOptional array of RARC codes on the same remittance line.
payerSlugbodynoOptional payer slug, to cite that payer's appeal policy and window.
providerNamebodynoOptional. Left as a placeholder if omitted.
claimNumberbodynoOptional. Left as a placeholder if omitted.
dateOfServicebodynoOptional. Left as a placeholder if omitted.
codesbodynoOptional array of procedure codes at issue, numeric reference only.
practiceNotebodynoOptional free-text detail from the practice, appended to the argument section.

request

curl -X POST https://denial7.com/api/v1/appeal \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DENIAL7_API_KEY" \
  -H "Idempotency-Key: appeal-demo-1" \
  -d '{"carc":"CO-45","payerSlug":"aetna","claimNumber":"CLM-10293"}'

response 200

{
  "data": {
    "subject": "Request for reconsideration - claim CLM-10293 - CO-45",
    "body": "2026-08-11\n\nAetna\nAttn: Claims Review / Appeals Department\n\nRe: Request for reconsideration\nClaim number: CLM-10293\nDate of service: [TO BE COMPLETED BY PRACTICE]\nProcedure code(s) at issue: [TO BE COMPLETED BY PRACTICE]\nProvider: [TO BE COMPLETED BY PRACTICE]\n\nTo whom it may concern,\n\nWe are writing to request reconsideration of the adjustment applied to the claim referenced above.\n\nThe remittance reports CO-45: Charge exceeds fee schedule/maximum allowable or contracted/legislated fee arrangement..\n\nThe payer is telling you the billed charge is higher than the amount their fee schedule or contract allows for this service. The difference between what you billed and what the payer allows becomes a contractual write off, not something you can bill the patient for when an in network contract is in place.\n\nBasis for reconsideration:\n1. Verify the contract rate. Pull the current fee schedule or contract rate sheet for this payer and CPT code and confirm the allowed amount matches what was paid.\n2. Write off per contract. If the allowed amount is correct per contract, adjust off the difference. This is a standard contractual adjustment, not an error.\n3. Check for a fee schedule update lag. If the payer recently updated its fee schedule, confirm the correct effective date was applied to this date of service.\n\nThis request is submitted within the appeal window stated in our participation agreement.\n\nWe ask that the claim be reprocessed. Supporting documentation is enclosed. Please contact the billing office at the number on file if any further information would assist the review.\n\nSincerely,\n\n[TO BE COMPLETED BY PRACTICE]\n[TO BE COMPLETED BY PRACTICE]",
    "citations": [
      {
        "source": "X12 Claim Adjustment Reason Codes",
        "url": "https://x12.org/codes/claim-adjustment-reason-codes",
        "confidence": "verified"
      },
      {
        "source": "Aetna timely filing and appeal policy",
        "url": "https://muni.health/blog/aetna-timely-filing-limits-2026",
        "confidence": "verify"
      }
    ],
    "placeholders": [
      "Provider or practice name",
      "Date of service",
      "Procedure codes at issue",
      "Signature, name and title of the person sending the letter"
    ],
    "grounded": true
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}
GET

/api/v1/timely-filing

Key optional

Days remaining to file an initial claim (or, if past, how far over) for a payer given a date of service. daysRemaining and expired are null when we hold no published timely filing limit for that payer, which is common since many limits are contract-specific; check note before treating the result as a deadline.

Can return: unauthorized (401), internal (500), invalid_request (400), rate_limited (429).

ParamInRequiredDescription
payerqueryyesPayer slug, e.g. aetna.
dateOfServicequeryyesISO yyyy-mm-dd.

request

curl "https://denial7.com/api/v1/timely-filing?payer=aetna&dateOfService=2026-01-15"

response 200

{
  "data": {
    "payerSlug": "aetna",
    "dateOfService": "2026-01-15",
    "checkedAt": "2026-08-11",
    "payer": {
      "payer": "Aetna",
      "slug": "aetna",
      "initialClaimLimitDays": 90,
      "limitText": "90 days from date of service for participating/in-network commercial providers; non-participating providers commonly have up to 12 months, per Aetna's published guidance",
      "clockStartsFrom": "date of service",
      "appealLimitDays": null,
      "notes": "The published default varies further by product (commercial, Medicare Advantage, Aetna Better Health Medicaid plans) and by the specific network contract. This entry reflects secondary-source reporting on Aetna's provider guidance rather than a directly confirmed page from aetna.com; verify against the current provider manual for the member's specific plan before acting.",
      "sourceUrl": "https://muni.health/blog/aetna-timely-filing-limits-2026",
      "confidence": "verify"
    },
    "daysElapsed": 208,
    "daysRemaining": -118,
    "expired": true,
    "note": ""
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}
GET

/api/v1/pricing

Key optional

Machine-readable pricing: every plan id, its monthly price (read live from lib/plans.ts, never hardcoded), what it includes, the included monthly API-call allowance (a hard ceiling, not a meter), rate limits, and whether it grants appeal-letter generation. Lets an agent self-select a plan without a human reading the pricing page. Free, keyless, not rate-limited.

Can return: unauthorized (401), internal (500).

request

curl https://denial7.com/api/v1/pricing

response 200

{
  "data": {
    "currency": "usd",
    "unit": "Metered by billable call once you send a live key on a paid plan. Anonymous and test-key calls never bill; they are rate-limited instead.",
    "determinism": "Every response is a projection of a cited CMS or X12 dataset plus deterministic arithmetic. There is no model in the request path, so the same query always returns the same answer. Every edit and code carries a `confidence` of \"verified\" or \"verify\" (render \"verify\" as Unverified, never as fact) and, where versioned, the CMS edit `quarter` it belongs to. Where the loaded dataset holds no edit for a code or pair, the response says `no_data` rather than reporting a pass: absence of data is never treated as a clean result. Procedure codes are referenced numerically only; CPT long descriptors are AMA-copyrighted and are never reproduced by this API.",
    "anonymous": {
      "price_usd": 0,
      "rate_limit_per_minute": 4,
      "rate_limit_per_day": 20,
      "api_access": false,
      "appeal_letters": false,
      "note": "No key needed. Every lookup endpoint (scrub, denial, ncci, mue, timely-filing) works at this throttled rate. POST /api/v1/appeal always requires a Pro or Scale plan, regardless of throttle."
    },
    "test_key": {
      "rate_limit_per_minute": 10,
      "rate_limit_per_day": 200,
      "bills": false,
      "appeal_letters": false,
      "note": "A ld_test_ key (see /api/v1 auth) never bills and never unlocks appeal letters; it only raises the anonymous throttle."
    },
    "plans": [
      {
        "id": "free",
        "name": "Free",
        "price_usd_per_month": 0,
        "cadence": "free forever",
        "tagline": "Scrub a claim, look up any denial code. No card, no signup.",
        "included_api_calls_per_month": 0,
        "rate_limit_per_minute": 0,
        "batch_claims_per_run": 0,
        "saved_claims": 0,
        "seats": 1,
        "api_access": false,
        "claim_history": false,
        "batch_scrub": false,
        "appeal_letters": false,
        "denial_analytics": false,
        "priority_support": false,
        "features": [
          "Single-claim scrubber, runs in your browser so claim data is never transmitted",
          "Every CARC and RARC denial page, with cited corrective actions",
          "NCCI PTP and MUE verdicts with the CMS citation and edit quarter",
          "Test API key for developers (throttled, never bills)",
          "Public API and MCP at the anonymous rate"
        ]
      },
      {
        "id": "pro",
        "name": "Pro",
        "price_usd_per_month": 49,
        "cadence": "per month",
        "tagline": "For the biller or practice working denials every week.",
        "included_api_calls_per_month": 1000,
        "rate_limit_per_minute": 60,
        "batch_claims_per_run": 250,
        "saved_claims": "unlimited",
        "seats": 1,
        "api_access": true,
        "claim_history": true,
        "batch_scrub": true,
        "appeal_letters": true,
        "denial_analytics": true,
        "priority_support": false,
        "features": [
          "Batch scrubbing, up to 250 claims per run",
          "Saved claim history with the verdict and the CMS quarter it was checked against",
          "Appeal letter generation and download, with the citations that justify it",
          "Denial analytics by payer across your saved claims",
          "Claim scrubbing API, 1,000 calls/mo included",
          "Hosted MCP server at your plan's burst rate instead of the anonymous rate",
          "Inspectable request log"
        ]
      },
      {
        "id": "scale",
        "name": "Scale",
        "price_usd_per_month": 149,
        "cadence": "per month",
        "tagline": "For billing companies and products built on the API.",
        "included_api_calls_per_month": 10000,
        "rate_limit_per_minute": 300,
        "batch_claims_per_run": 2000,
        "saved_claims": "unlimited",
        "seats": 1,
        "api_access": true,
        "claim_history": true,
        "batch_scrub": true,
        "appeal_letters": true,
        "denial_analytics": true,
        "priority_support": true,
        "features": [
          "Everything in Pro",
          "10,000 API calls/mo",
          "300 requests/minute burst",
          "Batch scrubbing up to 2,000 claims per run",
          "Priority support"
        ]
      }
    ],
    "checkout": {
      "note": "There is no machine-callable checkout API: a signed-in human starts Stripe Checkout from the billing page. An agent choosing a plan on a user's behalf should direct them to upgrade_url.",
      "upgrade_url": "https://denial7.com/pricing"
    }
  },
  "request_id": "req_2f9c41a7b0e84d15",
  "disclaimer": "Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.",
  "attribution": "Data from Denial7 (https://denial7.com): CMS NCCI/MUE edits and X12 CARC/RARC codes, cited by source and confidence. Free responses require this attribution."
}

Denial7 provides billing and administrative guidance based on published CMS and X12 sources. It is not medical advice, not a coverage determination, and not a guarantee of payment. NCCI and MUE edits are republished quarterly and payer policies vary by contract. Always confirm against the payer's own current policy before submitting or appealing.

Developer overviewMCP server

Start with no key, then raise the throttle

Every route answers anonymously at the free rate. A key lifts it to your plan's quota and gives you the inspectable request log.