n8n HTTP Request Node: Call Any REST API Tutorial

Learn to use the n8n HTTP Request node to call REST APIs, handle auth, pagination, and errors. Works with any API in your workflow.

Problem: Every API Has a Different Shape — n8n Has One Node for All of Them

You need to pull data from a third-party API, push events to a webhook, or chain two services together — and none of them have a native n8n integration. The HTTP Request node is the solution for all three cases.

The node is simple on the surface but has sharp edges: authentication setup, pagination loops, rate limits, and extracting nested JSON can trip you up fast.

You'll learn:

  • How to configure GET, POST, PUT, and DELETE requests
  • How to handle API key, Bearer token, and OAuth2 authentication
  • How to paginate through multi-page results automatically
  • How to pass workflow data into request headers, params, and body

Time: 20 min | Difficulty: Intermediate


Why the HTTP Request Node Is Your Most Useful Node

n8n has 400+ native integrations, but every API you'll ever encounter is reachable via HTTP. The HTTP Request node gives you:

  • Full control over method, URL, headers, body, and query params
  • Built-in credential management (no hardcoded API keys)
  • Automatic pagination with cursor, offset, or link-header strategies
  • Response mapping directly into n8n's item format

It runs on n8n 1.x (self-hosted or cloud) and works identically in both.


Solution

Step 1: Add the HTTP Request Node

In your workflow canvas, click +, search for HTTP Request, and add it.

You'll see four main sections: General, Authentication, Headers, and Options.

Start with the URL field — paste any REST endpoint:

https://api.example.com/v1/users

Set Method to GET for reads, POST for creates, PUT/PATCH for updates, DELETE for removals.


Step 2: Set Up Authentication

Avoid hardcoding API keys in the URL or headers directly. Use n8n credentials instead — they're encrypted and reusable across nodes.

API Key (header-based):

  1. Click Authentication → Generic Credential Type → Header Auth
  2. Create a new credential: Name = X-API-Key, Value = your key
  3. n8n injects the header on every request automatically

Bearer Token:

  1. Click Authentication → Generic Credential Type → Bearer Token
  2. Paste the token value

OAuth2 (e.g., Google, Salesforce):

  1. Click Authentication → OAuth2
  2. Fill in Authorization URL, Token URL, Client ID, Client Secret
  3. Click Connect — n8n handles the token refresh automatically
# Never do this — key exposed in workflow JSON
https://api.example.com/users?api_key=sk-abc123

# Do this instead — credential reference stays encrypted
Authentication: Header Auth → [your saved credential]

Step 3: Build the Request

GET with query parameters:

In the Query Parameters section, click Add Parameter:

NameValue
limit50
page{{ $json.page }}

The {{ }} syntax pulls values from the previous node's output — this is how you pass dynamic data into requests.

POST with a JSON body:

Set Method to POST, then under Body:

  • Body Content Type: JSON
  • Toggle to JSON/RAW Parameters and write:
{
  "name": "{{ $json.name }}",
  "email": "{{ $json.email }}",
  "role": "user"
}

PUT with path variables:

Embed node data directly in the URL:

https://api.example.com/v1/users/{{ $json.userId }}

n8n resolves the expression before sending the request.


Step 4: Handle Pagination

Most APIs return results in pages. The HTTP Request node has a built-in Pagination option under Options → Add Option → Pagination.

Offset-based pagination (most common):

Pagination Mode:         Update a Parameter
Parameter Type:          Query
Parameter Name:          offset
Initial Value:           0
Increment By:            50
Complete When:           Response Body Is Empty

Cursor-based pagination (GitHub, Stripe, etc.):

Pagination Mode:         Update a Parameter
Parameter Type:          Query
Parameter Name:          cursor
Value to Set Cursor:     {{ $response.body.next_cursor }}
Complete When:           {{ $response.body.next_cursor }} is empty

Link header pagination (GitHub API default):

Pagination Mode:         Response Contains Next URL
Next URL Extraction:     {{ $response.headers["link"].match(/<([^>]+)>; rel="next"/)?.[1] }}

n8n loops automatically and merges all pages into one output array — no Code node required.


Step 5: Extract and Transform the Response

By default, the node outputs the full response body as $json. For nested data, use dot notation in downstream nodes:

# Access a nested field
{{ $json.data.users[0].email }}

# Flatten with a Set node after HTTP Request
{{ $json.results.map(r => r.id) }}

If the API returns a non-200 status on errors, enable Options → Continue on Fail and add an IF node to branch on {{ $json.statusCode }}.


Verification

Build a quick smoke test workflow:

Manual Trigger → HTTP Request (GET https://httpbin.org/get) → Debug Output

Expected output in Debug:

{
  "args": {},
  "headers": {
    "Host": "httpbin.org"
  },
  "url": "https://httpbin.org/get"
}

httpbin.org echoes your request back — useful for confirming headers, auth, and body are sent correctly before pointing at a real API.

For authenticated endpoints, test credentials are valid by checking {{ $json.statusCode }} equals 200 before building out the rest of the workflow.


Common Errors and Fixes

401 Unauthorized → Credential misconfigured. Check the header name exactly matches what the API expects (e.g., Authorization vs X-API-Key).

400 Bad Request → Body format mismatch. Confirm the API expects application/json not form-data. Set Body Content Type explicitly.

Error: Cannot read property of undefined → Expression references a field that doesn't exist in the response. Use Debug to inspect actual response shape first.

Rate limit 429s → Add a Wait node (1–2 seconds) before the HTTP Request node inside pagination loops. For burst protection, set Options → Retry on Fail → Max Tries: 3, Wait Between Tries: 2000ms.


What You Learned

  • The HTTP Request node handles any REST API with the same configuration pattern
  • Always use n8n credentials — never hardcode keys in URLs or headers
  • Built-in pagination handles offset, cursor, and link-header strategies without extra code
  • {{ $json.field }} expressions make requests dynamic and data-driven

Limitation: The HTTP Request node doesn't support GraphQL queries natively — use it with POST, Content-Type: application/json, and a { "query": "..." } body instead. For WebSocket or streaming APIs, you'll need a custom Code node with the ws library.

Tested on n8n 1.78.0, self-hosted (Docker) and n8n Cloud, Ubuntu 24.04