Core pack

Users CSV import API

Import users from any CSV into a canonical directory schema. Email-validated, role-enumerated, multilingual headers handled.

low riskusers_v1
30-second curl
curl -X POST https://api.adaptivmapr.com/v1/uploads \
  -H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
  -F "template=users_v1" \
  -F "file=@your_data.csv"
→ 7 canonical fields · 1 validated · low risk

Canonical columns

The whole schema, printed as it ships.

Every canonical column, 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. This is the shipped definition, not a summary of it.

users_v1
fields
7
required
2
validated
1
hints
20
Canonical columnTypeRequiredValidatorsHeader hints the cascade matches
idstringyesmatched on the column name
emailemailyesemaile-mailmailcorreocourriel
first_namestringvornameprenomprénomnombre
last_namestringnachnamenomapellidocognome
roleenumadminmemberviewerownerrollerolerolruolo
created_atdatematched on the column name
countrystringlandpayspaíspaese

Read the same definition as JSON at GET /v1/templates/users_v1. A hint match resolves on layer 2 — no LLM call, no token spend, just the flat per-map fee. Hover a validator id to see what it checks.

  • 7 canonical fields
  • 2 required
  • 1 validated
  • 20 header hints, 5 languages

Why it exists

Written for the file you actually receive.

The Users template is the canonical schema for ingesting a user directory — the kind of file you get the morning of a migration, a SCIM dump, an HRIS export, or a CSV your customer assembled by hand the night before kickoff. It captures the seven attributes you actually want to keep across systems: a stable id, a validated email, given and family names split for personalisation, a role bounded by an enum so downstream RBAC does not break, a created_at timestamp parsed regardless of locale, and a country string for residency routing. The Users template is intentionally narrow — anything richer belongs in a profile table — so the cascade can lock onto it with minimal ambiguity. Teams use it as the first import on day one and the daily delta job from day two onwards.

Two hard guarantees: every row carries a validated email (RFC-style regex, not a vibe), and every role lands in {admin, member, viewer, owner} or surfaces as an error in the dry-run. Hints cover DE / FR / IT / ES / EN naming so a Swiss or Iberian export does not fall through to the LLM. The created_at format is auto-detected (ISO-8601, US, EU, epoch ms).

Migration scenarios & the foreign headers they ship

The most common migration scenarios for the Users template are: importing a fresh SCIM export from Okta or JumpCloud into a new B2B SaaS account, backfilling a year of historical signups from a Postgres dump into a CDP, syncing a daily delta from a legacy LDAP into a modern auth system, and porting a customer base from one identity provider to another at acquisition close. The headers we see most often in the wild are "User ID / Email / E-Mail-Adresse / First Name / Vorname / Prénom / Last Name / Nachname / Nom / Role / Rolle / Created / Erstellt am / Country / Land / País". The cascade catches all of these without an LLM call because the multilingual hint set is exhaustive for the people-data domain.

The cascade

Five layers, and the cheapest one wins.

Layers run in order and stop the moment a column resolves. That is the single biggest cost lever in the system: a column caught on layer 2 never reaches the metered layer 5.

  1. L1Statisticsno LLM

    Auto-accepts a header that past confirmations already resolved the same way, at {minN:100, minRatio:0.95} or {minN:20, minRatio:1.00}.

  2. L2Heuristicno LLM

    Normalises accents, punctuation and whitespace, then compares against the column name, the label, and every registered hint (DE / FR / IT / EN / ES).

  3. L3Fuzzyno LLM

    Token-set ratio plus Levenshtein over the normalised strings. Auto-accepts at 0.80 — it absorbs typos and reordered words.

  4. L4Semanticcheap, cached

    Embedding cosine between the header and the field’s label + hints. Catches the long tail of paraphrases.

  5. L5LLMmetered

    Everything still unresolved goes up in ONE batched, collision-aware call, constrained to this template’s column set so it cannot invent a field.

Try it

One template id, two ways in.

REST for your import pipeline, MCP for your editor. Both run the same cascade and both honour the same schema-only clamp.

REST · POST /v1/uploads

Name the template; the cascade picks up the rest. The canonical definition is read-only at GET /v1/templates/users_v1.

bash
curl -X POST https://api.adaptivmapr.com/v1/uploads \
  -H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
  -F "template=users_v1" \
  -F "file=@your_data.csv"
→ upload created · mappings ready · confirm before commit

MCP · Cursor / Claude Desktop

Drop AdaptivMapr into your editor and call the same cascade as a tool. Schema-only calls leave only column names and up to three clamped sample rows.

mcp
// In Cursor or Claude Desktop with the AdaptivMapr MCP server installed:
adaptivmapr.match_headers({
  template_id: "users_v1",
  headers: ["id", "email", "first_name", "last_name"]
})
schema-only · headers and ≤3 rows, 80 chars each
MCP install instructions

Questions

Users CSV import — FAQ

It does not. Deduplication is a downstream concern; the template guarantees a parseable email per row so your upsert key works. Run AdaptivMapr → land in a staging table → upsert on lower(email).
Map username to id and add an explicit `email` column with a placeholder. The Users template treats email as required because most downstream systems do.
Yes — fork the template into your workspace via POST /v1/templates and edit `enum_values`. The forked template gets its own id and lives only in your workspace.
Add the localised values as `hints` on the role field. The heuristic layer normalises and matches them at zero cost; the LLM never sees the column.

Ready when you are

Map users in production — without shipping raw records.

Schema-only mode leaves only headers and a handful of clamped samples. Add full-data when you need row-level AI, routed in-region under a BAA.

No free tier · $10 prepaid wallet to start · every map draws a small flat fee, deterministic ones included