Platform

One engine. Any data in, your schema out.

A stateless, pure-compute mapping cascade that turns any CSV, Excel, JSON, or SQL into your schema — resolving most columns on free deterministic layers before any AI is touched.

reshape.pyworkbook.xlsxImportGenerate codeClean output

The cascade

Five layers, cost-ordered — the engine stops the moment a column resolves

Each header runs down a ladder from free and deterministic to metered AI. The instant a layer is confident, the cascade accepts and moves on — so most files are fully mapped before the paid layer is ever touched. That early exit is the single biggest cost lever in the system.

LayerWhat it doesCost
1 · StatisticsDeterministic auto-accept from confirmed history — a header maps if past mappings agree at production-tested thresholds.Free
2 · HeuristicNormalizes accents, punctuation, and whitespace, then matches against each field’s column, label, and multilingual hints (DE/FR/IT/EN/ES).Free
3 · FuzzyToken-set ratio + Levenshtein over normalized strings — tolerates typos and token-order drift, auto-accepting above a fixed confidence bar.Free
4 · SemanticEmbeddings cosine over the header vs each field’s label + hints. Cached, cheap, and silently skipped when no embedding key is configured.Cached
5 · LLMEvery header still unresolved is sent in ONE collision-aware batched call, constrained to your column set and told which fields are already claimed.Metered

Layers 1–3 are free and pure-compute. Layer 4 is cheap and cached. Layer 5 is a single batched call for the long tail only — and it never runs for a header an earlier layer already claimed.

Structural understanding

Real-world grids are messy. The engine reads them before it matches.

Before a single header is compared, a deterministic pass (lib/structure.ts) turns spreadsheets-as-humans-made-them into clean logical tables. No LLM, no configuration — just structure recovery.

Headers that aren’t on row 0

Detects the real header row under title banners, logos, and blank lead-in rows — no “skiprows” guesswork required.

Multi-row & grouped headers

Flattens stacked header bands into a single logical name, joining a group and its child — “Instrument › Variable” — so each column reads cleanly.

Unit rows captured

Recognizes a units row beneath the header and carries it as column metadata instead of poisoning the first data row.

Transposed sheets un-pivoted

Auto-detects wide → long layouts where variables run down a column, and unpivots them back into tidy rows — deterministically, no LLM.

Reshape: beyond renaming

When mapping isn’t enough, the engine reshapes — safely

Some inputs need more than column renaming: a pivot, a split, a join across sheets. A PHI-free router picks the cheapest strategy that works, and the model — when one is used at all — never sees your data.

direct

The plain cascade. Columns map one-to-one; nothing to reshape. Free and deterministic.

plan

A declarative JSON DSL run in-process — deterministic and byte-reproducible. Same input, same output, every time. No code execution, no LLM.

code

Generated Python / R / SQL run in an isolated sandbox. The model sees only the table shape and ≤3 sample rows — never the data itself.

Across every generated path the boundary holds: the model is shown a skeleton — headers plus a clamped preview — and writes a transform it never gets to run against your full records. See how reshape works →

Two modes, one boundary

Schema-only, or full-data under a BAA — the data boundary is one code path

Both modes run the same in-process cascade. The only difference is what may leave you, and both are gated at a single clamp — not scattered across routes.

Schema-onlyFull-data
What leaves youColumn headers + up to 3 sample rows, each clamped to ≤80 characters. Raw records stay home.The same clamped preview for matching — plus, for the layer-5 call only, the cells that fell through to the LLM.
Where it runsEntirely in-process. The deterministic cascade never phones out.In-process cascade; the single layer-5 LLM call routes to a PHI-eligible, in-region provider under X-PHI + X-Region.
ComplianceData-minimized — only clamped previews leave you, so a DPA often isn’t needed (provided on request).Active PHI entitlement. In-region, under a BAA, PHI-eligible model enforced in-region.
One clampclampForSchemaOnly() is the single edge chokepoint every route shares.Same clamp for matching; the data boundary is one code path, not per-route promises.

Schema-only is a data-minimization mode — only clamped previews leave you. Full-data is gated behind an active PHI entitlement; only the layer-5 LLM call routes to a PHI-eligible provider, in-region, under a BAA.

Built for regulated data

Compliance isn’t a mode — it’s the substrate

The cascade is the product, but the deployed engine is a full stateful SaaS with the controls regulated teams have to answer for. These are wired in, not roadmap.

Hash-chained audit trail

Every commit and confirmation is written to a tamper-evident log (Chainlog) and mirrored to the Supabase audit_logs table — a replayable record of who mapped what.

24-hour upload TTL

Uploaded files live in Cloudflare KV with a 24h expiry, then vanish. Nothing lingers longer than the mapping session needs.

KEK-encrypted secrets

Connector credentials and other secrets are envelope-encrypted under a key-encryption key, scoped per tenant and never returned in plaintext.

Strict CSP, per-request nonce

Every page ships a strict Content-Security-Policy with a fresh nonce minted per request — inline scripts that aren’t ours simply don’t run.

Fail-closed PHI allowlist

Full-data PHI traffic only reaches BAA-covered hosts on an explicit allowlist. If it’s unset in production, PHI routing refuses rather than leaks.

GDPR / HIPAA / nFADP posture

Regulated-data-first by design: schema-only mode ships no identifiers, full-data routes in-region under a BAA, and residency is enforced at the edge.

Try it

One call reshapes a file end to end

POST a file (or a stored upload id) and, optionally, a target template. The router decides between direct, plan, and code, then returns the reshaped sheets — with the chosen strategy echoed back so you can prove exactly how the transform ran.

Good to know
  • A plan strategy is byte-reproducible: re-run it and you get the identical bytes back.
  • Add Accept: application/vnd.openxmlformats… to stream a ready .xlsx instead of JSON.
  • Delivered rows meter against your monthly quota; the strategy header rides on every response.
POST /v1/reshape
POST /v1/reshape
Authorization: Bearer sk_live_…
Content-Type: application/json

{
  "file": { "content_base64": "<your .xlsx or .csv>" },
  "template": "lab_results"
}
200 OK
{
  "ok": true,
  "strategy": "plan",
  "decision": "declarative reshape — no code, no LLM",
  "sheets": [
    {
      "name": "results",
      "headers": ["patient_id", "analyte", "value", "unit"],
      "rows": [
        ["P-1042", "glucose", "5.4", "mmol/L"]
      ]
    }
  ],
  "warnings": []
}

Ready when you are

One key unlocks the whole engine.

Schema-only mode runs the same cascade on your prepaid wallet — every map is a few tokens; only files that need the paid layer add AI token cost.

$10 minimum to start · pay only for what you map · PHI under BAA coverage
How AdaptivMapr works — the mapping engine — AdaptivMapr