CMS Order & Referring Status Delta avatar

CMS Order & Referring Status Delta

Pricing

$10.00 / 1,000 order/referring status changeds

Go to Apify Store
CMS Order & Referring Status Delta

CMS Order & Referring Status Delta

Monitors named NPIs in the official CMS Order and Referring registry and reports only real changes: gained/lost Medicare ordering/referring eligibility, or a Part B/DME/HHA/PMD/Hospice flag change. For billing companies, DME suppliers and compliance teams. Free when nothing changes.

Pricing

$10.00 / 1,000 order/referring status changeds

Rating

0.0

(0)

Developer

Radu Furtuna

Radu Furtuna

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 days ago

Last modified

Share

Durable, informational per-NPI monitor of the official CMS Order and Referring registry — the free, public REST feed CMS publishes at https://data.cms.gov/data-api/v1/dataset/{uuid}/data. No API key, no account, no proxy, no browser. Updated every ~3.5 days (2M+ rows total).

Order and Referring lists every NPI (physician / non-physician practitioner) currently eligible under Medicare to order or refer services covered by Part B, DME, HHA (home health), PMD (power mobility devices) or Hospice. Losing this right is a hard compliance signal: a claim submitted for a patient whose ordering/referring provider has lost eligibility gets denied. Most tools that touch this dataset are one-shot lookups. This actor is a recurring watch — "tell me if any of the NPIs I track gains, loses, or changes which of these rights it has" — built for billing companies, DME suppliers, home health/hospice agencies and Medicare compliance teams.

This is a mirror-with-diff of a public government registry, not a real-time eligibility check. It is not legal advice and not a substitute for verifying a provider's current status directly with CMS before billing — the source itself updates only every ~3.5 days, so there is always a lag window.

Why

CMS already publishes the full registry for free. What it doesn't give you is a durable, per-NPI "what changed since I last looked" — you'd have to download and diff a 70+ MB CSV yourself, on every release, against every prior release. This actor keeps that diff for you: a list of watches (one NPI each), a durable memory of each NPI's flags between runs, and a bill only for NPIs that genuinely gained the right, lost it, or changed which programs it covers.

How it works

  1. Dataset UUID resolution (once per run, not per watch). CMS does not publish a stable "latest" alias for this dataset — the UUID in the API URL changes with every release (confirmed live: two real releases two days apart used two different UUIDs). Every run fetches https://data.cms.gov/data.json (~3 MB) and resolves the freshest API-format distribution titled "Order and Referring" by its modified date (ties broken toward one explicitly marked "description": "latest" — both cases were observed live on the same day).
  2. Each watch is one NPI (10-digit National Provider Identifier). One point query per watch per run: ?filter[NPI]=<npi>. Confirmed live: this is an exact string match, not substring/LIKE — a leading zero, a stray space, or a wrong digit all return a legitimate 200 [], indistinguishable at the HTTP level from "this NPI genuinely has no such record."
  3. The first run for a watch establishes a baseline: whether the NPI is currently present and, if so, its five flags (PARTB, DME, HHA, PMD, HOSPICE). Nothing is billed or delivered.
  4. Every later run compares the fresh point-query result against the stored state:
    • NPI now present, previously absent → added (billable) — the NPI gained ordering/referring eligibility (or regained it after a confirmed removal).
    • NPI present both times, flags differ → flag_changed (billable) — which program(s) it's eligible for changed.
    • NPI present both times, flags identical, only the name changed → not billable (administrative correction, not an eligibility change).
    • NPI now absent, previously present → two-strike confirmation (see below), because the source returns the identical 200 [] for "this NPI was removed" and for any transient hiccup on our end. The first consecutive absence produces an unbilled removal_candidate row (informational only, still atomically deduplicated so it is never re-delivered). Only the second consecutive accepted absence confirms removed (billable) — the NPI lost every ordering/referring right it had. If the NPI reappears before the second miss, the streak resets silently with no charge.

Input

{
"monitorId": "my-referring-watch",
"watches": [
{ "watchId": "dr-smith", "npi": "1295400745" }
],
"notifyOn": "new_alerts",
"webhookUrl": "https://example.com/webhook"
}
  • watches — 1-25 objects, each {watchId, npi}. npi is a 10-digit National Provider Identifier (^\d{10}$, exact string as CMS stores it — no normalization). A watchId is bound to its npi on first use — reusing the same watchId with a different npi later fails the run honestly (watch_config_mismatch) instead of silently hiding history under a stale index.

Output

One row per gained/changed/lost right: watchId, npi, status (added/flag_changed/removed/removal_candidate), lastName, firstName, partB/dme/hha/ pmd/hospice (current or last-known flags), previousPartB/previousDme/previousHha/previousPmd/ previousHospice, contentHash, sourceUrl. removal_candidate rows carry billed: false — they are an early, unpaid signal of a possible removal still awaiting second-run confirmation. A run that finds nothing still writes an honest run_summary row to the default dataset (never silently empty).

Billing

Pay-per-event, one named event: order-referring-status-changed — covers an NPI newly gaining a right (added), an already-known NPI's flags changing (flag_changed), and a confirmed (two-strike) loss of every right (removed). Deduplicated by NPI + a monotonically increasing change counter + a hash of the resulting state, so the same NPI can be billed again later if its state genuinely changes again, but never twice for the same transition. removal_candidate rows are never charged. The baseline run establishes history without charging. Failed/blocked runs are never charged.

Delivery guarantee: at-most-once (not exactly-once)

The right to write a row and to charge for it is granted by a single atomic primitive — one addRequest(uniqueKey) into a dedicated, named claim-journal Request Queue (<prefix>-<monitorId>-claims). Exactly one run ever wins that key. Claim requests are never deleted and never handled: the queue is a permanent journal of irreversible attempts, not a work list. The unbilled removal_candidate row uses its own claim namespace (keyed without a run id, on a durable "missing epoch" counter) so it is also delivered at most once, even though it is never charged.

What this buys you, stated honestly:

  • You will never be charged twice for the same event. That is the guarantee.
  • It is not exactly-once. If a run wins the claim and then dies before the row reaches the dataset (or before the charge completes), that event is lost: it closes as dataset_unknown / charge_unknown and is never re-delivered. We deliberately prefer losing a delivery over double-charging you.
  • Boundary of the guarantee: it holds for as long as the named claim-journal queue exists. Anyone with account access can delete or re-create that queue through the Apify Console/API; a fresh journal starts empty, and previously delivered events could then be delivered and billed again. That is an inherent limit of any durable storage, not a defect of the protocol.
  • Migration boundary: the guarantee applies from the build that introduced the claim gate onward. Older builds of this actor must not keep running against the same monitorId.
  • coverage.claimJournalSize reports the journal's size each run (best-effort; null if the queue's metadata could not be read, and the value lags a few seconds because Apify's totalRequestCount is eventually consistent). Use it to watch growth, not to make decisions.

Honest limits

  • This is not a real-time eligibility check. CMS republishes the source dataset every ~3.5 days; between releases, a provider's true eligibility could have already changed. Before denying/paying a claim on an eligibility question, verify directly with CMS (data.cms.gov) or your MAC.
  • The durable dataset is a delivery-attempt log, not a guaranteed mirror of the default dataset. Each row is written to the durable dataset first, then mirrored to the run's default dataset before billing proceeds for that row. If the durable write succeeds but the mirror fails, the item is marked dataset_unknown, billing for it is permanently blocked (fail-closed), and the row can end up an orphan in the durable dataset only. The default dataset is the canonical log of rows successfully written to this run's output (see its run_summary row) — but a default-dataset row does not by itself prove the row was billed. run_summary.eventsBilled and Apify's own billing ledger are the source of truth for confirmed payment, not the presence of a row in either dataset.
  • "Removed" needs two consecutive misses to bill, by design. The source's point query returns the identical 200 [] for "this NPI has no such record" whether that's because the right was genuinely revoked or because of some transient issue on the CMS side that we cannot distinguish from the HTTP response alone. We would rather delay a removed charge by one run interval than bill a false positive caused by a source hiccup. removal_candidate rows tell you about the first miss for free.
  • A name correction alone (no flag change) is not billed — only a change in at least one of the five eligibility flags (or the NPI appearing/disappearing entirely) is a billable signal.
  • The dataset UUID changes with every CMS release and is re-resolved every run from data.json; if CMS changes the shape of data.json itself, or removes the "Order and Referring" title, this actor fails the run honestly (source_access_limited / all_watches_failed) instead of silently returning nothing.
  • If the feed is temporarily unavailable or its response shape changes (missing field, non-Y/N flag, duplicate NPI in a point-query response, or the returned NPI not matching the one requested), the affected watch reports that honestly (source_access_limited) instead of silently accepting bad data.

See ROADMAP.md for the live-verification write-up and known source quirks.

Author: OmniCoder (https://t.me/OmniCoder)