Import a processor settlement file without touching a full PAN.
Processors export settlements in their own shape. Map them to payments_v1 — brand, last four digits, amount, currency, status, processor reference — with the template built so a full card number has nowhere to land.
Abbreviated processor headers, an amount in minor units, a state vocabulary that is nearly but not quite the one your ledger uses.
The job
What you are actually trying to get done
Reconciling a processor settlement starts with getting the file into your own shape, and the constraint that makes it awkward is scope: whatever you build must not become a place a full card number can land. The job is to normalise brand, last four, amount, currency, status and reference — and nothing else.
Where it lands
Payments
payments_v1 · risk: high
card_last4 is constrained by a regex validator of exactly ^\d{4}$ — four digits, no more. There is no PAN field on this template, so a full card number has nowhere to map and is reported as unmapped rather than quietly carried through. That is the PCI posture, expressed in the schema rather than in a policy document.
Parsed in-process. Nothing about a tabular file egresses in either mode — the parse happens inside the Worker, on your bytes.
POST /v1/uploads
2
Map the abbreviations
last4 reaches card_last4 through the shipped last 4 hint; ccy reaches currency on the fuzzy layer; amt reaches amount. A column named pan or card_number reaches nothing, by design.
POST /v1/uploads/:id/match
3
Normalise the status vocabulary
status is an enum, so a processor’s SETTLED or CAP either maps to one of the four values or fails validation loudly. An unrecognised state does not become a silent new category in your ledger.
enum: authorized | captured | refunded | failed
4
Validate the masked fields
card_last4 against its four-digit regex, amount as a number, captured_at as a date. Failures come back per row with the field named.
POST /v1/uploads/:id/validate
5
Land it in your ledger
Commit inline, as a file, over a signed webhook, or straight into a destination connector. Reconciliation logic is yours — this gets the file into the shape your reconciliation reads.
POST /v1/uploads/:id/commit
In code
Settlement CSV in, ledger rows out
One call runs upload, match and validate and returns the transformed grid, with an optional serialized file attached to the same envelope.
→ 7 of 7 columns mapped on layers 2–3 · no PAN field exists to map into · 0 AI tokens
The finance pack maps masked card data only. That is stated in the template source and enforced by the schema: there is no PAN field, so there is no mapping target for one.
payments_v1 is high-risk, so every mapping response carries requires_hitl: true. The flag is advisory in v1 — it tells your importer to gate; it does not block the commit server-side.
The sql emit writes a CREATE TABLE IF NOT EXISTS plus one INSERT INTO per row, keyed on the template id, and round-trips back through the SQL parser — so a dump you emit is a file you can re-import.
xlsm is refused on this path with xlsm_requires_template: macro output needs a source workbook to take macros from, and a file merely named .xlsm is the format/extension mismatch Excel refuses.
Where the work lands
Which layer resolves this file
Layer
What it does here
Auto-accepts at
Cost
1 · statistics
The processor’s exact header row, after ~20 unanimous confirmations
≥100 @ 95% · ≥20 @ 100%
Free · deterministic
2 · heuristic
“last 4”, “card brand”, “currency”, “reference” — shipped hints in five languages
A processor-specific label with no shared vocabulary
≥ 0.78
Cheap, cached · off without an embedding key
5 · ai
One batched call over the leftovers, constrained to unclaimed fields
Model pick, constrained to the unclaimed column set
Metered · the only paid layer
Layers run in strict cost order and short-circuit — the first layer that resolves a column claims the target field and no later, dearer layer sees it. Layers 4 and 5 are config-gated (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
payments_v1 is a high-risk template, so PATCH /v1/uploads/:id/mappings returns requires_hitl: true and hitl_status: "pending_review" on every call, for every workspace, with nothing to configure.
Honest limit · The flag is derived from the template’s risk field and is advisory in v1 — we set it, your workflow owns the queue. The upload is not server-side blocked. A native AgentGate approval queue is roadmap, not v1.
Usually just the flat fee
When every column resolves on layers 1–3 — the common case for a file you receive regularly — no model runs, so there are no AI tokens to bill. A small flat per-map 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 subscription; you top up a prepaid wallet from $10 and it draws down.
Rate card · AI tokens are billed only when a model actually ran, at provider cost ×2 (×0.5 with your own LLM key). A PHI-routed run multiplies the whole charge — flat fee included — by 1.2. See lib/pricing.ts and GET /v1/pricing.
Standard routing, region still pinned
This job carries no protected health information, so it runs on standard routing with no surcharge. The workspace region pin still applies — the routing class picks the model catalogue; the region decides where compute may run.
Mechanism · resolveRunPhi() in lib/agreements.ts resolves the axis per run from phi_mode in the body, falling back to tenants.phi_mode (default false). PHI is available on this job too if your data class calls for it — it costs +20% and needs the BAA.
Questions
The things people actually ask
The payments_v1 template maps masked card data only — brand and the last four digits — and declares no field a full PAN could map to, so a PAN column in your source is reported as unmapped rather than carried through. Your own PCI scope depends on your whole environment; what we can say is that this template is built so cardholder data has nowhere to land.
No. AdaptivMapr normalises the file into your schema, validates it and delivers it. Matching settlements against ledger entries, handling fees and chargebacks, and deciding what an unmatched line means is reconciliation logic that belongs in your finance system. This removes the part where every processor has a different CSV.
It fails validation with the row index and the field named, rather than being accepted as a new category. That is deliberate: an unrecognised settlement state silently entering a ledger is worse than a rejected row. Map it explicitly, or extend your own schema with the values you actually use.
Yes. Destination connectors cover BigQuery (tabledata.insertAll), Snowflake (SQL Statement API v2 with key-pair JWT) and Databricks (SQL Statement API), plus sql_write over HTTP, Supabase via PostgREST — the only destination supporting upsert — object storage, and the SaaS three. Writes batch at 500 rows and are not transactional across batches, so check failed_batches.