2.0.0-ballot): you POST a FHIR message Bundle and get the answer in the same
exchange.
No source is connected yet. Until the first price source and insurer are connected, every
check is answered with the reason it could not be priced, never with a price made up in its
place. The answers below show exactly what comes back today. A price, once a source gives one,
is an estimate; the pharmacy confirms the price.
Service base
/v1/
is the version of the haau3 platform API contract, not a FHIR version. The FHIR release is
r4, and every response says so:
Accept: application/fhir+json, or no Accept
header at all, works fine. If you do ask for one we do not serve, or for a format other than JSON
(in Accept or _format), you get a 406 rather than a silent substitution.
Every error on this base is a FHIR OperationOutcome, including the 401 you get without a key
and a 429, so a FHIR client only ever has one error shape to parse.
Errors, limits and request ids lists the statuses every service shares.
The uppercase form
/v1/fhir/R4/... redirects to the lowercase base with a 308, which
preserves the method and body so a POST is not quietly turned into a GET.CapabilityStatement. This operation
is declared under rest.operation, beside MedList’s.
What is served
One operation, on the service base itself:GET [base]/metadata returns the CapabilityStatement, which lists this operation under
rest.operation and names CARIN’s responder statement in instantiates. The operation accepts
POST only, with Content-Type: application/fhir+json, and it needs an API key (see
Authentication). It takes no parameters: it answers synchronously, and its input
is the message Bundle sent as the body.
Every request is a Bundle of type message whose first entry is a MessageHeader. The
header’s eventCoding says which of two messages it is, from the system
http://hl7.org/fhir/us/carin-rtpbc/CodeSystem/rtpbc-event-type:
Price a medication without patient details
The request names the product and the quantity in itsClaim, masks the patient and the coverage
with a data-absent-reason of masked, and names either a pharmacy in Claim.provider or one or
more ZIP codes in its preferredPharmacyPostalCode extension.
request.json below is the synthetic example from the haau3 FHIR Implementation Guide: 30
lisinopril 5 mg tablets (RxNorm 311354) at pharmacies in ZIP code 33131.
request.json
Check a member’s cost
The member’s request carries theirPatient and Coverage, the prescription as a
MedicationRequest, its prescriber as a Practitioner, and the pharmacy as an Organization
named by its NPI or NCPDP provider id. The Coverage carries the payer’s identifier in
payor.identifier: it is how the member’s insurer is found, so a member’s request without it is
refused. For prices without patient details, send rtpbc-request-non-phi instead.
Some insurers answer only with the member’s own authorization. When this service connects to one,
your app will send the member’s authorization with each request, and it will be passed to that
insurer for that one request and kept nowhere. How it is sent will be documented here before then.
A member's request and today's answer
A member's request and today's answer
request.json
Patient comes back as it was sent, as CARIN requires.Reading the answer
The answer is aBundle of type message. Its MessageHeader answers yours: response.identifier
is your MessageHeader.id, and response.code is ok whenever the request was read. Its one
ClaimResponse carries either prices and coverage in item, or the reason there are none in
error, never both, as CARIN requires. ClaimResponse.request.identifier is your Claim’s
identifier. A member’s answer also carries your Patient, at the same fullUrl.
When no connected source can answer, ClaimResponse.outcome is error and error[0].code carries
a code from https://haau3.com/fhir/CodeSystem/pharmacy-benefits-processing-code:
An NCPDP reject code in an answer comes from the source that sent it, unchanged.
What is refused
The whole request is refused with HTTP400 and an OperationOutcome before any source is asked
when it holds:
- a query parameter: the operation takes none;
- a body that is not a
Bundleof typemessage(aParametersresource is refused by name), or a first entry that is not aMessageHeader; - an event other than the two above (issue code
not-supported); - a list over its cap (issue code
too-long): 20 entries, 5focusreferences, 10 codings on a product, 10 ZIP codes, 10 identifiers on a pharmacy, 5 payors and 20 classes on a coverage; - an element the CARIN profiles require that is missing, such as the
MessageHeader.id, theClaim’s one identifier and one item, or a quantity with no unit; - a reference that names no entry in the Bundle, or names one of the wrong type, resolved as FHIR resolves references inside a Bundle;
- a product with no NDC (11 digits, no dashes) or RxNorm code: text alone cannot be priced;
- a ZIP code that is not five digits or ZIP+4;
- in a request without patient details, a patient or coverage that is not masked, or no pharmacy and no ZIP code;
- in a member’s request, no
Coverage, or aCoveragewith nopayor.identifier; - malformed content, or a body over 1 MiB (HTTP
413).
OperationOutcome names the element by its FHIRPath in expression, and never repeats a value
you sent.
Errors
Every error is a FHIROperationOutcome.
The statuses every service shares, among them
401, 405, 406, 415, 429 and 500, are on
Errors, limits and request ids.
This operation is not offered inside a batch Bundle. A batch entry that names it is refused by
name.
Data handling
This operation is stateless. Nothing a request carries is stored, cached or logged, apart from a request ID you choose to send, and each check is a point-in-time answer: nothing from an earlier request bears on a later one. A refusal names the element, never a value. Every answer carriesCache-Control: no-store, errors included, so no cache between you and the service keeps one.
A member’s request is protected health information. The haau3
terms reserve patient data for services designated to receive
it under an executed agreement, and this operation is one of them. Send a member’s request only
under such an agreement with haau3. The platform project that serves it runs under Google Cloud’s
Business Associate Agreement.
Specification
The contract is the CARIN Consumer Real-Time Pharmacy Benefit Check, STU2 ballot, and the haau3 FHIR Implementation Guide’s Pharmacy Benefits page:- Pharmacy Benefits Processing Code, the code system
- Examples: the request without patient details and its answer, and the member’s request and its answer