/sandbox in front, answered with synthetic data that always gives the same answer, so you can
build and test against it. It takes a test key, haau3_sk_test_…, which you make on the API keys
page by choosing Test: a test key works only here, and a live key does not work here (see
test and live keys).
Its first service is the
CARIN Consumer Real-Time Pharmacy Benefit Check
(STU2 ballot, 2.0.0-ballot), answered by Example Health Plan, a test insurer, as a payer
would, so a client written for a payer runs against it with only its base URL changed. It answers
for a small cast of test members, and each medication in its formulary table always gets the same
answer, so every outcome can be rehearsed on demand: a price with a copay, an alternative drug, not
covered, prior authorization, a quantity limit and two errors.
Every organization can call it on every plan. Each request counts toward your plan like any other
request, and your Usage page shows it as Sandbox.
The open-source SDKs for TypeScript, Python and Go call every operation of this service,
and each operation in the API reference has a sample in all three and in cURL.
Service base
https://api.haau3.com/v1/fhir/r4; the Sandbox’s is the same with
/sandbox in front. It is a FHIR R4 server with its own CapabilityStatement, which says what the
Sandbox serves. It needs a test key (see Authentication), and
a live key gets 403 live-key-in-sandbox. It answers application/fhir+json; fhirVersion=4.0, and every
error on it is a FHIR OperationOutcome, the 401 without a key included.
What is served
metadata returns the Sandbox’s CapabilityStatement, which names CARIN’s responder statement in
instantiates and the member’s request (rtpbc-request) as the one message it receives.
$process-message takes a member’s request and answers it in the same exchange, at the same path
as the platform’s Pharmacy Benefits. It accepts POST only, with
Content-Type: application/fhir+json, and takes no parameters.
Test members
Send a test member’s member ID in any of the places CARIN carries one:
Coverage.subscriberId;- the Coverage’s
rxidclass, the member ID on a pharmacy benefit card (http://terminology.hl7.org/CodeSystem/coverage-class); - a
Patient.identifierwhosesystemishttps://example-health-plan.test/member-id.
SANDBOX-EHP, and the examples name the payer by it, in a
Coverage.payor.identifier whose type is payerid from
http://hl7.org/fhir/us/carin-bb/CodeSystem/C4BBIdentifierType, as the platform’s Pharmacy
Benefits finds a member’s insurer. Example Health Plan is the Sandbox’s only test insurer, so it
answers every member’s request, whatever payer it names.
Formulary table
A medication is matched by its RxNorm code or its NDC, in the Claim’s
item.productOrService.coding. The codes and displays are from RxNorm; the two drugs of CARIN’s
own examples, Prozac and Zepatier, keep CARIN’s amounts. The amounts are fixed whatever the quantity
you ask about.
What the test data does not cover
Example Health Plan lets you rehearse the shape of a member’s answer and each outcome above. It is not a model of a real plan, and it does not have:- a deductible, coinsurance tiers, or a running total of what a member has paid this year;
- step therapy, or any restriction beyond the ones in the table;
- prices that differ by pharmacy, network or mail order: the pharmacy you name changes nothing;
- amounts that follow the quantity or the days’ supply;
- an answer to the request without patient details, which price sources give;
- a member’s own sign-in: you send your platform API key, where a payer takes the member’s access token.
Send a request
The member’s request is the same message the Pharmacy Benefits page documents: aBundle of type message whose first entry is a MessageHeader with the event
rtpbc-request, then the Claim, the member’s Patient and Coverage, the prescription
(MedicationRequest), its prescriber and the pharmacy. That page’s member example answers here as
it is, since its member is Mei Lin.
Mei Lin's request for lisinopril, and the answer
Mei Lin's request for lisinopril, and the answer
The request, The answer:
request.json:request.json
answer.json
MedicationRequest, to another row of the tables above.
Reading the answer
The answer is aBundle of type message: a MessageHeader answering yours, one ClaimResponse,
and your Patient as you sent it, with a test member’s labelled HTEST
(http://terminology.hl7.org/CodeSystem/v3-ActReason) so a copy you keep stays marked as test data.
The ClaimResponse names the insurer by its Payer ID, SANDBOX-EHP, and carries either an answer
in item or an error in error, never both.
itemis the medication you asked about. Its restriction is thertpbc-benefitRestrictionextension (covered,prior-auth,quantity-limitornot-covered), and what the member pays is inadjudication, each amount coded by CARIN’s pay type (copay,coinsurance,eligibleortotal).addItemis an alternative drug, where the row has one: markedrtpbc-isAlternative, with its own restrictions and amounts and the quantity you asked about.processNotealways starts with one note saying the answer is synthetic, which test member it is for and which row answered. A limit’s words, such asQuantity limit: 9 tablets per 30 days, are a further note that the item points to withnoteNumber.errorcarries one code fromhttps://haau3.com/fhir/CodeSystem/sandbox-error:no-test-member(no test member matched) orinsurer-declined(the insurer declined the request), withoutcomeerror.
What is refused
A request is read by the same rules as Pharmacy Benefits’ member’s request, so a request this base accepts, the platform’s FHIR base accepts too. A request it refuses is answered400 with an
OperationOutcome that names the element by its FHIRPath, never a value you sent: a body that is
not a message Bundle, a list over its cap, an element the CARIN profiles require that is missing,
a reference that names no entry in the Bundle, a product with no NDC or RxNorm code, or a request
with no Coverage or no payer identifier.
The request without patient details (rtpbc-request-non-phi) is refused too, not-supported:
Example Health Plan answers a member’s request only.
Errors
The statuses every service shares, among them
401, 405, 406, 415, 429 and 500, are on
Errors, limits and request ids.
Data handling
Example Health Plan answers with synthetic data, for its test members only, and is not an operation for patient data. It is stateless all the same: nothing a request carries is stored, cached or logged, apart from a request ID you choose to send. The log records the outcome’s code, never a member or a medication, and every answer of$process-message carries Cache-Control: no-store.
See Patient data.
Specification
- CARIN Consumer Real-Time Pharmacy Benefit Check, STU2 ballot,
whose responder statement Example Health Plan’s
CapabilityStatementinstantiates. - The Sandbox’s error codes, in haau3’s FHIR Implementation Guide.
- The operation in the API reference.