HTTP Request
Call an outside API over HTTPS and keep its response for later steps and conditions. Two things to know before using it today: placeholders in the URL and body are not resolved, and production had no host on its outbound allow-list at the time of writing — see Limits.
Getting here
Automate → Workflows, open a workflow, click + on the canvas, then pick HTTP Request under Add Steps.
Before you start
- An owner, admin or agent can add this step and save the workflow. Publishing that workflow — the thing that makes it run on live conversations — is an owner or admin action.
- Building and running workflows depends on your plan; see pricing.
- The destination must be a public HTTPS endpoint whose full URL you can type in — not a template, since placeholders here are not resolved; see Limits. In production, that host also needs to already be on the platform's outbound allow-list, which was empty at the time of writing (see Limits) — file a ticket under Settings → Help & support to ask for a host to be added.
Set up
- Open the workflow and click + where the call belongs.
- Pick HTTP Request.
- Choose GET or POST, and set the request URL — the drawer offers the variable picker here, but see Limits before relying on it.
- Optional: add Headers, and, on POST, a JSON Body — the drawer offers placeholders here too, with the same caveat.
- Set Save response as to name where the answer lands (default
http). - Save the step, then publish the workflow. A saved but unpublished workflow calls nothing.
Fields
- Method
- GET or POST.
- Default: POST
- Request URL
- The endpoint to call.
- Limits: Must start with
https://(checked when you save) and use the default port (checked only when the step runs). The variable picker is offered but{{…}}text is sent exactly as typed — see Limits. - Headers
- Extra request headers, as name/value pairs.
- Body (JSON · sent as application/json)
- The POST body, written as JSON.
- Limits: Shown only for POST. Same placeholder caveat as the URL.
- Save response as
- The name later steps use to read the response, e.g.
{{http.status}},{{http.data.tracking_no}}. - Default: http
- Limits: Give a second lookup on the same run its own name, or it overwrites the first.
How it works
- What leaves Inchat: the method, URL, headers and body exactly as saved on the step — with one significant exception.
{{…}}placeholders in the URL and the body are NOT resolved before the request is sent: they go out as the literal text{{answer.text}}, not the customer's actual answer. This is a product bug, not a design choice — the drawer's variable picker still offers them on both fields, implying they work. - A fixed
user-agent: InchatWorkflow/1.0header is always attached, in addition to anything set under Headers. - When it leaves: the instant this step runs in the flow, synchronously — the flow waits for the response (or a 10-second timeout) before moving to the next step.
- The response — its status code, its parsed JSON body under
.datawhen the response declares JSON, and the raw text under.text, capped at 32 KB — is written into the run's context under the name you gave Save response as BEFORE the step is judged to have succeeded or failed. A later step can read{{http.status}}or branch onhttp.okregardless of which way this step went. - A non-2xx response does not throw the response away: the step is recorded failed, but
{{http.status}}and whatever body came back are still there for the next step to read — so a workflow can ask a courier for a tracking number, get a 404, and have the next step say "we couldn't find that order" itself instead of the whole run dying silently. - A redirect (3xx) is refused rather than followed, and treated the same as a failed call — the URL must already be the final one; a hop this code did not check itself would defeat the checks below.
When it fails
- The URL does not start with
https://: the drawer refuses to save it with HTTP request URL must be https://…. A URL on a non-default port saves, then fails the run with non-default HTTPS ports are blocked. - The hostname literally matches a private or loopback pattern (
localhost,10.x,192.168.x,172.16–31.x,169.254.x,0.x,::1): the step fails immediately, nothing is sent. This is a pattern match on the hostname text, not a DNS lookup — a public domain name that happens to resolve to a private address is not caught here. - The host is not on Inchat's outbound allow-list, which production requires: the step fails before anything is sent, with host <host> is not on WORKFLOW_HTTP_ALLOWLIST or, while the list is empty, WORKFLOW_HTTP_ALLOWLIST is required for workflow HTTP requests. At the time of writing, the list was empty in production. Getting a host allowed needs the platform side changed — file a ticket under Settings → Help & support; there is no workspace setting for it.
- The endpoint answers with a redirect: the step fails with the endpoint redirected (<code>); point the action at the final URL.
- The endpoint answers with a 4xx or 5xx status: the step fails with HTTP <status>, and the response is still captured — see How it works.
- The request times out (10 seconds) or the endpoint cannot be reached at all: the step fails with the transport error.
- A failed call does not stop the run: the step is recorded failed and the flow moves straight to the next one, which can still read whatever the response bound into the context.
Limits
- `{{…}}` placeholders in the URL and the body are not resolved. Whatever you type there — including a variable picked from the picker — is sent character-for-character. A URL written as
…/track/{{answer.text}}calls that literal, percent-encoded string, not the customer's answer. There is no way around this today; do not rely on this step for anything that needs a per-conversation value in the URL or body. - At the time of writing, production's allow-list was empty, so every production run failed before sending anything. File a ticket under Settings → Help & support to ask for the allow-list to be populated.
- Only GET and POST ever reach a saved step — the schema that gates every save (drawer or AI builder alike) accepts nothing else, even though the underlying runtime also understands PUT and PATCH.
- The response is capped at 32 KB. Whether anything is kept past the cap depends on how the response arrived: if the server declares a Content-Length above the cap up front, nothing is read at all and both
.dataand.textare empty; if the body is read as it streams in and only crosses the cap partway through, the text read so far is kept in.text— only the parsed.datais withheld either way. - It never retries. One call, once, when the step runs — a flaky endpoint needs its own retry step (e.g. a Wait and a second HTTP Request) built into the flow.
- It carries no authentication of its own beyond what you put in Headers — there is no stored-credential picker the way Google Sheets has one.
- A redirect is always refused, even a same-host one — the endpoint must answer directly at the URL given.
Use cases
- Look up a courier's tracking status by a fixed, non-templated identifier, then read the status from
{{http.data.status}}— once its host is on the allow-list. - Post a fixed-shape notification to an outside system right after Move Deal to Stage marks a deal won — again, once the destination host is allow-listed.
Related
- Send Conversions API Event — Report a conversion — a lead, a purchase, a cart — to Meta's Conversions API from this conversation's channel, so ad optimisation can see what happened after the click.
- Add Google Sheets Row — Append one row to a connected Google Sheet — the cheapest way to hand data from a conversation to a team that lives in a spreadsheet.
- Conditions and variables — How a condition decides whether a workflow starts or which path a contact takes, and how a {{variable}} is filled into the text a workflow sends.
- Workflows: how a flow runs — A workflow is one trigger, optional conditions and an ordered list of steps; only a published workflow runs, and this article explains how a run starts, forks, pauses, fails and stops.
Reading this with an AI assistant? Plain Markdown version.