Outbound Webhook Step

Send HTTP requests to external endpoints during a workflow, and optionally capture the response so you can map values into later steps.

The Outbound Webhook step sends an HTTP request to an external URL while a workflow runs. Use it to notify another system, create or update a record in a third-party API, or upload a file. You can run the request in the background, or wait for a response and pass response data to steps that follow.

For mapping placeholder syntax, see Mapping.

Waiting for a response

Set waitForResponse to true if the workflow should pause until the HTTP call finishes. When the external service returns a body (and a content type is present), Streamline stores that response so later steps can map values from it. response.statusCode is always available as a numeric field when the response is captured.

For JSON responses, the body is flattened into dot-notation paths that start with body. (for example, body.id or body.user.email). Non-JSON bodies, or JSON that fails to parse, are exposed as a single string field named body.

If waitForResponse is false, the workflow does not capture the HTTP response for mapping into later steps.

Continue on error

When continueOnError is true, HTTP error status codes (4xx/5xx) or network failures do not stop the workflow. The step can finish with a completed-with-errors state instead of failing the run. Default is false (failures stop the step).

Configuration

nametyperequireddescription
requestobjectyesThe HTTP request to send. See Request below.
waitForResponsebooleannoWhen true, the workflow waits for the HTTP response before continuing. Required if later steps should map response values. Default: false.
continueOnErrorbooleannoWhen true, the workflow continues when the request fails or returns an error status. Default: false.
listeningModeEnabledbooleannoWhen true, the next test request captures the response for field extraction. Streamline resets this to false after extraction completes. Default: false.
requestPayloadstringnoString snapshot of the outbound request. Streamline sets this when a test succeeds; you can also set it when updating the project. Field extraction reads this together with responsePayload.
responsePayloadstringnoString snapshot of a sample response body. Streamline sets this when a test succeeds; it feeds field extraction. Default: empty string.
mappableFieldsarraynoField descriptors for mapping into later steps. See Mappable fields. Default: empty array.

Request

The request object defines the HTTP call.

nametyperequireddescription
methodstringyesHTTP method: GET, POST, PUT, or DELETE.
urlstringyesEndpoint URL. Path placeholders use the :name form (for example :userId); supply values in pathParams.
authenticationobjectyesAuthentication settings. See Authentication below.
pathParamsarraynoPath parameter values. Each item has key and value (values support mapping).
queryParamsarraynoQuery string parameters. Each item has key and value (values support mapping).
headersarraynoCustom HTTP headers. Each item has key and value (values support mapping). Header names are normalized to lowercase.
bodyobjectvariesRequest body. See Body modes. Required for POST and PUT. Optional for DELETE. Not used for GET.

Authentication

nametyperequireddescription
typestringyesNONE (no authentication) or AUTHENTICATED (use a stored connection).
connectionIdstringyesID of the stored connection when type is AUTHENTICATED. Use null when type is NONE.

Body modes

The shape of body is determined by requestMode.

RAW

Send JSON or plain text. String values support mapping placeholders.

nametyperequireddescription
requestModestringyesMust be RAW.
contentTypestringyesJSON or TEXT.
contentstring or objectnoBody content. For JSON, either a string or an object whose string values support mapping.

MULTIPART

Send multipart/form-data. Each part is either text (string value) or a file resolved from a file reference or mapping placeholder.

nametyperequireddescription
requestModestringyesMust be MULTIPART.
contentarrayyesForm fields: each item has key and value (values support mapping).

RAW_BINARY

Send a single file as the entire request body.

nametyperequireddescription
requestModestringyesMust be RAW_BINARY.
rawBinaryFilevariesyesA file reference or a mapping placeholder (e.g. {{Form.uploadedDocument}}). See File object.

File object

Use when referencing a file by ID or download URL (instead of only a mapping placeholder).

nametyperequireddescription
idstringyes (variant A)File identifier. Use either id or downloadUrl, not both.
downloadUrlstringyes (variant B)File download URL. Use either id or downloadUrl, not both.
namestringyesFile name.
metadataobjectnoOptional: contentType, size, createdAt, updatedAt.

Mappable fields

mappableFields declares which response properties later steps can map and supplies type hints. Each key must match the flattened JSON path your endpoint returns, without the body. prefix (for example id or user.email, not body.id).

Supported type values include: string, number, boolean, date, datetime, object, array, and file.

nametyperequireddescription
keystringyesFlattened JSON key without the body. prefix (e.g. status, user.email).
labelstringyesHuman-readable label for the field.
typestringyesData type (see list above).
exampleValuevariesnoOptional example value (string, number, boolean, or null) stored with the field and shown in Streamline where sample values are displayed.

Populating mappable fields

mappableFields is a regular configuration property — you can populate it automatically from a test request, or write the array directly when you update the project.

Option A: Extract from a test request

To derive fields from a real HTTP call, use the outbound webhook test endpoint. Append ?test=true to the step's webhookSessionStartUrl from the project response:

POST {webhookSessionStartUrl}?test=true

Use the same authentication as for other /v1/sessions requests (bearer token). The body is a JSON array of objects with id, type, and sampleValue for each mapped input the test request should resolve; send [] when there are no mapped inputs. A successful response includes responsePayload, requestPayload, and extractedFields. On your next project update, persist extractedFields as mappableFields, and persist responsePayload and requestPayload so field extraction has both snapshots.

Option B: Set mappable fields directly

If you already know the response structure, you can include mappableFields in the step configuration when you create or update the project via PATCH /v1/projects/{projectId}:

PATCH /v1/projects/{projectId}

{
  "workflow": {
    "steps": [
      {
        "type": "outbound_webhook",
        "description": "Notify CRM",
        "config": {
          "request": { "..." : "..." },
          "waitForResponse": true,
          "mappableFields": [
            { "key": "id", "label": "User ID", "type": "string" },
            { "key": "status", "label": "Status", "type": "string" }
          ]
        },
        "edges": []
      }
    ]
  }
}

Customizing after extraction

Whether fields were extracted automatically or written directly, you can modify them at any time by updating the project. Add fields, remove fields, rename labels, or change types — then update the step's mappableFields array in the project. Later steps that reference these fields by key use whatever is currently stored on the step.

Examples

Simple GET with no authentication or body:

{
  "request": {
    "method": "GET",
    "url": "https://api.example.com/users",
    "authentication": { "type": "NONE", "connectionId": null }
  }
}

POST with a raw JSON body (string form):

{
  "request": {
    "method": "POST",
    "url": "https://api.example.com/webhook",
    "authentication": { "type": "NONE", "connectionId": null },
    "body": {
      "requestMode": "RAW",
      "contentType": "JSON",
      "content": "{\"message\": \"Hello\"}"
    }
  }
}

POST with connection auth, path/query parameters, JSON object body with mappings, and response mapping:

{
  "request": {
    "method": "POST",
    "url": "https://api.example.com/users/:userId",
    "authentication": { "type": "AUTHENTICATED", "connectionId": "my-api-connection" },
    "pathParams": [
      { "key": "userId", "value": "{{`Form`.`userId`}}" }
    ],
    "queryParams": [
      { "key": "format", "value": "json" }
    ],
    "headers": [
      { "key": "X-Custom-Header", "value": "custom-value" }
    ],
    "body": {
      "requestMode": "RAW",
      "contentType": "JSON",
      "content": {
        "name": "{{`Form`.`userName`}}",
        "email": "{{`Form`.`userEmail`}}",
        "metadata": {
          "source": "workflow",
          "requestId": "{{`Form`.`requestId`}}"
        }
      }
    }
  },
  "waitForResponse": true,
  "mappableFields": [
    { "key": "id", "label": "User ID", "type": "string", "exampleValue": "usr-12345" },
    { "key": "status", "label": "Status", "type": "string", "exampleValue": "created" }
  ]
}

Multipart POST with form fields:

{
  "request": {
    "method": "POST",
    "url": "https://api.example.com/submit",
    "authentication": { "type": "NONE", "connectionId": null },
    "body": {
      "requestMode": "MULTIPART",
      "content": [
        { "key": "name", "value": "{{`Form`.`userName`}}" },
        { "key": "description", "value": "Static description" }
      ]
    }
  }
}

Binary file upload with a file object:

{
  "request": {
    "method": "POST",
    "url": "https://api.example.com/upload",
    "authentication": { "type": "AUTHENTICATED", "connectionId": "file-api" },
    "body": {
      "requestMode": "RAW_BINARY",
      "rawBinaryFile": {
        "id": "file-123",
        "name": "document.pdf",
        "metadata": {
          "contentType": "application/pdf",
          "size": 1024000
        }
      }
    }
  }
}

Binary file upload with a mapping placeholder:

{
  "request": {
    "method": "PUT",
    "url": "https://api.example.com/files",
    "authentication": { "type": "NONE", "connectionId": null },
    "body": {
      "requestMode": "RAW_BINARY",
      "rawBinaryFile": "{{`Form`.`uploadedDocument`}}"
    }
  }
}

DELETE with an optional body:

{
  "request": {
    "method": "DELETE",
    "url": "https://api.example.com/resources/:resourceId",
    "authentication": { "type": "AUTHENTICATED", "connectionId": "api-connection" },
    "pathParams": [
      { "key": "resourceId", "value": "{{`Form`.`resourceId`}}" }
    ],
    "body": {
      "requestMode": "RAW",
      "contentType": "JSON",
      "content": "{\"reason\": \"cleanup\"}"
    }
  }
}