Payroll CSV import API

payroll_v1

high6 fields · 3 required · 1 validatedPack · HR & People

Import this template via API. Import payroll runs from any CSV — gross salary, pay period, payout IBAN. PII-aware: raw salary rows never leave, only clamped samples.

30-second curl

curl -X POST https://api.adaptivmapr.com/v1/uploads \
  -H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
  -F "template=payroll_v1" \
  -F "file=@your_data.csv"
phi-cloud bundle required for full-data mode on this template. Schema-only mode (headers + ≤3 sample rows) is free and always available. Activate the bundle →

At a glance

Pack
HR & People
FHIR resource
Risk level
high
Fields
6 (3 required, 1 validated)

Why it exists

Why this template?

The Payroll template is the canonical schema for a pay run — the file a payroll-provider export, a salary-register dump, or a finance reconciliation extract reduces to. Each row carries an employee_id (required), a gross_salary (required), a currency (required), a pay_period parsed across locales, an optional payout IBAN, and an optional tax_code. Payroll and finance teams reach for it when migrating between payroll providers, when backfilling a warehouse with historical pay runs for cost analysis, and when reconciling a payroll register against the general ledger. It is `high` risk because salary plus bank detail is among the most sensitive PII an organisation holds. Schema-only mode is therefore the default ingress: raw payroll rows never leave the customer; only headers and a handful of clamped sample cells are processed to decide the mapping.

employee_id, gross_salary, and currency are all required — a pay row without an amount or a currency is meaningless. gross_salary is number-typed and locale-tolerant (US "5,000.00", EU "5.000,00", Swiss "5'000.00"); pay_period auto-detects ISO, US, and EU date formats. IBAN runs mod-97 with a country restriction (CH, LI, DE, FR, IT, ES) so a transposed digit blocks a mispayment before it happens. tax_code is a free string because withholding-code formats vary per jurisdiction. Hints cover DE / FR / IT / ES / EN so a multilingual payroll export does not escalate to the LLM.

Migration scenarios & common foreign headers

Migration scenarios for the Payroll template: porting pay-run history between providers (ADP → Deel, Swissdec-based systems → a new bureau) so the new platform has a complete register, backfilling a finance warehouse with historical runs for labour-cost analysis, reconciling the payroll register against the general ledger each cycle, and consolidating multi-entity payroll after a merger. Foreign headers we routinely see: "Personalnummer / Matricule / Matricola / Número de empleado / Bruttolohn / Salaire brut / Stipendio lordo / Salario bruto / Währung / Devise / Valuta / Moneda / Lohnperiode / Période de paie / Periodo di paga / Período de pago / IBAN / Compte / Konto / Steuercode / Code fiscal / Codice fiscale / Tax code / Código fiscal". The cascade resolves every one through the registered hints — no LLM call, no salary figures in any prompt.

Canonical columns

Schema

The canonical column set, with the type each row carries, whether it is required, the field-level validators that fire on commit, and the multilingual header hints the cascade resolves against.

ColumnTypeRequiredValidatorsHints
employee_idstringyespersonalnummer · matricule · matricola · employee id · número de empleado
gross_salarynumberyesbruttolohn · salaire brut · stipendio lordo · gross salary · salario bruto
currencystringyeswährung · devise · valuta · moneda
pay_perioddatelohnperiode · période de paie · periodo di paga · pay period · período de pago
ibanstringiban (CH, LI, DE, FR, IT, ES)iban · compte · konto · bank account
tax_codestringsteuercode · code fiscal · codice fiscale · tax code · código fiscal

The cascade

How AdaptivMapr maps your headers to this template

Five layers run in order, cheapest first. Layer 1 (Statistics) auto-accepts headers that have been mapped the same way across past uploads. Layer 2 (Heuristic) compares your header to the column name, the optional label, and every registered hint (DE / FR / IT / EN / ES) after a Unicode-and-punctuation-normalising pass. Layer 3 (Fuzzy) catches typos and reordered words. Layer 4 (Semantic) uses cached embeddings to catch the long tail of paraphrases. Layer 5 (LLM) only fires on genuinely ambiguous columns, constrained to the template’s allowed column set so it cannot invent a field. When a layer auto-accepts, the lower-cost layers below it never run — that is the cost lever.

REST · POST /v1/uploads

Pass the template_id; the cascade picks up the rest.

curl -X POST https://api.adaptivmapr.com/v1/uploads \
  -H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
  -F "template=payroll_v1" \
  -F "file=@your_data.csv"

The canonical template definition is read-only at GET /v1/templates/payroll_v1.

MCP · Cursor / Claude Desktop

Drop AdaptivMapr into your IDE. Schema-only calls are free and unlimited.

// In Cursor or Claude Desktop with the AdaptivMapr MCP server installed:
adaptivmapr.match_headers({
  template: "payroll_v1",
  headers: ["employee_id", "gross_salary", "currency", "pay_period"]
})
MCP install instructions →

Questions

FAQ — Payroll CSV import

Does salary data leave our environment during mapping?

No. Schema-only mode is the default: only headers and three clamped sample rows (≤80 chars each) are processed to decide the mapping. Full payroll rows never touch our infrastructure unless you explicitly opt into full-data mode under an active subscription.

Is gross_salary the only amount field?

Yes — the canonical row is deliberately minimal (gross_salary plus pay_period). Net pay, deductions, and employer contributions vary too much per jurisdiction to enum-bound; add them via a workspace fork if your downstream needs the breakdown.

How does the IBAN country restriction work?

The default allow-list is CH / LI / DE / FR / IT / ES — the cluster most European payroll runs pay into. Fork the template and broaden the `countries` array for cross-border payroll; the validator otherwise rejects out-of-list IBANs at import.

Why does pay_period use a date rather than a string like "2026-06"?

The auto date parser accepts month-level and full-date inputs and normalises them, so "Juni 2026", "06/2026", and "2026-06-30" all resolve. Storing a real date lets downstream cost analysis group and sort correctly.

Keep exploring

Browse other templates in the HR & People pack