Docs / Strand / nodes/http-request

HTTP Request Node

The HTTP Request node makes HTTP requests to external APIs.

The HTTP Request node's Configuration: method, URL, headers, and body. Any field here accepts Jinja, so {{ vault.api_token }} in a header keeps the secret out of the node.

Overview#

HTTP Request nodes allow you to call external APIs, webhooks, and HTTP endpoints from your workflows.

Use Cases
  • Call REST APIs
  • Send webhooks
  • Fetch data from external services
  • Integrate with third-party services

Configuration#

Field Type Required Description
url string Yes* Full request URL (supports templating)
endpoint string No Path appended to connector base URL
method string No HTTP method (default: POST)
headers object No Request headers (values support templating)
body string/object No Request body (supports templating)
body_type string No Body format: json, form_data, form_urlencoded, raw, xml, binary (default: json)
query_params object No URL query parameters (supports templating)
path_params object No URL path parameter replacements
connector_id string No Use a saved HTTP connector
timeout number No Request timeout in seconds, 1-300 (default: 30)
follow_redirects boolean No Follow HTTP redirects (default: true)
verify_ssl boolean No Verify SSL certificates (default: true)
retry object No Retry configuration (see below)
URL vs Connector
  • Use url for direct API calls
  • Use connector_id + endpoint for saved connectors with authentication

URL Configuration#

Direct URL#

jinja

https://api.example.com/users/{{ payload.user_id }}

Using Connector#

When using a connector, specify the endpoint instead of full URL:

jinja

/users/{{ payload.user_id }}/profile

The connector provides the base URL and authentication.

HTTP Methods#

Method Use Case Body Required?
GET Retrieve data No
POST Create resources Usually
PUT Update resources Usually
PATCH Partial updates Usually
DELETE Delete resources No

Headers#

Headers support templating in their values:

json

{
  "Authorization": "Bearer {{ vault.api_token }}",
  "Content-Type": "application/json",
  "X-User-ID": "{{ payload.user_id }}"
}
Sensitive Headers

For sensitive values like API tokens, use the Global Vault instead of Workflow Variables. Headers are also automatically encrypted when using connectors.

Request Body#

JSON Body#

json

{
  "user_id": "{{ steps.user_lookup.output_payload.id }}",
  "message": "{{ payload.message }}",
  "timestamp": "{{ meta.received_at }}"
}

String Body#

jinja

{{ payload | tojson }}

Using Previous Steps (Direct Connection)#

When directly connected, use payload:

json

{
  "data": {{ payload | tojson }},
  "metadata": {
    "source": "{{ initial.meta.trigger_source }}"
  }
}

Using Non-Direct Steps#

When accessing data from a non-directly connected node:

json

{
  "data": {{ steps.process.output_payload | tojson }},
  "metadata": {
    "source": "{{ initial.meta.trigger_source }}"
  }
}

Query Parameters#

Add query parameters to the URL:

json

{
  "page": "{{ payload.page | default(1) }}",
  "limit": "50",
  "filter": "{{ payload.status }}"
}

Results in: ?page=1&limit=50&filter=active

Path Parameters#

Replace placeholders in the URL with dynamic values:

json

  {
    "user_id": "{{ payload.user_id }}",
    "order_id": "{{ payload.order_id }}"
  }

Body Types#

The body_type field controls how the request body is formatted:

Body Type Content-Type Use Case
json application/json REST APIs (default)
form_urlencoded application/x-www-form-urlencoded Form submissions
form_data multipart/form-data File uploads
raw Custom Raw text or custom formats
xml application/xml SOAP/XML APIs
binary Custom / caller-set Raw bytes (e.g. base64-decoded payloads)

Retry Configuration#

Configure automatic retries for transient failures:

json

{
  "retry": {
    "enabled": true,
    "max_attempts": 3,
    "backoff_type": "exponential",
    "backoff_delay": 1,
    "backoff_max": 30,
    "retryable_status_codes": [429, 500, 502, 503, 504]
  }
}
Field Type Description
enabled boolean Enable retries
max_attempts number Max retry attempts (default: 3). Accepts 1-10 in config, but the runtime caps effective attempts at 5 and reduces further so attempts × timeout fits the run deadline — see Limits.
backoff_type string exponential, linear, or fixed
backoff_delay number Initial delay between retries in seconds
backoff_max number Maximum delay between retries in seconds
retryable_status_codes array HTTP status codes that trigger a retry

Response#

The HTTP Request node outputs:

Accessing Response#

jinja

{{ steps.api_call.output_payload.data }}
{{ steps.api_call.output_meta.status_code }}

Response options#

A response object on the node tunes how the reply is judged and parsed:

Field What it does
expected_status_codes Which statuses count as success. Defaults to 200-299, which is what sets success in the envelope
error_on_status Statuses that should raise a hard node failure instead of returning an envelope. Empty by default, which is why a 4xx never halts a branch on its own
parse_as How to read the body: auto (default), json, text
extract_fields Pull named fields out of the parsed body instead of returning the whole thing
json

{
  "response": {
    "expected_status_codes": [200, 201],
    "error_on_status": [500, 502, 503]
  }
}

Error Handling#

A 4xx or 5xx response is not a node failure. The node returns the same { success, status, data } envelope a connector does (see Connector Output Structure), with success set to false, and downstream edges are traversed normally. Route on the envelope with an If/Else Logic node:

jinja

{{ payload.success }}

The if handle handles success; the else handle handles failure. See Conditional Logic.

Examples#

GET Request#

Configuration:

POST Request with Body (Direct Connection)#

Configuration:

json

  {
    "to": "{{ payload.email }}",
    "subject": "Welcome!",
    "body": "Hello {{ payload.name }}"
  }
Direct Connection

Since this HTTP Request node is directly connected to the previous node, use payload instead of steps.node_id.output_payload.

Using Connector#

Configuration:

The connector provides base URL and authentication automatically.

Best Practices#

Tips
  1. Use connectors for APIs requiring authentication
  2. Store API tokens in the Global Vault, not hardcoded or in Workflow Variables
  3. Use templating for dynamic URLs and data
  4. Branch on failures by routing {{ payload.success }} through a Logic node
  5. To make specific statuses raise and halt the branch instead, list them in the node's response.error_on_status
  6. Check response status codes in conditions
  7. Test with sample data before deploying