A technical guide to the Payer-to-Payer API under CMS-0057-F
Subscribe to our newsletter
SubscribeThe Payer-to-Payer API looks like an export problem. Build a bulk endpoint, respond to requests from other payers, done. But it’s the only API under CMS-0057-F where you sit on both sides of the exchange. Receiving data takes a lot more engineering than sending it.
When a member enrolls with you, you must go and get their history from their previous payer, then do something with what comes back. That second half is what gets underestimated in almost every project plan I’ve seen for this API.
First, a version problem
For Payer-to-Payer, CMS lists two recommended versions of the Da Vinci Payer Data Exchange (PDex) Implementation Guide (IG): STU 2.0.0 and 2.1.0. But 2.0.0 carries the same expiry footnote that retired Plan-Net 1.1.0 and US Core 3.1.1 on January 1, 2026. So 2.1.0 is the operative version, alongside US Core 6.1.0 and CARIN Blue Button 2.1.0.
The complication: much of the detailed bulk mechanics is in the PDex continuous build, not the published 2.1.0 version, which is organized around single-member exchange. And the CI (continuous integration) build has already changed.
The member match response used to come back as Group resources wrapped in a single Parameters resource. Now they’re emitted directly as NDJSON, with the old envelope kept for backwards compatibility.
So, pin the version you’re building against and read the conformance statements rather than the narrative.
What CMS-0057-F requires
The API must make available claims and encounter data, USCDI clinical data, and prior authorization information, for data with a date of service within five years of the request. Provider remittances and enrollee cost-sharing are excluded, as are prior authorizations for drugs and those that were denied.
Operationally, you have to identify a new member’s previous or concurrent payer and request their data, respond to incoming requests within one business day, exchange with concurrent payers at least quarterly, run an opt-in consent process with plain-language material, and incorporate what you receive.
Two points on scope that are easy to get wrong:
The five-year window is a floor, not a cap
The regulation sets a minimum you must request, and the current build reads it the same way on the responding side. Neither party is barred from going further back, so if your architecture caps responses at five years, you’ve built to the wrong constraint.
Prior auth scope is narrower and wider than it looks
The regulation requires active and pending decisions and excludes drugs and denials. The current build adds any authorization whose status changed in the last 12 months, so a denial that was appealed and approved comes back into scope even though standing denials don’t. Either way, you need the status change date per authorization, not just current status.
Supporting documentation travels too: clinical notes, lab reports, imaging interpretations, signed forms, structured and unstructured. PDex links these through ‘ExplanationOfBenefit.supportingInfo’ and DocumentReference. If that material sits in a document management system that’s never spoken to your FHIR server, plan that integration early, because it will take longer than the FHIR work.
Opt-in changes the sequence
The Provider Access API uses opt-out: data flows unless the member says no. Payer-to-Payer flips this. Nothing moves until the member actively opts in, which puts consent capture at the front of the workflow rather than alongside it.
Consent here isn’t a flag in your database. It’s a FHIR Consent resource on the HRex profile, submitted to the previous payer with the match request, carrying a policy scope (all data, or non-sensitive only) and a consent period. The responder evaluates whether it can comply, given the segmentation it supports and the rules that apply to it. If it can’t, the member isn’t unmatched. They’re a separate outcome, which I’ll come to.
A few things this changes about how you build:
- Capture consent in your enrollment flow, where you have the member’s attention. A form buried in the portal three weeks later defeats the point, which is having the data available while the member is new.
- Consent gets evaluated more than once. The current build checks it per member when the export runs, not just at matching, because the member may have contacted their previous payer directly in the meantime. Expect members who match successfully and then yield no data.
- Members can opt in later, or revoke, so your consent store needs to handle state changes with timestamps.
If you’ve built a consent framework for the Provider Access API opt-out, extend it. Same components (capture, storage, audit, propagation into the API layer), just pointing the other way.
Finding the other payer
You need the identity of the previous payer, which comes from the member at enrollment, and a way to reach their endpoint. The second is less settled, and this part is in the published IG.
There’s no national endpoint directory for payers yet, so PDex defines an interim mechanism: a public git repository of signed mTLS endpoint bundles, each built from National Directory profiles, with a certificate authority signing the bundle and the public key carried in the Endpoint record.
It’s a workable stopgap, not infrastructure to depend on long term, and it tells you how early this exchange still is.
The mechanics
With consent captured and the endpoint found, the exchange itself runs on two sequential asynchronous operations, both following the FHIR R4 async pattern: POST with ‘Prefer: respond-async’, a 202 with a ‘Content-Location’ header, then poll until a completion manifest comes back.
Member matching first. You submit one entry per member with HRex patient demographics, the prior coverage details the member gave you (usually off their old insurance card), and the Consent resource.
This is where implementations often get it wrong. It isn’t one group of matched members. In the current build, each member is evaluated independently and sorted into one of three outcomes:
- Matched, always returned even when empty, because you need that group identifier for the next step
- Non-matched, where the responder couldn’t match demographically
- Consent-constrained, where the member matched but the responder can’t comply with the consent
That third one is what to design for. A member with an expired consent, or a policy scope the responder can’t honor, matched fine. They just can’t be exported. Evaluation is per member, so one bad consent doesn’t fail the batch. Your reconciliation logic needs to tie each result back to the member you submitted, which the responder supports by returning your original Patient resource, ids intact, as a contained resource.
Then the export, called against the matched group using ‘$davinci-data-export’ from the Member Attribution IG. In the current build, ‘exportType’ takes ‘hl7.fhir.us.davinci-pdex#payertopayer’. Same operation Provider Access uses, which is why the two builds share so much.
The ‘_since’ trap
This one matters most, because it looks like it solves the five-year problem, but doesn’t. And this one isn’t a versioning question: the behavior comes from the Bulk Data specification.
‘_since’ filters on ‘Resource.meta.lastUpdated’, when the resource representation last changed on the source server. Not the clinical date of service inside the resource. So, it’s right for incremental retrieval and wrong for bounding clinical history. Use it for the second and you’ll pull resources whose data is decades old, but whose representation was touched last week, while missing in-scope records that haven’t been updated recently.
For date-of-service bounding, the current build uses ‘_typeFilter’ with each resource type’s date search parameter: ‘Encounter?date=ge{date}’, ‘ExplanationOfBenefit?service-date=ge{date}’, ‘Condition?onset-date=ge{date}’, and so on.
Two catches. Some resource types have no date-of-service search parameter, so the boundary must be enforced on the server side. And ‘_typeFilter’ support is optional under the Bulk Data spec, so check the CapabilityStatement before relying on it. If it isn’t supported, you’re filtering client-side on the returned NDJSON.
The real value of ‘_since’ shows up in run-off and concurrent coverage scenarios. Since claims keep arriving at the old payer even after a member leaves, a follow-up export lets you pick up anything that landed after your initial pull.
This same pattern underlies the quarterly requirement: an initial full export, followed by incremental ones using ‘_since’ to capture what’s changed. The member filter is what makes this practical at scale: instead of re-pulling the entire group each time, you scope each export to just the members whose coverage windows call for it, running full and incremental pulls side by side as needed.
Incorporating the data
Receiving the exports is the start of the work, not the end of it. You must incorporate the data into the member’s record, and once incorporated, it must be available through your other APIs like any other data in your system.
PDex is more concrete here than people expect, and this part is in the published IG. If you’re storing the content rather than keeping the bundle intact, records get written to your FHIR server with new ids and references re-written to maintain referential integrity.
Inbound Provenance records need their target references re-written too, and that’s the step that gets missed: re-map the clinical resources, forget the Provenance targets, and you’re left with provenance pointing at ids that no longer exist.
Provenance is worth implementing properly rather than minimally. PDex profiles it on US Core and adds an extension identifying the source format, so you can tell claim-derived data from clinical-record data or manual transcription.
Two more things to plan for. Duplicates are a certainty, especially with concurrent coverage where the history overlaps with claims you already hold, so you need deduplication rather than a bulk import job. And data you incorporate becomes data you serve, which means quality problems you import become quality problems you expose.
Done well, this is also the part that pays off beyond compliance: a new member arriving with five years of history, incorporated on day one, is a different starting point for care management than an empty record.
What carries forward
The SMART Backend Services layer, the async export pipeline, and the export operation itself are shared with Provider Access. Member matching has a direct parallel there too, and the current build has aligned the two response shapes so you can reuse the delivery code.
Worth tracking alongside this: CMS-0062-P, the proposed 2026 rule, would make the recommended IGs required and bring drugs into scope for prior auth data. It also proposes cross-referencing IG versions rather than hardcoding them into the regulation, so future updates can be adopted as ONC approves them instead of requiring new rulemaking each time. It’s a proposal, so nothing changes yet, but the direction is toward recommendations becoming mandatory and version updates becoming easier to keep current.
If you’re mapping where your CMS-0057-F implementation currently stands, the CMS-0057-F Readiness Checklist covers the Payer-to-Payer requirements alongside the other four APIs.
If you’re building on Firely Server, it supports the bulk data operations, PDex-conformant profiles, and SMART Backend Services auth this API requires. Get in touch if you want to talk through your situation.