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

  1. Open the workflow and click + where the call belongs.
  2. Pick HTTP Request.
  3. Choose GET or POST, and set the request URL — the drawer offers the variable picker here, but see Limits before relying on it.
  4. Optional: add Headers, and, on POST, a JSON Body — the drawer offers placeholders here too, with the same caveat.
  5. Set Save response as to name where the answer lands (default http).
  6. 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.0 header 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 .data when 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 on http.ok regardless 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 .data and .text are 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 .data is 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.