> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# HTTP Client Action

> Reference for the HTTP Client workflow action: request timeout, transport and job retries, success criteria, SSRF filtering, and signed request verification.

The **HTTP Client** action sends an outbound HTTP request to any REST API as a workflow step. It is the escape hatch for anything Rootly does not have a dedicated action for — calling an internet-reachable service, triggering a deploy, updating a system of record. It cannot reach services on a private network; see [SSRF Filtering](#ssrf-filtering) below.

Because it calls systems Rootly knows nothing about, its behavior under failure matters more than most actions. This page is the contract: how long it waits, when it retries, what counts as success, and how the receiving service can prove the request came from Rootly.

***

## Action Fields

These split into two groups, and the distinction matters if you are writing the receiver: only the first group reaches your endpoint.

**Sent in the request:**

| Field     | Purpose         |
| --------- | --------------- |
| `method`  | HTTP verb       |
| `url`     | Destination URL |
| `headers` | Request headers |
| `body`    | Request body    |

**Evaluated or recorded by Rootly, never sent:**

| Field               | Purpose                                          |
| ------------------- | ------------------------------------------------ |
| `succeed_on_status` | Which response statuses Rootly counts as success |
| `event_url`         | Link recorded on the incident timeline           |
| `event_message`     | Message recorded on the incident timeline        |

***

## Timeout

Each request is given **30 seconds**. A request still open at 30 seconds is abandoned and treated as a failed attempt.

If your endpoint does real work before responding, acknowledge the request immediately and do the work asynchronously. An endpoint that takes 45 seconds to finish will never report success to Rootly, no matter how well it eventually completes.

***

## What Counts as Success

`succeed_on_status` defines which response statuses are treated as success. It defaults to `"200"`.

You can use `x` as a wildcard digit, so a range is expressed as a pattern rather than a list:

| Value | Matches          |
| ----- | ---------------- |
| `200` | 200 only         |
| `2xx` | any 2xx response |
| `20x` | 200–209          |

Set this deliberately. With the default, an endpoint that correctly answers `201 Created` or `204 No Content` is recorded as a failure and retried — the request succeeded and the workflow says otherwise.

***

## Retries

Retries happen at two levels, and they cover different failures.

### Transport retries

A request that fails to complete — connection refused, DNS failure, timeout — is retried **twice**, with exponential backoff starting at 1 second and doubling. This happens regardless of configuration; you do not switch it on.

### Job retries

A completed request whose status is **429 Too Many Requests** can be retried at the job level, up to **4 times**.

<Warning>
  **Job retries default to 0 — they are off unless you turn them on.** Out of the box, a 429 fails the step immediately; the transport retries above do not cover it, because the request completed successfully and returned a status.

  If you are calling a rate-limited API, set this deliberately. Assuming the default is non-zero is the easy mistake, and it surfaces as a workflow that fails only under load.
</Warning>

When you do enable them, the retry count is **1 to 4** and the wait between attempts is **1 to 15 seconds**, both set on the action.

`Retry-After` interacts with your configured wait in a way worth knowing:

| Response `Retry-After` | What Rootly waits                                        |
| ---------------------- | -------------------------------------------------------- |
| Absent                 | Your configured wait                                     |
| 90 seconds or less     | **The longer** of your configured wait and `Retry-After` |
| More than 90 seconds   | Your configured wait — the header is **ignored**         |

<Warning>
  A `Retry-After` above 90 seconds is not capped at 90. It is discarded, and Rootly retries after your configured wait instead — a few seconds.

  If your service needs a long backoff, do not rely on `Retry-After` to deliver it. Keep refusing with 429 until you are ready, or return a status outside `succeed_on_status` so the step fails and the workflow stops rather than hammering you.
</Warning>

Only 429 triggers a job retry. Any other status that falls outside `succeed_on_status` — a 500, a 403, a 404 — fails the step without retrying. If your service signals overload with a 503, Rootly will not back off and try again; return a 429 for that case.

<Warning>
  Retried requests are byte-identical to the original, including the body, and **Rootly sends no idempotency key**. Make your endpoint idempotent yourself, or a retry after a slow success will apply the same change twice.

  **Do not deduplicate on the `X-Rootly-Signature` header.** Each rate-limit retry is a fresh job run that re-signs the request with a new timestamp, so the same logical request arrives with a different signature every time — deduplication keyed on it would silently never match.

  Put your own key in the body instead. A Liquid variable that is stable for the run — `{{ incident.id }}`, or a field you set earlier in the workflow — gives your endpoint something constant to deduplicate on across all five attempts.
</Warning>

***

## SSRF Filtering

Requests are filtered to block server-side request forgery. Destinations that resolve to internal, link-local, or loopback addresses are refused, so the HTTP Client cannot be used to reach infrastructure that is not publicly routable.

A workflow calling a service inside your own network will fail this check. Expose an endpoint that is reachable from the internet — protected by the signature below — or use a relay you already operate.

***

## Verifying the Request Came From Rootly

Every HTTP Client request carries an **`X-Rootly-Signature`** header containing a timestamp and an HMAC-SHA256 signature, in the same format outgoing webhooks use.

```txt theme={null}
X-Rootly-Signature: t=1492774588,v1=6657a869e8ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
```

Verify it before acting on the request. Because SSRF filtering means your endpoint has to be publicly reachable, the signature is what stops anyone else who finds that URL from driving it. The verification procedure — how the signed payload is assembled and compared — is written out in [Verifying Webhook Signatures](/configuration/webhooks#verifying-webhook-signatures).

### Where to Get the Secret

The signing secret is shown on the **HTTP Client action itself**, in a read-only **Secret** field in the workflow builder. Copy it from there into your receiving service.

Two things to know about it:

* **It is one secret per organization**, not per action. Every HTTP Client action in your Rootly organization signs with the same value, so a receiver can verify requests from any of them with one secret.
* **It is derived, not generated**, so there is no rotate button. If you need it changed, contact Rootly Support.

***

## Designing an Endpoint for This Action

Putting the pieces together, an endpoint that behaves well under this contract:

1. **Verifies `X-Rootly-Signature`** before doing anything else.
2. **Responds within 30 seconds**, acknowledging rather than finishing if the work is slow.
3. **Is idempotent**, because transport retries resend an identical body.
4. **Returns 429 when overloaded**, since that is the only status that earns a retry, and sets `Retry-After` at 90 seconds or less so it is honored in full.
5. **Matches its success statuses to `succeed_on_status`**, or has the workflow widened to `2xx`.

***

## Related Pages

<CardGroup cols={2}>
  <Card title="Workflow Actions Reference" icon="list-check" href="/workflows/actions-reference">
    Every workflow action by category, including the other Developer Tools actions.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/configuration/webhooks">
    Outgoing webhooks, and the signature verification procedure this action shares.
  </Card>
</CardGroup>
