# HTTP Request

> Call any REST API from a workflow, with control over the method, URL, headers and payload.

The **HTTP Request** step calls an API that has no ready-made step in Glow. It sends exactly the method, URL, headers and payload you configure, and nothing else.

> Dock: Data · Dev tools · Returns: the API's response

Reach for it whenever a service you need has no Glow connector yet, or when the connector exists but the endpoint you want is not one of its actions. It also reaches your own systems, provided they are reachable from the internet: an endpoint on a private network or a `localhost` address is refused.

**Add it from Tools → Data → Dev tools on the canvas dock.** Searching the Apps panel for "HTTP" turns up a separate connector of the same name. This page describes the built-in step under Tools, which is the one to use.

---

## How it fits in a workflow

```mermaid
flowchart LR
    A[Webhook Trigger] --> B[Parse JSON] --> C[HTTP Request] --> D{Status 200?}
    D -->|Yes| E[Slack Success]
    D -->|No| F[Slack Error Alert]
```

---

## Setting it up

  
    ### Select the Method
    Choose the HTTP method required by the target API:
    - **GET:** Retrieve data from an API
    - **POST:** Create a new resource or submit data
    - **PUT / PATCH:** Update an existing resource
    - **DELETE:** Remove a resource
    - **HEAD / OPTIONS:** Inspect headers or verify CORS capabilities without downloading the body
  
  
  
    ### Define the URL
    Enter the full URL for the API endpoint (e.g., `https://api.example.com/v2/orders`).

    Inject values from earlier steps with `{{ }}`, referencing each step by the number shown on the canvas. For a field the trigger received, that gives you `https://api.example.com/orders/{{ 1.order_id }}`.

    Use the data selector beside the field rather than typing the path. What a step exposes varies by step type, and picking the value inserts the reference that actually resolves.

    **Query parameters have their own section.** You do not have to build a query string by hand. Add them as name/value pairs (or raw JSON) and Glow assembles the URL, handling URL encoding and nested keys (e.g., `filter[status]=active` or `ids[]=1&ids[]=2`) for you.

  

  
    ### Set Headers & Authentication
    **Authentication** is its own field, above the headers. Pick the type and fill in the value. Glow builds the header for you:

    | Type | What you supply |
    | ---- | --------------- |
    | **None** | Nothing. The default. |
    | **Bearer Token** | The token, e.g. `{{ $secret.API_TOKEN }}` |
    | **Basic Auth** | Username and password |
    | **API Key in Header** | The header name the service expects, and the key |

    Use **Headers** for everything else the API asks for: `Accept`, `Content-Type`, a request id. You only need to write an `Authorization` header by hand for a scheme none of the four types covers.

    Both **Headers** and **Query Parameters** can be filled in as name/value **Fields** or pasted wholesale as **JSON**. Use whichever matches what the API's own documentation gives you.

    > **Put credentials in [secrets](/manage/workspace-settings/secrets-and-variables), not in the header value.** A token typed directly into the field is visible to anyone who can open the workflow. It also travels with the workflow if that is shared or published as a template.

  

  
    ### Configure the Payload

    For methods that send data (POST, PUT, PATCH) configure the request body. **Body Type** offers:

    | Option                | Sends                                                        |
    | --------------------- | ------------------------------------------------------------ |
    | **JSON**              | `application/json` — the usual choice for REST APIs          |
    | **Form URL Encoded**  | `application/x-www-form-urlencoded` (`a=1&b=2`)              |
    | **Form Data**         | `multipart/form-data` for structured key-value form fields   |
    | **Text**              | `text/plain`, sent exactly as you write it                   |
    | **None**              | No body at all (sends `Content-Length: 0` for POST/PUT)      |

    **Form URL Encoded and Form Data are not the same thing.** If an API's documentation shows `a=1&b=2`, you want Form URL Encoded.

  

  
    ### Advanced Options & Timeout

    Configure behavior for slow or custom endpoints under **Advanced Options**:

    - **Timeout (seconds, 1-300):** How long the step waits before aborting. Defaults to **30 seconds**.
    - **Ignore HTTP Status Errors (4xx/5xx):** Treats non-2xx error codes as successful runs, passing the error payload downstream instead of stopping the run.
    - **Ignore SSL Certificate Issues:** Disables strict TLS/SSL certificate validation. Useful when connecting to internal staging servers, self-signed certificates, or testing environments.
    - **Include Full Response (status, headers, body):** Returns response headers and status codes alongside the body.

    > **Payload size limit:** Outbound responses are capped at **10 MB**. If an API returns a larger payload, the step halts with `OutboundResponseTooLargeError`.

  

### Skip the form: Import cURL

Most API documentation provides a `curl` command. Click **Import cURL**, paste the command, and Glow automatically configures the method, URL, query parameters, headers, authentication, and request body.

![The Import cURL dialog with a POST command pasted in, showing its headers and JSON body across eight numbered lines.](/images/docs/action-steps/import-curl.webp)
*Paste the command as the API's documentation gives it to you. Glow reads the method, URL, headers and body out of it.*

#### Examples to Copy & Import

**1. POST Request with JSON Body and Bearer Auth:**

```bash
curl -X POST https://api.getglow.ai/v1/leads \
  -H "Authorization: Bearer {{ $secret.API_KEY }}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "email": "lead@email.com",
    "name": "John Doe"
  }'
```

**2. GET Request with Query Parameters and Custom Header:**

```bash
curl -X GET "https://api.getglow.ai/v1/customers?status=active&limit=50" \
  -H "X-API-Key: {{ $secret.SERVICE_KEY }}" \
  -H "Accept: application/json"
```

> Importing a cURL command overwrites whatever is currently configured on the
> step. Import the cURL snippet first, then map any dynamic `{{}}` variables.

---

## What it passes on

The response is stored under `ret`. Glow automatically detects the response content type:

  
    ### Default JSON Output
    Parsed JSON sits directly under `ret`:
    ```json
    {
      "ret": {
        "id": 1042,
        "title": "Invoice #1042",
        "status": "paid"
      }
    }
    ```
    Access fields directly: `{{ 3.ret.id }}` or `{{ 3.ret.status }}`.
  

  
    ### Full Response (Status & Headers)
    When **Include Full Response** is enabled under Advanced Options, `ret` contains `body`, `headers`, and HTTP status codes:
    ```json
    {
      "ret": {
        "body": {
          "id": 1042,
          "title": "Invoice #1042"
        },
        "status": 200,
        "statusCode": 200,
        "statusMessage": "OK",
        "headers": {
          "content-type": "application/json; charset=utf-8",
          "x-ratelimit-remaining": "98"
        }
      }
    }
    ```
    Access fields with `{{ 3.ret.body.id }}` and status with `{{ 3.ret.status }}`.
  

  
    ### Binary & Non-Text Responses
    When downloading non-text files (PDFs, images, zip files), Glow encodes the binary buffer as Base64:
    ```json
    {
      "ret": {
        "data": "JVBERi0xLjQKJcfs...",
        "encoding": "base64",
        "contentType": "application/pdf",
        "fileName": "statement.pdf"
      }
    }
    ```
    This object can be handed directly to file upload steps or forwarded to external APIs.
  

> **Run the step once and read the Executions tab** rather than working the path
> out from the API's own documentation. What Glow stores is the shape you
> reference, and one look settles it.

---

## Troubleshooting & Error Handling

> **When the API answers with an error**
>
> Any non-2xx status, such as `400 Bad Request` or `500 Internal Server Error`, is treated as a failure and halts the workflow. Three settings change that:
>
> - **Ignore HTTP Status Errors (4xx/5xx)**, in the step's own **Advanced Options**, turns an error status into an ordinary result. The step passes on the response body instead of failing. Use it when a `404` is a real answer ("no such customer") rather than a fault. Pair it with **Include Full Response** so a [Condition](/build/action-steps/conditions) can read the status and decide what it meant.
>
> The remaining two are in the step's **Test & Debug** tab:
>
> - **Retry on fail** repeats the request before giving up. Off by default, so a `429` or `5xx` fails the run on first response unless you turn it on. See [Error Handling](/build/core-concepts/error-handling).
> - **If this step fails → Continue** lets the run carry on so you can handle the failure yourself. Follow it with a [Conditions](/build/action-steps/conditions) step checking `{{ 3.ret.status }}`, replacing `3` with this step's number. That reference needs **Include Full Response** turned on. Without it the step returns only the body and there is no status to test.

### Common Errors

| Code    | Meaning           | What to Do                                                                                |
| :------ | :---------------- | :---------------------------------------------------------------------------------------- |
| **401** | Unauthorized      | Verify your authentication credentials in the headers.                                    |
| **403** | Forbidden         | Confirm you have permission to access the requested resource.                             |
| **404** | Not Found         | Check the URL structure and verify any dynamically injected variables (like `id`).        |
| **429** | Too Many Requests | You have hit an API rate limit. Add a **Wait** step before the request to throttle calls. |

## Top Real-World Recipes

  
    ### Post Lead to Custom API
    Send clean dynamic data from an earlier step (e.g. step 1) to an internal endpoint:

    - **Method:** `POST`
    - **URL:** `https://api.yourcompany.com/v1/leads`
    - **Auth:** `Bearer Token` → `{{ $secret.CRM_API_KEY }}`
    - **Body (JSON):**
    ```json
    {
      "email": "{{ 1.email }}",
      "first_name": "{{ 1.first_name }}",
      "company": "{{ 1.company_name }}",
      "source": "glow_workflow"
    }
    ```

  

  
    ### Call an API for Each Item in a List
    When running in **Run for each item** mode (or inside a [Repeater](/build/action-steps/loops/repeater)), reference the current item using `{{ item }}`:

    - **Method:** `PATCH`
    - **URL:** `https://api.example.com/v2/contacts/{{ item.id }}`
    - **Body (JSON):**
    ```json
    {
      "status": "synchronized",
      "last_updated": "{{ $now }}"
    }
    ```
    Every row in the incoming list executes an isolated HTTP call.

  

  
    ### Forward Entire Webhook Payload
    To forward an entire incoming event without picking individual fields, use `$full_result`:

    - **Method:** `POST`
    - **URL:** `https://webhook.site/your-endpoint`
    - **Body (JSON):**
    ```json
    {
      "event_type": "typeform_submission",
      "timestamp": "{{ $now }}",
      "raw_payload": "{{ 1.$full_result }}"
    }
    ```

  

  
    ### Fetch OAuth 2.0 Access Token
    Authenticate using `client_credentials` with **Form URL Encoded** body:

    - **Method:** `POST`
    - **URL:** `https://auth.provider.com/oauth/token`
    - **Body Type:** `Form URL Encoded`
    - **Fields:**
      - `grant_type`: `client_credentials`
      - `client_id`: `{{ $secret.CLIENT_ID }}`
      - `client_secret`: `{{ $secret.CLIENT_SECRET }}`

    The response token will be available in downstream steps as `{{ 2.ret.access_token }}`.

  

---

## What's Next?

- **[Parse JSON](/build/action-steps/parse-json)**: Turn raw text or nested strings into addressable fields.
- **[Error Handling & Retries](/build/core-concepts/error-handling)**: Configure automatic retries on 429/5xx status codes.
- **[Secrets & Variables](/manage/workspace-settings/secrets-and-variables)**: Securely manage API tokens and environment endpoints.
