Skip to main content
The HTTP Request step, in the flow builder’s Actions group, calls a URL of yours in the middle of a conversation, to look something up in your own system, push a lead into a tool DMLY has no connector for, or notify a backend that a step was reached. It sends one request, optionally saves fields from the JSON reply, and the flow moves on. It is the mirror image of workspace webhooks: those push events to your endpoint whenever they happen anywhere in the workspace; this step fires only when a contact walks through this exact point in this flow.

The fields

Variables only work in the body. Any {{token}} in the JSON body is substituted per contact before sending. See the variables reference. The URL and the headers are sent exactly as typed: a {{token}} there is not replaced, so don’t build per-contact URLs or per-contact header values.
The Send test request button in the step’s panel shows a canned demo response. The panel says so itself: “Demo response — live requests run when the flow engine is enabled.” It does not call your endpoint. To test for real, publish the flow, walk through it, and watch your endpoint’s logs and Logs.

Using the response

Each Save response to fields row plucks one value out of the JSON reply by its path (dots reach into nested objects, so data.id reads {"data": {"id": …}}) and saves it as a flow variable under the field name you chose. From the next step onward, use it like any other token: name the field crm_id and write {{crm_id}} in a later message. Two boundaries to know:
  • The saved value lives in this run of the flow only. It is not written to the contact, and the next conversation starts without it. To keep something permanently, have your endpoint write it back through the REST API.
  • A path that doesn’t exist in the reply (or a reply that isn’t JSON) saves nothing, and the token resolves to empty text later. Nothing errors.
Two tokens you always get. Whatever you map, or don’t, the step leaves {{_last_http_status}} and {{_last_http_error}} behind for the rest of the run. They aren’t in the builder’s {} picker, so type them by hand. {{_last_http_status}} is the HTTP status your endpoint returned (200, 404, 500), or 0 when the request never got a response: a timeout, an unreachable host, or a body DMLY couldn’t render as JSON. {{_last_http_error}} carries the reason in that 0 case, either the network error text or invalid_json_body. A successful response doesn’t rewrite {{_last_http_error}}, so if an earlier HTTP Request step in the same run set it, the old text is still sitting there; only read it alongside a {{_last_http_status}} of 0. Neither token is set when the URL is refused outright, because that stops the run.
A Condition step can’t branch on these. Conditions compare a fixed list of contact and trigger fields, and none of those fields reads a variable a step saved. To see the value at all, print it somewhere a later step writes: a Send Slack message step, or a Send to Google Sheets row next to {{flow_run_id}}.

When the call fails, the flow does not

The step has a single output, and the run continues through it whatever happens: a timeout, an unreachable server, a 500, a 404. The conversation is never held hostage by your endpoint: the contact just moves to the next step, with any unsaved response fields left empty. This is about calls that were actually made. A URL the step refuses to call isn’t a failed call, it stops the run: see What it refuses to call. If a call silently “did nothing”, check Logs and your endpoint’s own logs. Three lines are worth searching for:
  • HTTP Request rejected by the endpoint, with the status. Your endpoint answered and said no.
  • HTTP Request failed, with the error text. The request never reached a reply: a timeout, a DNS failure, a refused connection.
  • HTTP Request body is not valid JSON. Nothing was sent at all; see below.
The step waits at most 5 seconds for a response (3 to connect). An endpoint that needs longer should acknowledge immediately and do the slow work after replying.

What it refuses to call

The URL must be a public http:// or https:// address on the open internet. Requests to localhost, private network addresses and other reserved ranges are blocked outright, and unlike an ordinary network error, a blocked URL fails the run: the contact’s run stops at that step and shows as failed in the automation’s analytics and in Logs. If your endpoint lives on an office network or a dev machine, publish it to the internet (a tunnel works) before pointing a flow at it. Anything that isn’t an http(s) address at all is refused the same way, and fails the run the same way: an empty Endpoint URL, free text, or the bare https:// a freshly added step starts out with.

An empty URL publishes anyway

Publishing never checks this step’s URL. A missing or malformed endpoint only shows as an amber Needs attention badge on the node (Endpoint URL is missing or not http(s).), and a freshly added step wears that badge from the start, because its URL box begins as just https://. The badge also flags Body is not valid JSON. Clear both before you publish; nothing else will stop you. See Publish a flow. Neither badge is cosmetic, though, and at runtime the two behave in opposite ways:
  • A URL still left as https://, empty, or not an http(s) address fails the whole run when a contact reaches the step, exactly like a blocked address does. See What it refuses to call.
  • A body that can’t be rendered as JSON sends nothing at all, not an empty request. DMLY writes HTTP Request body is not valid JSON to Logs and the run carries on through the step’s single output, with the response fields empty and {{_last_http_error}} set to invalid_json_body.
The badge’s JSON check is stricter than the engine. It runs a plain JSON parse on what you typed, so a body with a token outside the quotes, like {"qty": {{count}}}, wears the badge even though the step renders and sends it correctly. If your body only “fails” because of a numeric token, the badge is the thing that’s wrong, not your flow.

Variables reference

Every token you can put in the JSON body.

Workspace webhooks

Event push for everything that happens in the workspace, no flow required.

Connect n8n

Point this step (or workspace webhooks) at an n8n workflow.

Build a flow

The canvas this step lives on.