Map API
Turn incoming data into the exact shape your application expects. Give Map your source records plus the target schema you need, and it infers the field mapping, converts every value to the target type, and returns data in your shape — with a confidence and a plain-language reason for each mapping. You don’t write dozens of field-mapping rules by hand.
Endpoint & cost
POST /api/v1/map
Metering is based on input records: 100 records sent to Map draws down 100 records, regardless of how many fields are mapped or whether repair-first runs. The synchronous maximum is 500 records per request. Requests that fail validation are never charged.
How mapping works
For each field in your target schema, Map picks the best source mapping:
- Direct match — the source field name equals the target name (case-insensitive).
- Alias match — both names represent the same business concept (e.g.
annualrevenueandannual_revenue). - Field similarity — a conservative name-overlap fallback.
- Combine — a full-name target fed by separate
first_name+last_namecolumns. - Safe split — a first/last-name target derived from a single full-name column.
The matched value is then converted to the target type (currency and numbers parsed, dates to ISO 8601, phones to E.164, emails normalized, booleans parsed). Low-confidence mappings are not applied silently — they go to review_required.
Request fields
| Field | Type | Description |
|---|---|---|
| records* | object[] | Source records to transform (1-500). Values must be primitives (no nested objects/arrays). |
| target_schema* | object | The schema you want. Each value is a type string ("string") or an object { type, required }. Types: string, integer, float, number, boolean, email, phone, url, date, datetime, currency, percentage, company, name, country, state, postal_code, identifier. |
| options.strict | boolean | Only apply very high-confidence mappings; ambiguous ones go to review. Default false. |
| options.repair_before_mapping | boolean | Clean and standardize values with the Repair engine before mapping. Billed once. Default false. |
| options.drop_unmapped | boolean | Drop source fields that do not map to any target field. Default true. |
Response
| Field | Type | Description |
|---|---|---|
| data | object[] | Your records in the target shape, one per input record. |
| mappings | object[] | How each target field was resolved: source_fields, target_field, transformation, confidence, and reason. |
| unmapped_source_fields | string[] | Source fields that did not feed any target field. |
| unresolved_target_fields | string[] | Target fields no source could confidently populate. |
| review_required | object[] | Low-confidence mappings, unresolved required fields, and per-record conversion issues. |
| summary | object | Counts: records_received/mapped, records_with_review_items, fields_mapped, unresolved_fields, plus the flags used. |
Strict mode
Set options.strict: true to only auto-apply mappings at very high confidence. Anything less certain is left unresolved and surfaced in review_required rather than guessed — use it when a wrong mapping is worse than a missing one.
Repair before mapping
Set options.repair_before_mapping: true to run the Repair engine over your records first (normalize and standardize values, without changing the row count), then map the cleaned records. This is billed once per input record — you are never charged separately for the internal repair.
Errors & limits
400 invalid_request— empty records, a nested/non-primitive value, or an empty target_schema.400 invalid_request— a target field declares an unknown type.413 payload_too_large— the body exceeds the size cap or more than 500 records.401 unauthorized/invalid_api_key— missing or invalid key.429 usage_limit_exceeded/rate_limit_exceeded— allowance or burst limit reached.
Internal errors return a sanitized 500 internal_error and never leak record contents. See Errors.
Try it live
Pick a scenario (map, strict, or repair-first) or edit the JSON, then send it against the live engine. No API key required.
POST /api/v1/map// Send the request to see the live response.
Live demo endpoint · no API key needed · rate-limited · not stored · runs the production engine
Example request
POST /api/v1/map
Authorization: Bearer zap_live_...
Content-Type: application/json
{
"records": [
{ "firstname": "Mike", "lastname": "Perkins", "annualrevenue": "$2.4M", "phone": "(704) 555-1234", "company": "Acme, LLC" }
],
"target_schema": {
"full_name": { "type": "string", "required": true },
"company_name": { "type": "string" },
"annual_revenue": { "type": "number" },
"phone_number": { "type": "phone" }
},
"options": { "strict": false, "repair_before_mapping": false }
}Example response
{
"request_id": "req_xxx",
"success": true,
"data": [
{ "full_name": "Mike Perkins", "company_name": "Acme, LLC", "annual_revenue": 2400000, "phone_number": "+17045551234" }
],
"mappings": [
{ "source_fields": ["firstname", "lastname"], "target_field": "full_name", "target_type": "string", "transformation": "concatenate_with_space", "confidence": 0.98, "reason": "target expects a full name and the source provides separate first and last name columns" },
{ "source_fields": ["company"], "target_field": "company_name", "target_type": "string", "transformation": "alias_match", "confidence": 0.95, "reason": "source field \"company\" and target \"company_name\" both represent \"company\"" },
{ "source_fields": ["annualrevenue"], "target_field": "annual_revenue", "target_type": "number", "transformation": "alias_match", "confidence": 0.95, "reason": "source field \"annualrevenue\" and target \"annual_revenue\" both represent \"revenue\"" },
{ "source_fields": ["phone"], "target_field": "phone_number", "target_type": "phone", "transformation": "alias_match", "confidence": 0.95, "reason": "source field \"phone\" and target \"phone_number\" both represent \"phone\"" }
],
"unmapped_source_fields": [],
"unresolved_target_fields": [],
"review_required": [],
"summary": {
"records_received": 1,
"records_mapped": 1,
"records_with_review_items": 0,
"fields_mapped": 4,
"unresolved_fields": 0,
"repaired_before_mapping": false,
"strict": false
},
"usage": { "records_processed": 1, "credits_used": 1, "credits_remaining": 999 }
}Code examples
curl -X POST https://zapinner.com/api/v1/map \
-H "Authorization: Bearer $ZAPINNER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [
{ "firstname": "Mike", "lastname": "Perkins", "annualrevenue": "$2.4M", "phone": "(704) 555-1234", "company": "Acme, LLC" }
],
"target_schema": {
"full_name": { "type": "string", "required": true },
"company_name": { "type": "string" },
"annual_revenue": { "type": "number" },
"phone_number": { "type": "phone" }
}
}'