Use case · Healthcare
Ingest claim line items with CPT and ICD-10 checked first.
Billing files arrive per clearinghouse, per payer, per month. Map them to claims_line_items_v1, have every CPT and ICD-10 code checked before the batch is written, and emit FHIR Claim.item.
The job
What you are actually trying to get done
Every payer and every clearinghouse hands you a different line-item layout, and the fields that matter are codes: a wrong CPT is a denial, a wrong ICD-10 is a resubmission. The job is to get each file into one shape, prove the codes are well-formed before you write anything, and keep an auditable record of which mapping produced which batch.
Where it lands
Claims line items
claims_line_items_v1 · risk: medium · FHIR Claim.item
The template declares fhir_resource: "Claim.item" — the line-item half of the two-level Claim split in lib/fhir.ts. Columns the template does not declare (a rendering NPI, a claim number) are not lost: carry them through POST /v1/reshape, or map them to a schema of your own with POST /v1/schemas.
Canonical columns
- cpt_code
- icd10_code
- amount
- service_date
4 canonical columns · 2 required · 2 validated
Step by step
The whole run, one call at a time
- 1
Upload the batch
CSV, TSV, Excel, JSON, XML or a SQL dump — all parsed in-process, nothing egresses to read them. 10 MiB ceiling by default (MAPR_MAX_UPLOAD_BYTES).POST /v1/uploads - 2
Map the abbreviations
Proc Codereachescpt_codethrough thecptandprocedurehints;Dx1reachesicd10_codeon the fuzzy layer againsticd/icd-10. Neither needed a model.POST /v1/uploads/:id/match - 3
Check the codes per row
cpt_codeandicd10_codevalidators run over every row. Errors come back with their row index, capped at 500 per response so a bad batch cannot return a 40 MB error list.POST /v1/uploads/:id/validate - 4
Commit and record the layout
The response carriesaccepted,skippedand amapping_fingerprint. Deliver inline (≤10,000 rows), in HMAC-signed webhook batches of 500, or straight into a database through a saved destination connector.POST /v1/uploads/:id/commit - 5
Reuse it next month
Same payer, same header row, same fingerprint — the confirmed mapping comes straight back and the cascade does not run at all. The flat per-map fee still applies; the AI cost does not, because no AI ran.POST /v1/layouts/lookup
In code
The mappings call, and the flag it returns
Confirming a mapping is also where the review flag appears. It is derived from the template’s own risk field, so there is no per-id list to maintain and no setting to forget.
curl -X PATCH https://api.adaptivmapr.com/v1/uploads/upl_8f3a2c/mappings \
-H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mappings": [
{ "source_col": "Proc Code", "target_field": "cpt_code" },
{ "source_col": "Dx1", "target_field": "icd10_code" }
]
}'{
"upload_id": "upl_8f3a2c",
"mappings": [
{ "source_col": "Proc Code", "target_field": "cpt_code", "source": "user" },
{ "source_col": "Dx1", "target_field": "icd10_code", "source": "user" }
],
"requires_hitl": true,
"hitl_status": "pending_review"
}- A user override is recorded and feeds
mapping_statistics, the cascade’s layer 1. Twenty unanimous confirmations of the same header→field pair and it auto-accepts there next time — before any string is compared. - A target field, once assigned, cannot be reused by another header in the same call. Two source columns can never map to one target, and reversing your column order cannot change the result.
Idempotency-Keyis NOT read on inbound requests. Retrying a failedcommitproduces a second map and a second flat fee — build your retry logic around themapping_fingerprint, not an assumed guarantee.- Webhook batches are signed with
X-Mapr-Signatureand delivered through a Cloudflare Queue with a dead-letter queue and admin replay.GET /v1/uploads/:id/deliveryreports per-batch status.
Where the work lands
Which layer resolves this file
| Layer | What it does here | Auto-accepts at | Cost |
|---|---|---|---|
| 1 · statistics | This payer’s exact header row, after ~20 unanimous confirmations | ≥100 @ 95% · ≥20 @ 100% | Free · deterministic |
| 2 · heuristic | “Proc Code” → cpt_code and “Dx1” → icd10_code via the shipped cpt / icd hints | ≥ 0.85 | Free · deterministic |
| 3 · fuzzy | “Billed Amt” → amount and “DOS” → service_date after normalization | ≥ 0.80 | Free · pure compute |
| 4 · semantic | A payer-specific label that shares no vocabulary with the field | ≥ 0.78 | Cheap, cached · off without an embedding key |
| 5 · ai | One batched call over the leftovers, told which fields are already claimed | Model pick, constrained to the unclaimed column set | Metered · the only paid layer |
MAPR_EMBEDDING_API_KEY, MAPR_LLM_API_KEY) and fail soft to OFF, so an unconfigured deployment still maps on the deterministic layers rather than erroring.Before you commit
Review, cost and where it routes
It comes back flagged for review
PATCH /v1/uploads/:id/mappings returns requires_hitl: true and hitl_status: "pending_review" — automatically, from the template’s own risk field.Usually just the flat fee
$0.0010) is drawn on every map — a fully deterministic one and a layout-cache re-map included. There is no free tier and no seats or contract; you top up a prepaid wallet from $10 and it draws down.lib/pricing.ts and GET /v1/pricing.PHI routing is opt-in, and gated
X-PHI and a region pin, so a PHI-eligible in-region model handles it under the BAA.POST /v1/me/agreements). An explicit PHI ask without one is 403 agreement_required with a settings_url pointer — never a silent downgrade. PHI adds 20% to the whole map charge.Questions