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):
- Click Authentication → Generic Credential Type → Header Auth
- Create a new credential: Name =
X-API-Key, Value = your key - n8n injects the header on every request automatically
Bearer Token:
- Click Authentication → Generic Credential Type → Bearer Token
- Paste the token value
OAuth2 (e.g., Google, Salesforce):
- Click Authentication → OAuth2
- Fill in
Authorization URL,Token URL,Client ID,Client Secret - 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:
| Name | Value |
|---|---|
limit | 50 |
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