The node that reaches every API n8n has never heard of
Part 8 wired up Slack, Gmail and Google Sheets — popular products that each ship a ready-made node, so you fill in a few fields and they work. The world holds a great deal more than those. The CRM you have to connect at work, a regional accounting system, an IoT vendor's API: n8n may have no node for any of them. This article is about the one node that does not care. If the other side has a REST API, the HTTP Request node can reach it.
The escape hatch, and when you are supposed to use it
At the time this guide's source was written, n8n listed 400+ integrations, covering many well-known SaaS products. Check the live catalog rather than trusting that number — it changes. Either way, pull the camera back and the figure stops being impressive, because the world holds a few hundred thousand services with an API. Five kinds of thing routinely have no node:
- Internal systems your company self-hosts — ticketing, inventory and ordering, CRM. n8n was never going to build those.
- Regional SaaS — a local accounting product, a logistics service, an invoicing API. Sometimes too niche for an official node.
- Services that just launched. n8n has not had time to build a node yet.
- Things everyone uses that n8n happens not to cover — some obscure CI/CD tool, say.
- Services you wrote yourself, and your department's internal microservices.
As long as it has a REST API — the kind where you call a URL and JSON comes back — the HTTP Request node reaches it. This node holds the same place in n8n as the Code node: it is the escape hatch. Anything the ready-made nodes cannot do, you assemble here.
A ready-made node is the vending machine with pictures on the buttons. HTTP Request is the shop counter, where you have to say out loud what you want and hand over the right money. Both sell you the same packet of crisps. Only one of them expects you to know the words — and only one of them stocks everything.
You met this node in passing in Part 5, when we walked the Core node family. Strictly speaking it straddles two families: it is not tied to any particular SaaS, which makes it Core, but what it does is call an outside service, which behaves like an Action. The distinction matters far less than the rule for when to reach for it.
One HTTP call is always the same four decisions
Whichever API you are calling, making one HTTP call means deciding four things. If you already know HTTP, skip ahead. If you do not, three minutes here pays off for good.
| Part | What it asks you | Typical value |
|---|---|---|
| URL | Where do you send it? | https://api.example.com/users |
| Method | What action do you want? | GET, POST, PUT, DELETE, PATCH |
| Headers | What information comes along? | Authorization: Bearer xxx, Content-Type: application/json |
| Body | What data are you sending? | A JSON payload — only POST, PUT and PATCH need one |
It is posting a parcel. The URL is the address on the front. The method is what you are asking the post office to do — deliver it, or collect one, or take the old one back. The headers are the sender's details on the label, which is how they know it is really from you. The body is what is actually inside the box, and a collection request goes in an empty envelope.
flowchart TD A["An item arrives from
the node before"] --> B["HTTP Request node"] B --> U["URL
where to send it"] B --> M["Method
what to do there"] B --> H["Headers
who you are"] B --> D["Body
what you send"] U --> S["Their API"] M --> S H --> S D --> S S --> J["Response JSON lands in
the output pane"] J --> N["The next node reads a field
from it with an expression"]
The method is just a verb. It says what you want done to that URL, and there are five you will meet:
Headers carry information alongside the call. Two of them turn up constantly: Authorization: Bearer <your-token>, which proves who you are, and Content-Type: application/json, which tells the other side you are sending JSON. The body is filled in only for POST, PUT and PATCH. GET and DELETE carry no body — a few APIs are exceptions, but not many.
Three things to find in anyone's API docs
When you open the documentation for an API you have never used — Stripe, Notion, your company's internal system — there are three things to find. Everything else on the page is trimming.
-
Find 1
The endpoint URL — where to send it
A sidebar or a table usually lists every address you can call:
https://api.example.com/v1/users,https://api.example.com/v1/orders/{id}. Braces like{id}in an address mean you replace that part with a real value. -
Find 2
The method — which verb the endpoint takes
Every endpoint is labeled
GET,POST,PUTorDELETE. The same URL often supports several:GET /usersreturns the list andPOST /userscreates a new one. Read carefully and do not mix them up. Doc tables are usually three columns — method, path, description. -
Find 3
The auth section — how you prove who you are
There is always an Authentication section near the front telling you which scheme they use. Three are common: a Bearer token in a header (most modern APIs),
?api_key=xxxon the end of the URL (the older style), and a full OAuth round trip (Google, Facebook and the like). Work out which one it is and you know what to fill in.
curl -H "Authorization: Bearer xxx" https://api.example.com/users. Read that one line and you have all three: the URL at the end, the header after -H, and the method by absence — no -X means GET. If you can read curl, you can use the HTTP Request node.Docs look different from vendor to vendor, but those three are always written down somewhere. If you cannot find them, either the docs are bad or you need to go and ask their support.
Hands-on: fetch public GitHub data, no auth required
Start with a public API that needs no authentication, purely to get used to the node. The goal is to fetch the public data for the GitHub user octocat, their octopus-cat mascot.
flowchart LR A["Manual Trigger"] --> B["HTTP Request
GET api.github.com/
users/octocat"] B --> C["Output pane
login, id, name,
public repos"] C --> D["Edit Fields (Set) or Slack
reads the login field"]
-
Step 1
Add an HTTP Request node to the canvas
Press + on an empty part of the canvas to open the nodes panel, search for
httpand pick HTTP Request. It lands on your workflow with connector dots on both sides, the same as an Action node. If there is no trigger in front of it, add a Manual Trigger so you can run it by hand, and wire the two together. -
Step 2
Set Method to GET
Open the node's panel on the right and set the Method dropdown at the top to
GET. GET is the default, so usually there is nothing to change. -
Step 3
Put the address in the URL field
Paste this into the URL field below the method:
https://api.github.com/users/octocatThat is GitHub's own public REST API for reading one user's data.
-
Step 4
Leave Authentication on None
Public data needs no auth. In real work you will usually pick Generic Credential Type or Predefined Credential Type instead; both come later in this article, so skip them on your first run.
-
Step 5
Press Execute step
The Execute step button sits at the top right of the node. Some versions label it Test step — recognize the button rather than the word. Press it and n8n really does call the API.
-
Step 6
Read the JSON in the output pane
Within seconds the octocat's data appears on the right:
login: "octocat",id: 583231,name: "The Octocat",avatar_url: "...",public_repos: 8— one whole block of JSON. That means your API call worked. -
Step 7
Prove it downstream with an expression
Wire a Slack or
Edit Fields (Set)node after the HTTP Request and type this into a message field:User {{ $json.login }} has {{ $json.public_repos }} reposAt run time each expression is replaced with the real value. Part 10 is devoted to that syntax.
Proving who you are, without leaving the token lying around
Public APIs are the minority. In practice most of them want to know who is calling. Five styles cover nearly everything you will run into:
| Style | How it is written | Common with |
|---|---|---|
| Bearer Token | Add Authorization: Bearer <token> to the headers | OpenAI, Anthropic, Notion, most modern APIs |
| API Key in Query | Add ?api_key=xxx or ?key=xxx to the URL | Google Maps, OpenWeatherMap, some older APIs |
| Basic Auth | Add Authorization: Basic <base64(user:pass)> to the headers | Jira, some self-hosted systems, internal tools |
| API Key in Header | Add a custom header field such as X-API-Key: xxx | Stripe (the old one), some enterprise APIs |
| OAuth 2.0 | Run an authorization round trip to get a token, refreshed automatically | Google, Slack, Facebook — these usually have a dedicated node |
The node's own Authentication dropdown has three settings, and the third one is where the list above gets used:
- None — public APIs need no auth.
- Predefined Credential Type — n8n has these set up for you already, so you just pick the matching service:
OpenAI,NotionorHubSpot, for example. - Generic Credential Type — you name the scheme yourself. The dropdown offers seven:
Basic Auth,Custom Auth,Digest Auth,Header Auth,OAuth1 API,OAuth2 APIandQuery Auth. Some versions also carrySimplified Custom Auth.
Exporting a workflow is handing somebody a photocopy of every settings panel in it. If the token is typed into a panel, it is on the photocopy. A credential is the key on your own ring: the workflow says use the key called MyCompany CRM Bearer, and the photocopy says exactly that and nothing more.
Make a credential once, point several nodes at it
If you keep using the same API key against several endpoints at the same service — GET the customer list, POST a message to each customer, DELETE the expired ones — do not paste the token into three nodes. Store it once.
-
Step 1
Open Credentials and create one
Pick Credentials in the main sidebar on the left, then press Create Credential at the top right. The first time through, n8n may offer you a guided button instead.
-
Step 2
Search the type list for Header Auth
Search for
headerand pick Header Auth. Older interfaces show it as HTTP Header Auth — same thing. It is the most general of them: Bearer tokens andX-API-Keyboth go through it. -
Step 3
Fill in the header name and its value
Name is the header field's name and Value is its value — for a Bearer token that is
AuthorizationandBearer <your-token>. Save the pair and give the credential a name you will recognize later, such asMyCompany CRM Bearer. -
Step 4
Point the node at it
Back in the HTTP Request node, set Authentication to
Generic Credential Type→Header Auth→ the credential you just made. From then on every request that node makes carries the header automatically, and changing the token is a one-place edit for every node that shares it.
Hands-on: post a JSON body, and the URL patterns behind it
GET fetches; POST sends. In practice you reach for POST whenever you want n8n to create a record in another service. Say a messaging API's endpoint is POST /messages, and its docs say the body has to hold a text field and a to field.
-
Step 1
Change Method to POST
Set the Method dropdown at the top of the right-hand panel to
POST. Once POST is selected, a Send Body option appears below it. -
Step 2
Put the endpoint in URL
For example
https://api.example.com/v1/messages. Their docs always give you this. -
Step 3
Set up Authentication
Pick whatever they require. Usually that is
Generic Credential Type→Header Auth, holding oneAuthorization: Bearer <your-token>pair — the credential you built in the previous section. -
Step 4
Turn on Send Body
If you are sending a body, switch Send Body on. The body fields only appear once you do.
-
Step 5
Set Body Content Type to JSON
A Body Content Type menu appears with five options:
JSON,Form URLencoded,Form-Data,n8n Binary FileandRaw. Most modern APIs takeJSON. A file-upload form takesForm-Data; raw binary, a PDF sent straight through for instance, takesn8n Binary File; XML or a custom MIME type takesRaw. Pick whatever their docs say. -
Step 6
Set Specify Body to Using JSON and paste the payload
A large text box appears. Paste this in:
{
"text": "{{ $json.message }}",
"to": "[email protected]"
}Two fields inside one pair of braces, and each does a different job:
Field Value to paste What it does "text""{{ $json.message }}"An expression — it reads the messagefield from the previous node"to""[email protected]"A hard-coded value. Replace it with a real recipient Hard-coding the first one is fine too — just type
"hello"in place of the expression. Type the object exactly as it appears above, comma between the two fields and no comma after the last one; a stray comma is the single most common reason this box turns red. -
Step 7
Execute step and read the response
Press run. Their API's response appears in the output pane on the right, usually a confirmation along the lines of
{"id": "msg_xxx", "status": "sent"}. If{"error": "..."}comes back instead, the last section of this article is where to go.
{{ JSON.stringify($json) }} sends the entire item as the body. Watch your quote escaping against the surrounding double quotes.The pattern almost every REST API follows
Once you have done one POST, the rest of any API's docs read faster, because nearly all of them are the same four CRUD operations — create, read, update, delete — mapped onto methods:
| What you want to do | Method and URL convention | Body needed |
|---|---|---|
| Pull a list of records | GET /items?limit=100 | No |
| Pull a single record | GET /items/{id} | No |
| Create a record | POST /items | Yes — JSON for the new record |
| Replace a whole record | PUT /items/{id} | Yes — the complete new content |
| Update part of a record | PATCH /items/{id} | Yes — only the fields you are changing |
| Delete a record | DELETE /items/{id} | No |
| Query with filters | GET /items?status=active&created_after=2026-08-01 | No — the filters live in the query string |
flowchart TD A["What do you want done
to that URL?"] --> B{"Reading, or changing?"} B -->|"reading"| C{"A list, or one record?"} C -->|"a list"| C1["GET /items
no body"] C -->|"one record"| C2["GET /items/id
no body"] B -->|"changing"| D{"Creating, updating
or removing?"} D -->|"creating"| D1["POST /items
body: the
new record"] D -->|"updating"| E{"All of it, or
a few fields?"} E -->|"all of it"| E1["PUT /items/id
body: the
whole content"] E -->|"a few fields"| E2["PATCH /items/id
body: only
what changes"] D -->|"removing"| D2["DELETE /items/id
no body"]
{id} in real docs; the diagram drops the braces only so the shapes stay legible.Two conveniences are worth knowing before you start typing URLs by hand.
Query parameters — the ?a=1&b=2 part after the question mark — do not have to be typed at all. Switch on Send Query Parameters and fill in one Name/Value pair per row. n8n assembles the correct URL for you, URL encoding included, so spaces and non-Latin characters are escaped automatically.
Path placeholders take an expression. To swap a real value into a {id} slot, write the expression straight into the URL field:
https://api.example.com/items/{{ $json.id }}n8n replaces it with the actual value at run time. This is one of the most common things you will ever do in this node.
When one call is not enough, and the settings that pace them
Most APIs will not return everything at once. One response is capped at 100 records — some at 50, some at 25. To pull 500 customers you have to call five times in a row, one page each. That is pagination, and the good news is that the HTTP Request node has it built in, so you never write the loop yourself.
It is the ticket machine that only dispenses ten at a time. You do not queue once for five hundred; somebody presses the button fifty times. Pagination is n8n doing the pressing, and stacking every ticket into one pile before the next node ever looks at it.
sequenceDiagram participant N as HTTP Request node participant A as Their API N->>A: Request, page 1 A-->>N: 100 records, plus a next page marker N->>A: Request, page 2 A-->>N: 100 records, plus a next page marker Note over N,A: Interval Between Requests (ms)
puts a gap between these N->>A: Request, page 5 A-->>N: 100 records, no next page Note over N: Complete Expression is now true, so it stops N->>N: Every page merged into one output
-
Step 1
Open the node's Pagination block
Scroll down the node's right-hand panel to Pagination and change Pagination Mode from
Offto the mode you want. -
Step 2
Pick the mode their API docs describe
Two are common. Response Contains Next URL is for APIs whose JSON holds a
nextornext_urlfield — n8n follows it automatically. Update a Parameter in Each Request is for the rest: you tell n8n which query parameter to change each time,page=1, 2, 3...orcursor=xxx. -
Step 3
Tell it when to stop
n8n decides whether to stop using a boolean expression in the field called Complete Expression. Two shapes cover most APIs:
{{ $response.body.results.length === 0 }}— stop when an empty array comes back{{ !$response.body.next_page }}— stop when there is no next pageThere is also Limit Pages Fetched, a safety cap on how many pages it will ever request — twenty, say. Set one.
-
Step 4
Run it and look at the output
n8n makes the calls back to back and merges every page into one output. The next node sees the full 500 records and never has to care that there were five requests.
429 error — Too Many Requests — means you are calling too fast. The Pagination settings hold an Interval Between Requests (ms) field; 500 to 1000 ms is usually enough to calm it down. You can also control the pace by hand with a Wait node in front.The official pagination documentation is thorough, with an example for every pattern: docs.n8n.io/code/cookbook/http-node/pagination.
The other options, in one pass
An Add Option button at the bottom of the node opens the advanced settings. Seven of them you will meet sooner or later:
| Option | What it does | When you need it |
|---|---|---|
| Response > Response Format | Sets how the response is parsed: Autodetect (the default), JSON, Text, File | Pick File to download a PDF, image or CSV; Text when they return a plain string |
| Response > Full Response | The output carries the headers and status code as well as the body | When you need to see the HTTP status code or the response headers |
| Response > Never Error | The node stays out of the red even when the API returns 4xx or 5xx | When you want to read the status code yourself and branch on it |
| Timeout | The longest time in milliseconds to wait for a response. Leave it empty and n8n's built-in default applies, usually 300000 ms | Their API is slow or flaky, or you want to fail fast |
| Batching | Call once every N items, and how many milliseconds to wait between calls | 500 items arrive and each needs its own API call — this is your rate limit |
| Redirects | Whether 3xx redirects are followed automatically | Their API uses shortened URLs, or redirects to a sign-in page |
| Proxy | Sends the call through an HTTP proxy | Your corporate network only reaches outside APIs through a proxy |
Split In Batches node in front — and if the API bills per call, read the next warning before you press run.Eight failures, and what each one is actually telling you
When a call does not get through, the error message is usually an HTTP status code. Knowing a handful of them by sight saves a great deal of time, because each points at a different half of the problem.
flowchart LR
A["The node went red"] --> B{"What came back?"}
B -->|"401"| C["Auth is wrong or expired.
Get one call working in curl
first, then match the node to it"]
B -->|"403"| D["The token is valid but lacks
the scope. Issue a new one"]
B -->|"404"| E["Wrong URL, a missing version
segment, or no such record"]
B -->|"429"| F["Calling too fast.
Add an interval, a Wait node,
or Retry on Fail"]
B -->|"500, 502, 503"| G["Their server, not yours.
Retry on Fail, and check
their status page"]
B -->|"200, but HTML"| H["A redirect landed you on a
sign-in page. Check the URL
and the auth"]
- 401 Unauthorized — no auth, or the wrong token. Auth is set up wrong, or the token expired. Get one successful call through Postman, Insomnia or curl first, then come back and compare: take the curl that works and fill the node's Method, URL and Header to match it field by field. That isolates whether the problem is an n8n setting or the token itself.
- 403 Forbidden — signed in, but not allowed. The token is right, but you have no permission for this endpoint. Read the scope or role section of their API docs; a specific permission usually has to be granted (OpenAI wants a read or write scope, Slack wants
chat:write). Issue a new token with the right permissions. - 404 Not Found — wrong URL, or the record does not exist. A typo, a missing
/v1/, or a wrong{id}in the path. Compare it against the URL in the docs carefully. Building a URL with an expression makes an extra or missing slash especially easy. - 429 Too Many Requests — you are calling too fast. Their API has a rate limit, 60 calls a minute say, and you went over it. Three fixes: set an interval in the node's Options → Batching; put a
Waitnode in front to slow it down; or turn on Retry on Fail with Retry Wait on the node. Part 12 covers retries in detail. - 500 / 502 / 503 — their server fell over. Not your problem: their API is down. Turning on Retry on Fail, three retries five seconds apart, usually gets you through. A 500 that keeps coming means they really are broken — go and find their status page.
- 200, but HTML comes back instead of JSON — your URL is wrong. A 302 has probably redirected you to a sign-in page or an error page. Check whether the output is a pile of HTML tags. Compare the URL carefully, confirm auth is set up, and confirm the API base URL is right. Sometimes
httpsagainsthttpis enough to trigger the redirect. - It succeeds, but the body is empty — check the status code first. A
204 No Contentmeans "it worked, there is nothing to return", which is entirely normal; DELETE often returns 204. Or the API is simply designed that way. To tell whether it worked, switch on Options → Response → Full Response and judge by the status code. - SSL certificate errors — internal company APIs often use a self-signed certificate. Turning on Options → Add Option → Ignore SSL Issues (Insecure) skips verification.
Authorization: Bearer in a header for exactly this reason.Questions that come up every time
I have a curl command in front of me. How do I turn it into a node?
-X is the Method, -H is a Header, -d is the Body, and the URL is the URL. Or fastest, use the node's own Import cURL button at the top of its Parameters tab — paste the curl in and it fills all four for you.The API returns a file. What does HTTP Request do with it?
File. The output then becomes a binary field — the output pane offers it as a downloadable file — and downstream you can attach a Google Drive node to upload it, or a Set Binary Data node to work on it.Are the Webhook node and the HTTP Request node the same thing?
Webhook node receives — someone else calls into n8n. The HTTP Request node calls out — n8n makes the call itself. Same wire, opposite directions. Part 17 is devoted to Webhook. In practice the two often work together: some system calls your webhook, n8n reshapes the data, and HTTP Request sends it on to another system.Is the {{ }} in API docs the same as an n8n expression?
{{ variable }} in API docs is a placeholder for you to replace by hand — Bearer {{ token }} means swap the whole {{ token }} for a real token. An n8n expression like {{ $json.field }} is syntax that n8n really evaluates at run time. When you see a placeholder in someone's docs, replace it yourself; do not leave it for n8n to work out.Can I use expressions in the URL, the headers and the body?
{{ $json.xxx }}. A dynamic URL such as /users/{{ $json.userId }}, a dynamic header whose Authorization value comes from the previous node, and a fully dynamic body with {{ JSON.stringify($json) }} all work. Part 10 walks through the syntax properly.What do I do when their API has no docs at all?
Where to go from here
You can reach anything now. Next, reach it safely and dynamically.
Part 10 takes the two loose ends this article left: managing credentials properly — sharing, permissions, and what survives an export — and expression syntax, so the URL, headers and body of an HTTP Request node can all read from the node before it. The fastest real practice in the meantime is to find one internal system at work that n8n has no node for, and get a single endpoint answering.
Open the full guidePart 9 of the Woow n8n Onboarding Guide series on the Apporo blog.
Adapted from the Woow n8n Onboarding Guide, produced by WoowTech and released under CC BY 4.0. This adaptation is published by Apporo under the same licence.
Light · Air · Water · Control · apporo