Skip to content
Expedify
Actions — making things happen

Module · The outside world

API Request

Lesson 21 of 21 · 9 min

Twenty nodes in this path talk to systems somebody built a node for. This one talks to everything else: your warehouse software, a partner's ordering system, an internal service, a payment provider, the API of a product that will never have an Expedify integration because eleven companies use it.

It is the escape hatch, and it is the node you will use more than you expect. Learn it properly and no integration gap ever fully blocks you.

The request

Ten of twenty. The rest are the auth credentials, per-field source switches and proxy settings.

url

What it holds
Request URL (supports variable substitution)

method

What it holds
HTTP method One of: GET · POST · PUT · PATCH · DELETE · HEAD · OPTIONS Defaults to GET.

headers

What it holds
Request headers

body

What it holds
Request body content

body_content_type

What it holds
Content type for request body One of: json · form · text · xml Defaults to json.

auth_type

What it holds
Authentication type One of: none · basic · bearer · api_key Defaults to none.

timeout

What it holds
Request timeout in seconds Defaults to 30.

max_retries

What it holds
Maximum number of retry attempts Defaults to 3.

retry_delay

What it holds
Delay between retry attempts in seconds Defaults to 1.

output_mapping

What it holds
Mapping for output fields

If you have used any HTTP client this is familiar: a URL, a method, headers, a body. Everything is templatable, including the URL — which is how one node serves every record rather than one.

auth_type covers the four common cases — none, basic, bearer, and an API key — and the credential fields sit alongside it. output_mapping reshapes the response before it leaves the node, which is worth using when an API returns something deeply nested and every downstream reference would otherwise be four levels deep.

A worked example

A deal changes and the fulfilment system is told. Both outcomes are wired, because an external system that is down is not a hypothetical.

Post it, and handle both answers

success creates a note; error creates a task for a person.

SuccessError

Scroll for all 4 steps →

Notice what is missing from that node. It was built with a bearer token, and the token is not in the snapshot — the tooling that captures these workflows strips credentials and records that it did. That is the right instinct to copy: a workflow definition gets exported, shared and pasted into support tickets, and a token in one is a token in all of them.

This node has two exits and you should use both. The success path writes a note; the error path creates a task for a human. Most nodes in this course fail by returning success and doing nothing, and the recurring advice has been to check a count or a length. This one is different — it decides from the HTTP status and takes the error branch honestly. Leaving that branch empty wastes the one node that tells you the truth.

What counts as success

A 2xx status. Anything else — 400, 401, 404, 500 — is a failure, and the run leaves down the error path with the status code and whatever the server said available to read.

{{alias.status_code}}

What you get
The HTTP status. The first thing to put in any error message you write.

{{alias.response_data}}

What you get
The parsed body. JSON becomes an object you can reach into; text stays text.

{{alias.response_headers}}

What you get
The headers — where pagination cursors and rate-limit budgets live.

{{alias.runtime_ms}}

What you get
How long it took. Worth logging when an integration starts feeling slow.

The retries, and the danger in them

The node retries automatically, three times by default, but only for the failures where retrying makes sense: a 5xx, meaning the server broke, and a 429, meaning you are going too fast. Delays double each attempt, and a Retry-After header is respected if the server sends one.

A 4xx is never retried, which is correct — a 401 is not going to authenticate on the second attempt, and a 400 will be just as malformed.

Nothing distinguishes a POST from a GET. A write that returns 500 is retried like a read. If the server actually processed your order and then failed while replying, you have just sent it again — up to four times. Duplicate orders, duplicate charges, duplicate tickets, all from a workflow that looks correct.

Two ways out, and you want one of them on every write:

  • Send an idempotency key. Most APIs worth integrating accept a header that makes repeated identical requests safe. Put a stable value in it — the deal id, not a random one — and retries become harmless.
  • Set max_retries to zero on non-idempotent writes, and handle the failure on the error path instead. A task for a person is better than a duplicate order.

Reads are the opposite: leave retries on, and raise them if the API is flaky. There is no cost to fetching something twice.

What breaks

A 200 does not mean it worked. Plenty of APIs return 200 with a body saying the operation failed — {"status": "error"} and a message. The node sees a 2xx, reports success and takes the success branch. When you integrate a new API, read its documentation for this pattern specifically, and if it does that, add a Condition on {{alias.response_data}} after the node.

The timeout is a promise you make, not one the server makes. Thirty seconds by default, and a workflow that waits thirty seconds per call is slow if it is inside a Loop over two hundred records. Lower it for anything in a loop, and remember a timeout counts as a failure and therefore as a retry.

Credentials in a node are credentials in an export. Prefer a stored integration where one exists. Where it does not, know that the token is in the workflow definition, and treat rotating it as part of the same job as changing it anywhere else.

Templating into a JSON body needs care. A value containing a quotation mark or a newline breaks the body it is pasted into, and the API returns a 400 you will spend an hour on. If a field could contain arbitrary text — a note, a customer's message, an address — build the payload in a Transform Data node first and send the result.

Try it

  1. Call a public API with GET and no authentication — a weather or exchange-rate endpoint. Read {{alias.status_code}} and {{alias.response_data}}.
  2. Point the same node at a URL that returns 404 and confirm the run leaves down the error path rather than continuing.
  3. Wire something real to that error path. A task assigned to yourself is enough — the habit matters more than the destination.
  4. Set timeout to 1 against a slow endpoint and watch the retries in the execution log, then set max_retries to 0 and compare.
  5. Template a value containing a quotation mark into a JSON body and read the 400 that comes back. Then fix it properly and remember the shape of that error.

Next: that is the Actions path finished — twenty-one nodes. What follows is AI and the Knowledge Base, where the workflow stops following instructions and starts deciding.