Payerbox Docs

Querying via FHIR API

Every query is a GET to /fhir/<ResourceType>, every filter is a SearchParameter, and the response is a Bundle of type searchset - matched resources plus pagination links.

Examples below use ExplanationOfBenefit (EOB) - for prior auth, the PDex Prior Authorization profile. The base resource also covers paid and denied claims; use disambiguates (claim, preauthorization, predetermination).

Anatomy

GET /fhir/ExplanationOfBenefit
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/fhir+json

{
  "resourceType": "Bundle",
  "type": "searchset",
  "link": [
    {"relation": "self", "url": ".../fhir/ExplanationOfBenefit"},
    {"relation": "next", "url": ".../fhir/ExplanationOfBenefit?_page=2"}
  ],
  "entry": [
    { "resource": { "resourceType": "ExplanationOfBenefit", "id": "...", "...": "..." } }
  ]
}

Counts

_summary=count returns the total with no rows in the body:

GET /fhir/ExplanationOfBenefit?_summary=count
HTTP/1.1 200 OK
Content-Type: application/fhir+json

{
  "resourceType": "Bundle",
  "type": "searchset",
  "total": 30214876
}

Combine with any SearchParameter to count a slice:

GET /fhir/ExplanationOfBenefit?use=preauthorization&_summary=count
GET /fhir/ExplanationOfBenefit?use=claim&_summary=count

Search capabilities

The Aidbox UI lists the SearchParameters available for any resource type under Resources → ExplanationOfBenefit → Search parameters:

Available SearchParameters for ExplanationOfBenefit shown in the Aidbox UI - care-team, claim, coverage, created, disposition, encounter, identifier, patient, provider, status, and more, each with type and description columns

The patterns below use those parameters.

CapabilityExampleDescription
Read by idGET /fhir/ExplanationOfBenefit/XXXX-XXXX-XXXX-XXXX-XXXXDirect primary-key lookup
Filter by referenceGET /fhir/ExplanationOfBenefit?patient=Patient/XXXX-XXXX-XXXX-XXXX-XXXXEOBs for one member; also provider, insurer, coverage
Filter by code/statusGET /fhir/ExplanationOfBenefit?use=preauthorization&status=activeCombine codes - implicit AND
Filter by dateGET /fhir/ExplanationOfBenefit?_lastUpdated=ge2026-05-01_lastUpdated = system time; service-date = clinical date
CompoundGET /fhir/ExplanationOfBenefit?patient=...&_lastUpdated=ge2020-01-01Reference + date - for per-member time-windowed reports
OR within a paramGET /fhir/ExplanationOfBenefit?status=draft,entered-in-errorEither status
ModifiersGET /fhir/ExplanationOfBenefit?status:not=active:not, :missing, :exact, etc.
Sort & pageGET /fhir/ExplanationOfBenefit?_sort=-_lastUpdated&_page=2Leading - = descending; page 2 of results
Field selectionGET /fhir/ExplanationOfBenefit?_elements=id,status,outcomeReturn only the named fields
Include referencedGET /fhir/ExplanationOfBenefit?_include=ExplanationOfBenefit:patientPull related Patient into the Bundle
ChainingGET /fhir/ExplanationOfBenefit?patient:Patient.gender=femaleFilter by an attribute of the referenced resource
Reverse chainingGET /fhir/Patient?_has:ExplanationOfBenefit:patient:use=preauthorizationPatients who have at least one prior-auth EOB

Full reference in FHIR search in the Aidbox docs.

Looking up EOBs by member identifier

To find every EOB for a given member ID: the identifier lives on the Patient, not on the EOB, so the search chains into the reference and must name the target type (:Patient):

GET /fhir/ExplanationOfBenefit?patient:Patient.identifier=1A23B45C67D8

The match works two ways:

  • Value only - matches any identifier with that value.
  • System + value - pipe-separated, matches a specific identifier.system plus identifier.value:
GET /fhir/ExplanationOfBenefit?patient:Patient.identifier=https://example.org/member-ids|100071056

Same pattern for any reference - by provider NPI:

GET /fhir/ExplanationOfBenefit?provider:Organization.identifier=https://example.org/npi|1234567893

Where this stops being enough

FHIR Search is read-shaped, not analytical. When you need aggregation, joins across resource types, or fields without a SearchParameter, step up to flat views on FHIR data or SQL on FHIR data. For Aidbox's alternative search surfaces (Search resource, AidboxQuery, dot expressions) see Aidbox Search in the Aidbox docs.

Response tabs (Aidbox REST Console)

The Response panel has Body, Headers, Raw, Explain. For a query like ?patient=Patient/<id> each one shows:

x-duration:       429
x-temp-dur-in-pg: 86
x-request-id:     45c24181cfcfe184ec28c4fa457a2598
content-type:     application/json
content-length:   353939

x-duration is total HTTP wall time in milliseconds; x-temp-dur-in-pg is how much of that was spent in Postgres. x-request-id correlates the call with server logs.

HTTP/1.1 200 OK
content-type: application/json
content-length: 353939
x-duration: 429
x-temp-dur-in-pg: 86

{"resourceType":"Bundle","type":"searchset","entry":[...]}

The unparsed HTTP response - status line, headers, and body in one block. Useful for debugging content-type negotiation or copying the exact wire format.

SELECT resource
FROM   explanationofbenefit
WHERE  resource #>> '{patient,id}' = 'XXXX-XXXX-XXXX-XXXX-XXXX'
LIMIT  30;

The SQL Aidbox emits from the FHIR URL. (Explain has a Statement sub-tab too, showing the parameterized form.)

Limit  (cost=0.56..34.19 rows=30 width=451) (actual time=0.015..0.082 rows=30 loops=1)
  Buffers: shared hit=34
  → Index Scan using explanationofbenefit_pt_idx on explanationofbenefit
        (cost=0.56..362.61 rows=323 width=451) (actual time=0.014..0.079 rows=30 loops=1)
      Index Cond: ((resource #>> '{patient,id}'::text[]) = 'XXXX-...'::text)
      Buffers: shared hit=34
Planning Time: 1.480 ms
Execution Time: 0.098 ms

Postgres EXPLAIN for the emitted SQL. Open it when a query is slow or to check that a SearchParameter is hitting the index you expect.

Last updated: