Data Transformer
Map and reshape data between systems using a visual field mapper or JSONata expressions — no code required for standard transformations.
The Data Transformer at Integrations → Transformer provides a visual way to define data mappings between external payload formats and FlowOS table schemas (and vice versa). Use it to normalize inbound webhook data, reshape records before sending to an API, or convert between field naming conventions.
Transform Types
| Type | Description |
|---|---|
| Visual Mapper | Drag-and-drop field mapping with type coercion and static value injection. |
| JSONata | Full JSONata query language for complex transformations, array operations, and conditionals. |
| JQ | jq filter syntax for JSON reshaping. Familiar to DevOps teams. |
| SDK Artifact | Use a custom Transform artifact for logic that visual or expression transforms cannot handle. |
Visual Field Mapper
The visual mapper shows source fields on the left and target fields on the right. Draw a line between fields to create a mapping. Each mapping supports:
- •Direct copy — copy the value as-is.
- •Type coercion — string → number, number → string, epoch → ISO 8601, etc.
- •Static value — always write a fixed value regardless of input.
- •String template — compose a string from multiple fields:
{{firstName}} {{lastName}} - •Enumeration map — map input enum values to output enum values (e.g.,
"High" → "P1"). - •Condition — write to the target only if a condition is met.
JSONata Transforms
JSONata is a query and transformation language for JSON. The full specification is at jsonata.org. Below are the patterns most used in integration transforms:
Basic Field Mapping
/* Input: PagerDuty incident */
/* Output: FlowOS incident fields */
{
"title": payload.incident.title,
"source": "pagerduty",
"external_id": payload.incident.id,
"severity": payload.incident.urgency = "high" ? "P1" : "P2",
"status": "open",
"created_at": $toMillis(payload.incident.created_at)
}Array Operations
/* Map array of tags */
{
"tags": payload.labels.name[],
/* Filter and map */
"high_priority_ids": payload.issues[priority = "high"].id,
/* Flatten nested array */
"all_assignees": payload.projects.issues.assignee.email
}Conditional Logic
{
"severity": $lookup({
"p1": "P1", "critical": "P1",
"p2": "P2", "high": "P2",
"p3": "P3", "medium": "P3",
"p4": "P4", "low": "P4"
}, $lowercase(payload.priority)),
"assigned_team": payload.team_name != null
? payload.team_name
: "unassigned"
}JQ Transforms
# Reshape a GitHub push event into an event bus payload
{
repo: .repository.name,
branch: (.ref | split("/") | last),
pusher: .pusher.name,
commits: [.commits[] | { id: .id, message: .message }]
}Testing Transforms
The transformer editor has a built-in test panel. Paste sample input JSON on the left, see the transformed output on the right. Errors are highlighted with line numbers.
# Test via API
POST /api/v1/integrations/transformer/:id/test
Body: { "input": { /* sample payload */ } }
Response: { "output": { /* transformed result */ }, "errors": [] }Using in Workflows
Add a Transform node to the canvas. Select a saved transformer or write an inline JSONata expression. The node's output is the transformed object, available to downstream nodes as {{nodes.transform-1.*}}.