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

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has several environments and each has its own keys, which are plain `pk_` strings with no environment prefix. Start with Test.
> Send with `client.send.message`, the default import of the v7 Node SDK. Reference a template by its `nt_` id or its alias.
> A send accepts a bare Elemental element list, but storing content on a template requires the top-level elements wrapped in a channel element.
> Templates and journeys can be built in the Courier app or created through the API. Either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.
> Prefer the Guides tab for how-do-I questions and the Docs tab for how-does-it-behave questions. The API reference lives under /api-reference.

# Journey fetch data node

> Call an external HTTP endpoint during a run and merge the response into the context.

export const AppLink = ({href, children, name, bare}) => {
  const label = children || name || "Open in Courier";
  if (bare) {
    return <a href={href} target="_blank" rel="noreferrer">{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="app" href={href} target="_blank" rel="noreferrer">
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method" aria-hidden="true">↗</span>
    </a>;
};

export const Doc = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="doc" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">DOC</span>
    </a>;
};

Fetch data nodes make HTTP requests to external services during journey execution. Courier merges the response into the journey context, where downstream nodes read it as variables.

Use it to pull real-time data from your application: whether a user completed an action, order details, or any internal API.

## Configuration

The fetch node has two panels: a summary panel (visible when clicking the node on the canvas) and a full HTTP request editor (opened by clicking **Setup Request**).

<Frame caption="Fetch node summary panel showing HTTP Request, Merge Strategy, and Conditions">
  <img src="https://mintcdn.com/courier-4f1f25dc/9rcgucLA9fBnJt_U/assets/fetch-data-config.webp?fit=max&auto=format&n=9rcgucLA9fBnJt_U&q=85&s=2f618c6cc98b39170d36a1f2aa5d6fb8" width="1812" height="1458" data-path="assets/fetch-data-config.webp" />
</Frame>

### HTTP request editor

Click **Setup Request** to open the full-screen HTTP request editor. The editor has three columns: setup, input, and output.

<Frame caption="HTTP request editor with method, URL, toggleable sections for headers/params/body, a cURL preview, and response output">
  <img src="https://mintcdn.com/courier-4f1f25dc/9rcgucLA9fBnJt_U/assets/fetch-request-editor.webp?fit=max&auto=format&n=9rcgucLA9fBnJt_U&q=85&s=3f2f0e6555a13dfaf7d012bbb8c8989d" width="3456" height="1880" data-path="assets/fetch-request-editor.webp" />
</Frame>

**Setup (left column):**

* **Import cURL**: Paste an existing cURL command to auto-populate the request configuration.
* **Method**: GET, POST, PUT, or DELETE.
* **URL**: The endpoint to call. Supports variable interpolation with `{{field_name}}` syntax (e.g., `https://api.example.com/users/{{user_id}}`). Only HTTPS URLs are allowed.
* **Headers**: Toggle on to add key-value header pairs. Common use: `Authorization: Bearer {{api_token}}`.
* **Query Parameters**: Toggle on to add key-value query parameters appended to the URL.
* **Body**: Toggle on to add a JSON request body (available for POST and PUT only, disabled for GET and DELETE).

**Input (center column):**

If your URL or body contains variables like `{{user_id}}`, this column shows fields for test values. A live cURL preview updates as you fill them in.

**Output (right column):**

Click **Execute Step** to run the request and see the response. On a successful 2xx response, Courier extracts the response schema and saves the available fields. The summary panel then lists those field names and types, so you can confirm what data is available downstream. A "Last tested" timestamp shows when the schema was last captured.

### Merge strategy

The merge strategy controls how the fetch response is combined with the existing journey context. Choose from the dropdown on the summary panel:

| Strategy                 | Behavior                                                                                                      |
| ------------------------ | ------------------------------------------------------------------------------------------------------------- |
| **Soft Merge** (default) | Adds new fields from the response without overwriting existing values. Existing context fields are preserved. |
| **Overwrite**            | Deep-merges the response into the context. Response values overwrite existing fields with the same key.       |
| **Replace**              | Replaces the entire context with the response. Existing fields not in the response are removed.               |
| **None**                 | Does not merge. If context already exists, it's left untouched. If empty, uses the response.                  |

**Soft Merge is the safest default.** Trigger schema fields and profile data are never overwritten by a fetch response.

### Conditions

Fetch nodes support optional <Doc href="/docs/journeys/nodes/branch">conditions</Doc>. If they are not met, the node is skipped and the journey continues without making the HTTP request.

## Response handling

The response body is parsed as JSON and merged into the journey context using the selected merge strategy. If the fetch returns:

```json theme={null}
{
  "onboarding_complete": true,
  "last_login": "2026-02-09T10:30:00Z"
}
```

These fields become part of the journey's data context. Downstream nodes reference them the same way they reference trigger schema fields:

* In <Doc href="/docs/journeys/nodes/branch">branch conditions</Doc>: select `data.onboarding_complete` as the field
* In <Doc href="/docs/journeys/build">journey templates</Doc>: use `{{onboarding_complete}}` or `{{last_login}}`
* In <Doc href="/docs/journeys/nodes/send">send node</Doc> recipient overrides: select the field from the dropdown

**A failed fetch does not stop the journey.** On a network error or a non-2xx response the run carries on with no data merged, and nothing marks the run as degraded. Branch on the fields you expected so a missing response takes a path you chose.

## Chaining fetch nodes

Fetch nodes can run in sequence. Each one merges its response into the journey context, and all fields are available downstream. For example:

1. **Fetch order details**: merges `order_id`, `total`, `status` into context
2. **Fetch user preferences**: merges `email_frequency`, `locale` into context
3. **Branch**: check `email_frequency` to decide whether to send
