For AI agents: the documentation index is at /docs/payerbox/llms.txt. A Markdown version of this page is available at /docs/payerbox/analytics/pas-metrics.md or by requesting it with the Accept: text/markdown header.
Payerbox Docs

PAS Metrics

Payerbox ships a SQL-on-FHIR package that computes the Da Vinci Prior Authorization Support (PAS) Implementation Guide's suggested metrics straight from the resources Aidbox already stores - the Claim, ClaimResponse and CommunicationRequest produced by the prior-auth flow. No separate reporting database, no ETL: the metrics read the live FHIR data.

What the IG proposes

The PAS IG describes a set of suggested metrics that a prior-authorization system can report, together with a logical PASMetricData model - one entry per submitted service line, carrying the request and response timestamps, the item result, the exchange type (initial, update, cancel, query), and the payer, provider and line-of-business identifiers.

This package implements that model. A layer of SQL-on-FHIR ViewDefinitions flattens the raw FHIR resources; a set of Library (SQLQuery) resources assembles the PASMetricData rows from those views; and one Library per metric computes the metric on top. The output is queryable as plain SQL, so it feeds any BI tool.

Metrics

The IG suggests ten metrics. The package implements all ten; two query-based views additionally require the deployment to persist inquiry (Claim/$inquire) exchanges.

#MetricWhat it reports
1Submission volumeCount of prior-auth requests submitted, by day, payer, provider and line of business
2Updates, cancels and queriesVolume split into initial, update, cancel and query exchanges
3Non-ordering provider queriesQuery exchanges made by a provider other than the ordering one
4Error percentageShare of exchanges that carried a business error (ClaimResponse.error)
5Final response on initial submissionShare of requests decided on the first response, without a pend
6Pend volume and resolutionItems currently pended vs resolved, with average time to resolution
7Time to final resultElapsed time from request to final decision, per service line - the 100 slowest decided items per payer
8SegmentationItem counts by result (approved, denied, modified, pended, cancelled), segmented by day, payer, provider and line of business
9Outstanding requestsRequests still awaiting a final decision
10Pend agingHow long currently pended items have been waiting

The query bucket of metric 2 and metric 3 report on Claim/$inquire exchanges. $inquire is a read operation and persists nothing by default; enable PAS_PERSIST_INQUIRIES=true and every successful inquiry is stored as a query exchange record, lighting up both. Metric 3 tells ordering from non-ordering queries by comparing the inquiring provider's NPI with the NPI of the provider on the original claim.

The package

  • Download: io.healthsamurai.pas-metrics-0.1.9.tar.gz
  • Contents: 26 SQL-on-FHIR resources - 10 ViewDefinitions and 16 Library resources (6 source/model wrappers plus one per metric).
  • Dependencies: hl7.fhir.r4.core only. The package reads PAS extensions by their canonical URL, so it installs and runs on any Aidbox that stores the prior-auth resources - the full PAS IG does not need to be loaded.

Install

The package is a standard FHIR NPM package. $fhir-package-install takes the tarball's location, which can be the download URL itself - Aidbox fetches it directly, so there is nothing to download, mount or vendor first:

POST /fhir/$fhir-package-install
Content-Type: application/json

{
  "resourceType": "Parameters",
  "parameter": [
    {"name": "package", "valueString": "https://storage.googleapis.com/payerbox-public/io.healthsamurai.pas-metrics-0.1.9.tar.gz"}
  ]
}

The fetch is anonymous and happens from the Aidbox process, so this form needs the instance to reach the bucket. Where it cannot - an isolated or air-gapped deployment - download the tarball, put it where Aidbox can read it, and pass a file:///path/to/io.healthsamurai.pas-metrics-0.1.9.tar.gz location instead. Both forms take the same install path.

Re-running either is safe: canonical resources upsert by URL, so installing the same version twice leaves one copy.

Alternatively, serve it from a package registry and reference it by io.healthsamurai.pas-metrics#0.1.9 in BOX_BOOTSTRAP_FHIR_PACKAGES or an init bundle. Note that BOX_BOOTSTRAP_FHIR_PACKAGES only installs into an empty package store - on a live instance use $fhir-package-install. See FHIR packages in the Aidbox docs for the mechanics.

Large audit logs

Query exchanges are stored in the auditevent table, which Payerbox shares with the platform audit log, so metrics 2 and 3 scan it directly. On a deployment with a large audit log, create the matching partial index once:

create index if not exists auditevent_pas_exchange_type
  on auditevent (ts)
  where resource @> '{"subtype":[{"system":"http://prior-auth.example.org/CodeSystem/pas-exchange-type"}]}'::jsonb;

The first where clause of the query is byte-identical to this predicate, which is what lets the partial index apply. Deployments that do not record inquiries do not need the index.

Query the metrics

Each metric is a SQLQuery Library. Run it directly and get rows back:

POST /fhir/Library/$sqlquery-run
Content-Type: application/json

{
  "resourceType": "Parameters",
  "parameter": [
    {"name": "queryReference", "valueReference": {"reference": "Library/<metric-library-id>"}},
    {"name": "_format", "valueCode": "json"}
  ]
}

Look the Library up by name first, for example GET /fhir/Library?url=https://example.org/Library/metric-07-time-to-final-result.

For dashboards, wrap each metric's compiled SQL in a Postgres view and point a BI tool at it, the same way as any other SQL-on-FHIR analytics.

Reading the results

Three things are worth knowing when you interpret the numbers:

  • Request time is the submitted Claim.created, the time the request carries in its payload, not the moment the server received it. Test data with a fixed created will pile onto that one date; real submissions carry a realistic timestamp.
  • Rows are per service line. A request with two service items produces two rows, keyed by item sequence, because items in one request can be decided independently (one approved while another pends or is denied). When every item shares the same outcome and timing, the rows differ only by item sequence.
  • Metric 4 counts business errors, and only on requests that were accepted. An error is an entry in ClaimResponse.error - typically an X12 error code written back by the utilization-management system. A submission rejected up front, for example by profile validation, is answered with an OperationOutcome and never stored, so it appears in neither the numerator nor the denominator of this metric. To exercise metric 4, drive a request that is accepted and then answered with an error rather than a decision.

The same ten metrics render as charts natively in an Aidbox Notebook (see the Aidbox docs on Notebooks) - one sql-query cell per metric, resolved by Library url. It is published beside the package:

Create it like any other resource, once the package itself is installed:

PUT /Notebook/pas-metrics
Content-Type: application/json

<the downloaded file>

The notebook is not part of the package tarball and is not installed by $fhir-package-install: that operation materializes canonical conformance resources, and a Notebook has none - it would be skipped silently.

Last updated: