Use case · HR & People
Load an employee master file into a new HRIS.
An HRIS migration is one file with identity, contact, national ID and bank details per person. Map it to employees_v1, validate the identifiers, and get a review flag on every run because the template is high-risk by design.
The job
What you are actually trying to get done
You are standing up a new HRIS and the old one exports a single flat file. It has to land with the right person in the right department, the national identifiers intact, and the bank details correct — and the headers are in whatever language the last system was configured in. The job is to do it once, correctly, with a record of what was mapped to what.
Where it lands
Employees
employees_v1 · risk: high
Every field on this template ships hints in five languages — DE, FR, IT, EN and ES. Matricule, Personalnummer, Matricola and número de empleado all reach employee_id on layer 2, at zero cost, with no model involved.
Canonical columns
- employee_id
- legal_name
- national_id
- iban
- hire_date
- department
- status
8 canonical columns · 2 required · 3 validated
Step by step
The whole run, one call at a time
- 1
Upload the export
CSV delimiter is sniffed; Excel is read natively. The response returns your detected columns and three clamped sample rows, so you can see exactly what the mapping call will be working from.POST /v1/uploads - 2
Let the multilingual hints do the work
normalize()strips accents and punctuation, then the header is compared against each field’scolumn,labeland everyhintsentry.Département→departmentis a normalized exact hit at 1.00.POST /v1/uploads/:id/match - 3
Correct the ones you disagree with
A contest is settled by layer rank, then confidence, then column index — never by which column comes first. If you still want a different answer, your override is authoritative and is learned.PATCH /v1/uploads/:id/mappings - 4
Validate identity and payment fields
emailby its validator,national_idagainst the template’s regex,ibanby mod-97.statusis an enum —active,terminated,on_leave— so four spellings of “left” are caught, not silently accepted.POST /v1/uploads/:id/validate - 5
Commit into the new system
Straight into a destination connector (database: { connector_id, table }), or as a file, or over a signed webhook. Checkfailed_batches: batches are independent, so a 200 is not proof of full delivery.POST /v1/uploads/:id/commit
In code
Five languages, one template
The public match endpoint is the fastest way to see multilingual hints working. No key, 100 requests an hour per IP, sample rows hard-clamped to three at the HTTP edge.
curl https://api.adaptivmapr.com/v1/match \
-H "Content-Type: application/json" \
-d '{
"template_id": "employees_v1",
"headers": ["Matricule", "Courriel", "Date d'\''embauche", "Département"]
}'{
"template_id": "employees_v1",
"matches": [
{ "source_col": "Matricule", "target_field": "employee_id", "source": "heuristic", "confidence": 1 },
{ "source_col": "Courriel", "target_field": "email", "source": "heuristic", "confidence": 1 },
{ "source_col": "Date d'embauche", "target_field": "hire_date", "source": "heuristic", "confidence": 1 },
{ "source_col": "Département", "target_field": "department", "source": "heuristic", "confidence": 1 }
],
"cascade_layers": ["statistics", "heuristic", "fuzzy", "ranker", "semantic", "ai"],
"unmapped": []
}- Adding a hint is the single highest-leverage thing you can do to catch your own in-house vocabulary — the heuristic layer compares against every hint and a hint costs nothing at runtime.
employees_v1is high-risk, sorequires_hitlistrueon every mapping response. So ispayroll_v1. Between them they are two of the five high-risk templates in the catalogue.- The dashboard plane is Supabase Auth with RLS as the enforcement gate; the v1 bearer API uses HMAC self-contained keys carrying a
tenant_id, with a Supabase revocation check layered on top that fails closed. - Deleting the workspace destroys the tenant row and its cascade, purges KV, clears caches and writes the audit event first —
DELETE /api/v1/me/workspaceand the account route run the same implementation.
Where the work lands
Which layer resolves this file
| Layer | What it does here | Auto-accepts at | Cost |
|---|---|---|---|
| 1 · statistics | Header→field pairs confirmed on earlier migrations from the same source system | ≥100 @ 95% · ≥20 @ 100% | Free · deterministic |
| 2 · heuristic | “Matricule”, “Courriel”, “Date d’embauche”, “Département” — French hints, shipped | ≥ 0.85 | Free · deterministic |
| 3 · fuzzy | “Codice fiscale” → national_id and “Statut” → status after normalization | ≥ 0.80 | Free · pure compute |
| 4 · semantic | An org-specific label — “Kostenstelle”, “Band” — with no shared vocabulary | ≥ 0.78 | Cheap, cached · off without an embedding key |
| 5 · ai | One batched call over the leftovers, constrained to the unclaimed field set | 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
employees_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 limitThe 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 seats or contract; you top up a prepaid wallet from $10 and it draws down.
Rate cardAI 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.
MechanismresolveRunPhi() 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
Which languages do the header hints cover?
What if our headers are in a language you do not ship?
Can two source columns map to the same field?
Is there a free tier to try this on?
Stop hand-mapping this file. Map it once.
Start with a $10 prepaid wallet. In schema-only mode only headers and up to three sample rows — each cell clamped to 80 characters — ever leave you.