Skip to Content
API ReferenceReusable Field Mappings

Reusable Field Mappings API

A field mapping is authored on five surfaces — Reverse ETL syncs, syncs (audience), orchestration send tiles, Store feeds and event-forwarding rules — and each stores its own copy. These endpoints back the mapping library: named, reusable mappings plus a single lookup that returns every mapping that could be loaded into a given place, already checked against it.

See Field Mapping → Reusing an Existing Mapping for the product behaviour.

Endpoints

MethodPathDescription
GET/api/v1/workspaces/{id}/field-mapping-libraryMappings that can be loaded into a given context, each with its verdict
GET/api/v1/workspaces/{id}/field-mapping-presetsList saved mappings
POST/api/v1/workspaces/{id}/field-mapping-presetsSave a mapping
GET/api/v1/workspaces/{id}/field-mapping-presets/{presetId}Get a saved mapping
PUT/api/v1/workspaces/{id}/field-mapping-presets/{presetId}Update a saved mapping
DELETE/api/v1/workspaces/{id}/field-mapping-presets/{presetId}Delete a saved mapping

Permissions: field_mapping_presets.read for the library and the reads, field_mapping_presets.write for the writes. The library additionally filters each origin by that origin’s own read permission — syncs.read, audience_syncs.read, journeys.read, stores.read, events.forwarding.read — so it never reveals a configuration you could not open directly.


Get the Mapping Library

GET /api/v1/workspaces/{id}/field-mapping-library

Returns every reusable mapping that could be loaded into the described context — saved mappings and the mappings already configured on other objects — each resolved against that context and carrying the adapted entry list. No second call is needed to apply one.

Query parameters

ParameterRequiredDescription
surfaceyesWhere the mapping would be pasted: model_sync, audience_sync, journey_send, store_feed, event_forwarding
destination_typeyes, except store_feedThe destination type whose field vocabulary applies
model_idThe model whose columns are in scope
parent_model_idAnchor for related-column paths; defaults to model_id
store_idStore feeds only — enables the field-ownership check
exclude_idThe object being edited, so it is never offered its own mapping
exclude_tile_idNarrows exclude_id to one orchestration send tile, keeping the rest of that journey’s tiles available

Response

{ "candidates": [ { "origin": "preset", "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Meta CAPI standard identifiers", "description": "Email, phone and external id, all pre-hashed", "destination_type": "facebook_ads", "source_model_id": "660e8400-e29b-41d4-a716-446655440000", "source_model_name": "Customers", "updated_at": "2026-08-10T11:04:00Z", "entry_count": 3, "same_model": true, "verdict": "applies", "mapping": [ {"source_column": "email", "destination_field": "email", "hash_pii": true}, {"source_column": "phone", "destination_field": "phone", "hash_pii": true}, {"source_column": "customer_id", "destination_field": "external_id"} ] }, { "origin": "audience_sync", "id": "770e8400-e29b-41d4-a716-446655440000", "name": "VIP members to Meta", "destination_type": "facebook_ads", "destination_name": "Meta Ads — Growth", "source_model_id": "880e8400-e29b-41d4-a716-446655440000", "source_model_name": "Loyalty members", "updated_at": "2026-08-02T08:15:00Z", "entry_count": 4, "same_model": false, "verdict": "partial", "mapping": [ {"source_column": "email", "destination_field": "email", "hash_pii": true} ], "issues": [ { "index": 1, "source_column": "customer_tier", "destination_field": "tier", "code": "unknown_source_column", "severity": "error", "message": "\"customer_tier\" is not on this model" } ] } ], "truncated": false, "context": { "surface": "audience_sync", "source_kind": "model", "destination_type": "facebook_ads", "model_id": "660e8400-e29b-41d4-a716-446655440000", "parent_model_id": "660e8400-e29b-41d4-a716-446655440000" } }

mapping is the adapted list — entries that could not be used here have already been removed, related-column aliases recomputed, and trait references rebound. Write it straight into the target object’s field_mapping.

Verdicts

verdictMeaning
appliesEvery entry survived. Warnings are still possible.
partialSome entries survived; the rest are listed in issues.
blockedNothing survived, or the source mapping was empty. Still returned, so a caller can explain why rather than appear to lose it.

Issue codes

codeseverityMeaning
missing_destination_fielderrorThe saved row names no destination field.
unknown_source_columnerrorA referenced source column is not on the target model. A multi-input transform is dropped whole if any input is missing.
blocked_source_columnerrorThe column exists but the model marks it blocked, so a sync strips it at run time — the row would save and then deliver nothing.
unknown_traiterrorThe trait is neither present by id nor matchable by name on the target model.
trait_reboundwarningThe trait was matched by name; trait_ids was rewritten to the local id.
related_unsupportederrorThe entry uses a related-model column, which this surface rejects.
related_path_invaliderrorThe relationship path does not resolve from this parent model.
field_owned_by_other_feederrorStore feeds only — another feed already owns that Store field.
unknown_destination_fieldwarningThe destination type does not document that field. Kept, since many destinations accept custom attributes.
duplicate_destination_fielderrorAn earlier surviving entry already claimed that destination field and path.

index refers to the entry’s position in the original mapping, so a caller can point at a row that is absent from mapping.

truncated is true when the 200-candidate cap was reached; narrow with model_id or fall back to listing presets directly.

Example

curl -X GET "https://composable.zeotap.com/api/v1/workspaces/{id}/field-mapping-library?surface=audience_sync&destination_type=facebook_ads&model_id={modelId}" \ -H "Authorization: Bearer <token>" \ -H "X-Workspace-ID: <workspace-id>"

List Saved Mappings

GET /api/v1/workspaces/{id}/field-mapping-presets

Returns every saved mapping in the workspace, most recently updated first. Unlike the library, this applies no compatibility filter and computes no verdicts.

Response

[ { "id": "550e8400-e29b-41d4-a716-446655440000", "workspace_id": "660e8400-e29b-41d4-a716-446655440000", "name": "Meta CAPI standard identifiers", "description": "Email, phone and external id, all pre-hashed", "destination_type": "facebook_ads", "source_kind": "model", "source_model_id": "770e8400-e29b-41d4-a716-446655440000", "source_model_name": "Customers", "mapping": [ {"source_column": "email", "destination_field": "email", "hash_pii": true} ], "created_by": "880e8400-e29b-41d4-a716-446655440000", "created_at": "2026-08-10T11:04:00Z", "updated_at": "2026-08-10T11:04:00Z" } ]

Save a Mapping

POST /api/v1/workspaces/{id}/field-mapping-presets

Request

{ "name": "Meta CAPI standard identifiers", "description": "Email, phone and external id, all pre-hashed", "surface": "audience_sync", "destination_type": "facebook_ads", "source_model_id": "770e8400-e29b-41d4-a716-446655440000", "mapping": [ {"source_column": "email", "destination_field": "email", "hash_pii": true}, {"source_column": "customer_id", "destination_field": "external_id"} ] }
FieldRequiredDescription
nameyesUnique within the workspace
descriptionFree text
surfaceyesThe surface the mapping was authored on: model_sync, audience_sync, journey_send, store_feed, event_forwarding. The server derives source_kind from it — and clears destination_type for store_feed. Deriving the kind client-side could store a preset with one the pickers filter on exactly, making it invisible forever with no save error
destination_typeThe destination type this mapping targets. Ignored for store_feed
source_model_idThe model the source columns were written against. Used for display and to rank exact-model matches first
mappingyesThe mapping array. Rows with no destination field are dropped; related-column aliases are normalized. A mapping that reduces to nothing is rejected

Returns 201 with the created object.


Get, Update, Delete

GET, PUT and DELETE on /api/v1/workspaces/{id}/field-mapping-presets/{presetId}.

PUT accepts name, description, source_model_id and mapping. destination_type and source_kind are not updatable: changing either would re-point the mapping at a different field vocabulary while keeping rows written for the old one. Save under a new name instead.

DELETE returns 204. Deleting a saved mapping never affects the syncs, tiles or feeds built from it — applying a mapping copies it.

Example

curl -X DELETE https://composable.zeotap.com/api/v1/workspaces/{id}/field-mapping-presets/{presetId} \ -H "Authorization: Bearer <token>" \ -H "X-Workspace-ID: <workspace-id>"
Last updated on