---
title: "HTTP request step - Workflow Suite"
description: "Call any API or webhook URL from a workflow: method, headers, JSON body with Liquid, secrets for keys, and how later steps read the response."
canonical: "https://docs.workflow-suite.app/http-request"
---

# HTTP request

The **HTTP request** step calls any API or webhook URL: your ERP, your CRM, a shipping tool, your own backend. Later steps can read the answer.

## Set it up

1. Press **+** and pick **HTTP request**.
2. Choose the **Method**.
3. Enter the **URL**. It must start with `https://`, or be a variable or a secret that holds the URL.
4. Under **Headers**, select **Add header** for each header, for example `Content-Type` with `application/json`, and `Authorization`. Up to 30 headers.
5. For every method except GET, write the **Body**.

## Keep keys in secrets

Never type a token into a header. Save it on the **Secrets** page and reference it:

```liquid
Bearer {{ secrets.ORDER_API_TOKEN }}
```

The value is filled in when the step runs, is never stored with the run, and is masked in the step's output and in error messages. See [Secrets](https://docs.workflow-suite.app/secrets.md).

## Write a JSON body

The body is a Liquid template. In JSON, add the `json` filter to text values, so quotes and line breaks in the data stay valid JSON. The filter also adds the surrounding quotes:

```liquid
{
  "number": {{ event.payload.name | json }},
  "total": {{ event.payload.total_price | json }},
  "email": {{ event.payload.email | json }},
  "lines": [
    {% for line in event.payload.line_items %}
      { "sku": {{ line.sku | json }}, "quantity": {{ line.quantity }} }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}
```

To send a whole object as it is:

```liquid
{{ event.payload | json }}
```

More in [Liquid in every field](https://docs.workflow-suite.app/liquid-in-fields.md).

## Read the response

| Variable | Holds |
| --- | --- |
| `steps.<id>.output.status` | The HTTP status, for example 200 |
| `steps.<id>.output.body` | The response. A JSON response is parsed, so you can read its fields: `steps.<id>.output.body.id` |

Run a **Test** for real once, and the variable picker offers the real fields of the response.

## When it fails

A response that is not 2xx fails the step. What happens next depends on the kind of failure:

- **425, 429 and 503** mean the server did not work on the request. It is sent again, whatever the method.
- **A timeout, a broken connection, 408 and other 5xx answers** leave open whether the request arrived. Only GET, PUT and DELETE are sent again. A POST or PATCH that may have arrived is never sent twice.
- **Any other answer**, such as 400, 401 or 404, fails the step at once.

You set the number of tries under **If it fails**. See [Automatic retries](https://docs.workflow-suite.app/automatic-retries.md).

If the other system can handle it, make your POST requests safe to repeat on its side, for example with an idempotency key header built from the run:

```liquid
{{ run.id }}
```

> [!NOTE]
> **In a preview no request is sent**
> A Test as **Preview (nothing is changed)** does not send HTTP requests, not even a GET. The step shows the method, URL, headers and body it would have sent, with secrets masked. Choose **Run for real** to call the other system.

## Limits and safety

- Requests leave from a guarded sandbox, not from the app's own servers. Addresses inside private networks cannot be reached; the URL must be public.
- Large responses are better fetched as a file. See [Files, SFTP and downloads](https://docs.workflow-suite.app/files-sftp-and-downloads.md).

## Post JSON to a URL

For the common case there is a ready-made action, **Post JSON to a URL**: a **URL**, a **JSON body** and an optional **Authorization header**. It fails the step when the endpoint answers with an error status. Several data sync templates use it.

## Related

- [Recipe: send new orders to an ERP](https://docs.workflow-suite.app/recipe-send-orders-to-erp.md)
- [Incoming webhooks](https://docs.workflow-suite.app/incoming-webhooks.md) - the other direction.
- [Slack, Discord and Teams messages](https://docs.workflow-suite.app/slack-discord-teams.md)
