Deliver Data Step
Write workflow data back to your organization's datasets—insert new records, update existing ones, or upsert conditionally.
The Deliver Data step lets you write data collected during a workflow back to one or more of your organization's datasets. For each dataset, you define which entity to write to, what operation to perform, and how workflow fields map to dataset properties.
You can also write one record per item in a collection (see Repeating Records), and attach files to the records you write (see File-to-record mappings).
Datasets
A Deliver Data step contains one or more dataset operations.
| name | type | required | description |
|---|---|---|---|
datasetId | string | yes | The id of the target dataset, as returned by the Data Set Management endpoints. |
selectedSearchDataStep | string or null | yes | The name of the Data Search step whose record you are updating. Use null when the step does not update a searched record (for example, a plain INSERT). This links the two steps, but it does not identify the record on its own — see Key fields. |
stepDatasetInstanceId | string or null | yes | A stable unique identifier you assign to this dataset entry within the step. It is used internally to link field mappings to their dataset. Any non-empty string works; the Streamline UI generates a short random value (e.g. "fg4z6aiy"). Must not change once field mappings have been created against it. |
entities | array | yes | One or more entity operations. See Entities below. |
Entities
Each entity operation targets a specific entity type within the dataset.
| name | type | required | description |
|---|---|---|---|
linkId | string or null | yes | The linkId of a traversal route entry in the dataset, used when writing to a linked (non-primary) entity. Corresponds to the same linkId used as a key in the Data Search step's linkedEntitiesFilters. Use null for the primary entity. |
entityId | string | yes | Identifier of the entity type to write to. |
operation | string | yes | Operation to perform. See Operations below. |
mappings | array | yes | Field mappings from workflow data to entity properties. See Mappings below. |
repeatableConfigs | array or null | no | Collections to write as one record per item. See Repeating Records below. |
fileToEntityMappings | array or null | no | Files to create and link to the record. See File-to-record mappings below. |
Operations
INSERT: Create a new record in the dataset.UPDATE: Modify an existing record. Requires at least one key field.UPSERT: Insert if no matching record exists; update if one does.SKIP: Perform no operation—useful in conditional branches.
Mappings
Each mapping connects a workflow value to a field in the dataset entity.
| name | type | required | constraints | description |
|---|---|---|---|---|
fieldId | string or null | yes | The id of the dataset field to write to, as returned by the Data Catalog field endpoints. | |
value | string, number, object, or null | yes | The value to write. Strings support mapping placeholders (e.g. {{Form.email}}). See Date and time values for the object form. | |
isKeyField | boolean | yes | Whether this mapping identifies the record to update. See Key fields. Use false for every other mapping. | |
primitiveType | string or null | yes | See Value types | The type of the source value. Must match the type of the mapped workflow field. |
complexType | string or null | yes | See Value types | The type of the target dataset field. |
repeatableId | string or null | no | Must match a repeatableId in the entity's repeatableConfigs | Marks this mapping as part of a repeating collection. See Repeating Records. |
Key fields
A key field tells Streamline which existing record to change. Set isKeyField to true on the mapping that carries the record's unique identifier, and false on every other mapping.
The most common pattern is updating a record found by a Data Search step:
- Set
selectedSearchDataStepto the name of the Data Search step. - Add a mapping whose
fieldIdis the entity's primary key field (for Salesforce, the Record Id) and whosevaluemaps that same field from the Data Search step. - Set
isKeyFieldtotrueon that mapping.
When you set up this step in the Streamline app, the key field mapping is added for you. When you configure the step through the API, you must add it yourself. An
UPDATEwith no key field fails the session with the error "UPDATE operations require at least one usable key field".
Value types
primitiveType accepts:
string,number,boolean,date,filearray<string>,array<number>,array<boolean>,array<date>,array<file>
complexType accepts:
string,object,number,float,binary,booleandate,time,datetime,uuid,unknown,filearray<string>— use this for multi-select (ordered list) dataset fields.
Both keys are required, but either can be null when the type is not known.
Date and time values
A static date-time can be sent as an object instead of a string:
| name | type | required | constraints | description |
|---|---|---|---|---|
utc | string | yes | ISO 8601 date-time ending in Z | The moment in UTC, e.g. "2026-03-15T14:30:00Z". |
timezone | string | no | IANA time zone name, e.g. "America/New_York". | |
offset | string | no | +HH:MM or -HH:MM | UTC offset, e.g. "-04:00". |
At least one of timezone or offset is required.
Repeating Records
Use Repeating Records to write one record for each item in a collection — for example, one Contact per entry in a webhook's contacts array, or one record per result of a Data Search step with Repeating Records enabled.
Each entry in repeatableConfigs names a collection:
| name | type | required | description |
|---|---|---|---|
repeatableId | string | yes | A unique identifier you assign to this collection. Mappings reference it through their repeatableId. |
collectionSourcePath | string | yes | A mapping placeholder pointing to the collection in an earlier step, e.g. {{`Incoming webhook`.`body.contacts`}}. |
Mappings that belong to the collection set repeatableId and use [] in their placeholder to refer to the current item, e.g. {{`Incoming webhook`.`body.contacts[].email`}}. Streamline resolves the placeholder once per item and writes one record per item.
A few rules apply:
- Every
repeatableIdused on a mapping must match an entry in the same entity'srepeatableConfigs. - Mappings without a
repeatableIdwrite the same value to every record.
File-to-record mappings
Use fileToEntityMappings to create file records and link them to the record you write — for example, to attach an uploaded document to a Case.
| name | type | required | description |
|---|---|---|---|
fileRowId | string | yes | A unique identifier you assign to this file mapping. |
fileEntityId | string | yes | The id of the file entity to create records in. |
fileLinkId | string | yes | The linkId of the dataset relationship that connects the record to its files. |
fileFieldMappings | array | no | Mappings for the file entity's fields. Each item has the same structure as a mapping. Default: []. |
Examples
Let's start with the simplest valid configuration: inserting a single record with one field.
{
"datasets": [
{
"datasetId": "ds1b2c3d-e5f6-7890-1234-567890abcdef",
"selectedSearchDataStep": null,
"stepDatasetInstanceId": "ab1c2d3e",
"entities": [
{
"linkId": null,
"entityId": "e1b2c3d4-e5f6-7890-1234-567890abcdef",
"operation": "INSERT",
"mappings": [
{
"fieldId": "f1b2c3d4-e5f6-7890-1234-567890abcdef",
"value": "[email protected]",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string"
}
]
}
]
}
]
}The next example updates a customer found by a Data Search step named Search Customers, and inserts an audit log entry in the same step. The first mapping is the key field: it maps the customer's Record Id from the Data Search step to the entity's primary key field.
{
"datasets": [
{
"datasetId": "ds2b3c4d-e5f6-7890-1234-567890abcdef",
"selectedSearchDataStep": "Search Customers",
"stepDatasetInstanceId": "ab1c2d3e",
"entities": [
{
"linkId": null,
"entityId": "e2b3c4d5-e5f6-7890-1234-567890abcdef",
"operation": "UPDATE",
"mappings": [
{
"fieldId": "f2b3c4d5-e5f6-7890-1234-567890abcdef",
"value": "{{`Search Customers`.`f2b3c4d5-e5f6-7890-1234-567890abcdef`}}",
"isKeyField": true,
"primitiveType": "string",
"complexType": "string"
},
{
"fieldId": "f3c4d5e6-e5f6-7890-1234-567890abcdef",
"value": "{{`Form`.`first_name`}} {{`Form`.`last_name`}}",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string"
},
{
"fieldId": "f4d5e6f7-e5f6-7890-1234-567890abcdef",
"value": "{{`Form`.`email`}}",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string"
},
{
"fieldId": "f5e6f7a8-e5f6-7890-1234-567890abcdef",
"value": "{{`Form`.`seats`}}",
"isKeyField": false,
"primitiveType": "number",
"complexType": "number"
},
{
"fieldId": "f6f7a8b9-e5f6-7890-1234-567890abcdef",
"value": "true",
"isKeyField": false,
"primitiveType": "boolean",
"complexType": "boolean"
}
]
},
{
"linkId": null,
"entityId": "e3c4d5e6-e5f6-7890-1234-567890abcdef",
"operation": "INSERT",
"mappings": [
{
"fieldId": "f7a8b9c0-e5f6-7890-1234-567890abcdef",
"value": "{{`Session metadata`.`__session_start_date`}}",
"isKeyField": false,
"primitiveType": "string",
"complexType": "datetime"
},
{
"fieldId": "f8b9c0d1-e5f6-7890-1234-567890abcdef",
"value": "customer_updated",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string"
},
{
"fieldId": "f9c0d1e2-e5f6-7890-1234-567890abcdef",
"value": {
"utc": "2026-03-15T14:30:00Z",
"timezone": "America/New_York"
},
"isKeyField": false,
"primitiveType": "date",
"complexType": "datetime"
}
]
}
]
}
]
}The next example inserts one Contact for each entry in the contacts array sent to an Incoming Webhook step named Incoming webhook. Every Contact also receives the same static source value.
{
"datasets": [
{
"datasetId": "ds3c4d5e-e5f6-7890-1234-567890abcdef",
"selectedSearchDataStep": null,
"stepDatasetInstanceId": "cd3e4f5a",
"entities": [
{
"linkId": null,
"entityId": "e4d5e6f7-e5f6-7890-1234-567890abcdef",
"operation": "INSERT",
"repeatableConfigs": [
{
"repeatableId": "contacts",
"collectionSourcePath": "{{`Incoming webhook`.`body.contacts`}}"
}
],
"mappings": [
{
"fieldId": "fa1b2c3d-e5f6-7890-1234-567890abcdef",
"value": "{{`Incoming webhook`.`body.contacts[].firstName`}}",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string",
"repeatableId": "contacts"
},
{
"fieldId": "fb2c3d4e-e5f6-7890-1234-567890abcdef",
"value": "{{`Incoming webhook`.`body.contacts[].email`}}",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string",
"repeatableId": "contacts"
},
{
"fieldId": "fc3d4e5f-e5f6-7890-1234-567890abcdef",
"value": "partner_import",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string"
}
]
}
]
}
]
}The last example inserts a Case and attaches the file uploaded in a form step named Form to it.
{
"datasets": [
{
"datasetId": "ds4d5e6f-e5f6-7890-1234-567890abcdef",
"selectedSearchDataStep": null,
"stepDatasetInstanceId": "ef5a6b7c",
"entities": [
{
"linkId": null,
"entityId": "e5e6f7a8-e5f6-7890-1234-567890abcdef",
"operation": "INSERT",
"mappings": [
{
"fieldId": "fd4e5f6a-e5f6-7890-1234-567890abcdef",
"value": "{{`Form`.`subject`}}",
"isKeyField": false,
"primitiveType": "string",
"complexType": "string"
}
],
"fileToEntityMappings": [
{
"fileRowId": "case-attachment",
"fileEntityId": "e6f7a8b9-e5f6-7890-1234-567890abcdef",
"fileLinkId": "l6f7a8b9-e5f6-7890-1234-567890abcdef",
"fileFieldMappings": [
{
"fieldId": "fe5f6a7b-e5f6-7890-1234-567890abcdef",
"value": "{{`Form`.`attachment`}}",
"isKeyField": false,
"primitiveType": "file",
"complexType": "file"
}
]
}
]
}
]
}
]
}Updated 21 days ago
