Guided exercises

The bot runs. Now make it do something else.

Six exercises that connect your bot to public data sources. Every address is real, and none of them asks for an account except the fifth, which is there for that reason.

Written for someone who has the bot running and has never built anything in n8n on their own. Every technical word is explained the first time it turns up, and again in the glossary at the bottom of the page.

Every address on this page was called by hand on 13 September 2026.

weather pollen river flow train times aircraft MCP
The decision

Why none of this ships inside the template.

Every outside service you wire in becomes a maintenance promise with no end date. The day a field gets renamed or an access rule tightens, the bot goes quiet for everybody who bought it, on the same day, with nobody having touched a thing.

📉

The case that settled it

Exercise five uses OpenSky. In March 2026 the service dropped username-and-password access in favour of OAuth2, a login method where you first ask for a short-lived pass and then show that pass on every call. Everything still connecting the old way stopped counting aircraft overnight. Had that service been wired into the template, the outage would have been ours, everywhere, for a gadget.

🔧

What we do instead

We show you how to wire them yourself: the exact address, the box to place, and the trap that costs an hour. You keep the ones that serve you, you ignore the others, and the day one of them changes you already know where to look.

The shared pattern

The six exercises do the same thing, six times.

A command arrives, you call an address, you turn the answer into a sentence, you send it. Once that gesture belongs to you, the rest is only a question of which fields to reach for.

Five words before we start

  • Workflow. The whole picture you see in the n8n editor: boxes joined by lines, read from left to right. Your bot is one workflow, and these exercises add to it rather than start a new one.
  • Node. One box in that picture. A node does exactly one job: receive a message, call a website, write a sentence, save a row. Everything below amounts to placing two or three more of them.
  • Webhook. The address n8n keeps open so that Telegram can push each new message to it the second someone types, rather than n8n asking over and over whether anything has happened. Your bot already has one and you never touch it again.
  • API and endpoint. An API is a web address built to answer with data instead of a page meant for human eyes. One precise address inside it, with its parameters, is an endpoint. Each exercise here calls a single endpoint.
  • JSON. The text format the data comes back in: named fields holding values, lists, or more fields, nested inside one another. Reading JSON means walking down that nesting, and that is most of the work in these exercises.

The five steps, every time

  • Try the address in your browser first. Paste it, look at what comes back. What the browser does not show you, n8n will not hand you either, and you will spend the next hour looking for the mistake in the wrong place.
  • One more branch in the Switch node. That is the node that already recognises your 22 commands and sends each one down its own line. Add an output for yours.
  • One HTTP Request node, method GET. This is the node that calls a web address; GET is the verb that asks for data without changing anything at the far end. Put the address in the URL field. Nothing else to set for the first four exercises.
  • One Code node to write the sentence. A Code node is a box where you type a few lines of JavaScript. Two or three are enough: take the useful values, build the text to send.
  • The Telegram node you already have, operation sendMessage. You reconnect it, you do not rebuild it.

Tick Continue On Fail on every node that reaches out to the internet. It is the house rule, and it has a precise reason: without it, one broken service stops the whole run — and your bot goes silent even for your own tasks. A quiet gadget beats a quiet bot.

The six exercises

From a quarter of an hour to a real evening.

Do them in order. Each one adds a single new difficulty and reuses what the previous one taught you. The first four need no account at all. The fifth is genuinely hard, and the sixth is hard in a different way.

1 Tomorrow's weather, in one sentence

About twenty minutes · the gentlest one on the page

Why start here: this exercise teaches the single move that the five others reuse — reaching into an answer and pulling one value out of it. Nothing else about it is new, and that is the point.

What you want: you type /weather and the bot answers "Tomorrow in Sion, 12 to 25 degrees, no rain."

you /weather

the bot ☁️ Tomorrow in Sion · 12.0 to 25.4 °C · 0 mm of rain

The nodes: Switch (one extra branch) → HTTP RequestCode → Telegram. The pattern, with nothing added to it.

The address:

open-meteo.com · no key needed
https://api.open-meteo.com/v1/forecast?latitude=46.2331&longitude=7.3606
  &daily=temperature_2m_max,temperature_2m_min,precipitation_sum,weather_code
  &timezone=Europe/Zurich&forecast_days=1

The coordinates are Sion's. Put your own in; a right click on any map gives them to you.

The trap: the answer is not a list of days, it is an object holding lists. Even for a single day, temperature_2m_max arrives as a list, so you have to write daily.temperature_2m_max[0]. The [0] means "the first item of the list", and lists are counted from zero. Without it the field turns up empty and you hunt for the mistake somewhere else for twenty minutes. Second detail: weather_code is a number rather than a text (0 = clear sky, 3 = overcast, 61 = light rain). You need a small lookup table in the Code node.

What you learn: how to walk down a JSON answer and pull the right value out of it. It is the basic move, and it comes back five more times.

2 Pollen, the same move on another service

About fifteen minutes · shorter than the first one, on purpose

Why it comes second: same publisher as exercise 1, different host, different shape of answer. Changing service is first of all changing shape, and it costs nothing to learn that on an easy one.

What you want: /pollen and the bot reports the four pollens that spoil spring in Valais.

The address:

air-quality-api.open-meteo.com · no key needed
https://air-quality-api.open-meteo.com/v1/air-quality?latitude=46.2331
  &longitude=7.3606&current=grass_pollen,birch_pollen,alder_pollen,ragweed_pollen
  &timezone=Europe/Zurich

The trap: here you ask for current and not daily, and the values arrive on their own, without a list around them. So current.grass_pollen reads straight, with no [0]. And one more thing we checked: outside Europe the fields still exist but hold null, which is JSON's way of saying "there is nothing here". The forecast model only covers the continent, and nothing in the answer says so.

What you learn: an empty field is not automatically your fault. Before you go and fix your node, ask whether the service has the data at all.

3 The Rhône, and the word you must not write

About thirty minutes · the most profitable lesson on the page

Why it matters: this is where you find out that a call that succeeds and a call that asks the right question are two separate things. Everything after this exercise gets easier to debug.

What you want: /river and the bot gives the measured flow in cubic metres per second. Useful in Valais when it has rained for three days.

The source: the measurements come from the Swiss Federal Office for the Environment. They are republished by api.existenz.ch, run by a Swiss association. Station 2011 is the Rhône at Sion.

api.existenz.ch · no key needed
https://api.existenz.ch/apiv1/hydro/latest?locations=2011
  &parameters=flow,temperature&app=YOUR_APP&version=1.0

The app parameter expects the name of your bot. No key, no check: it is a courtesy that lets whoever pays for the hosting see who is calling. Put a readable name in rather than leaving it as it stands.

The trap, and it is a pretty one: the parameter is called flow. Write discharge, the word a technical dictionary hands you when you look up river flow, and the service still answers 200 — the status code meaning the call itself went through — carrying "payload": [], an empty list. No error, no hint, nothing. We called both to be sure: flow returns the value, discharge returns an empty list.

The second trap: the answer is a flat list of objects shaped {timestamp, loc, par, val}. You ask for two parameters and you may well get one back: station 2011 publishes the flow but not the water temperature. So look for the item whose par field equals flow. Never take payload[0] on the assumption that the order will follow your request.

What you learn: a 200 does not prove you asked the right question. That lesson pays for itself far beyond rivers.

4 The next train, with a parameter that comes from you

About forty minutes · the first one where typed text leaves your server

Why it is different: in the first three exercises the address never changes. Here it depends on what the person typed, and everything difficult about the exercise follows from that one fact.

What you want: /train Sion Lausanne and the bot answers with the departure time, the platform and any delay.

you /train Sion Lausanne

the bot 🚆 11:39 · platform 3 · 1 min late · 2 h 06 on the way

transport.opendata.ch · no key needed
https://transport.opendata.ch/v1/connections?from=Sion&to=Lausanne&limit=1

The nodes: before the HTTP Request, you have to cut the command text apart to isolate the two stations. Either a Code node, or an expression written straight into the field, along the lines of {{ $json.message.text.split(' ')[1] }}. An expression is how n8n lets you compute a value on the spot instead of typing a fixed one; the double braces are what mark it as one.

The trap: station names contain spaces, hyphens and accented letters. A name like Genève-Aéroport, pasted straight into the address, falls apart, because a web address only accepts a narrow set of characters and the rest have to be escaped. Rather than patching the text by hand, switch on Send Query Parameters in the HTTP Request node and give from and to as two separate parameters: n8n encodes them correctly for you. Tested with Genève-Aéroport, it goes through.

What you learn: how to get text written by a human safely into an outside call. Done carelessly, this is the door that injections walk through — an injection being what happens when something typed by a stranger gets treated as part of your instruction instead of as plain data. It is the same caution as the apostrophes in the bot's SQL.

5 Aircraft overhead, and a real token

An evening, honestly · the hardest exercise here

Fair warning: this one is not a coffee-break exercise. Two calls instead of one, a credential that expires, and a rule change in March 2026 that has left most of the tutorials on the web quietly wrong. Start it when you have a clear evening.

What you want: /planes and the bot counts the aircraft in a square of sky around you. The service is OpenSky Network, an association based in Switzerland.

opensky-network.org · limited anonymous access
https://opensky-network.org/api/states/all?lamin=46.0&lomin=7.0
  &lamax=46.5&lomax=7.6

With no account the call still works, on a daily budget. A response header called x-rate-limit-remaining tells you what is left of it — a header being an extra line of information the server sends alongside the data itself. For a personal bot that answers when asked, that budget is enough.

The beginner trap: when the square of sky is empty, the states field holds null instead of an empty list. Any node that counts a length stops right there. Checked on the same day at the same minute: over Valais, null; over Zurich, 47 aircraft. The difference was not in the code.

The serious trap, the one that makes the exercise: since March 2026, a username and password placed on the call do nothing whatsoever. They do not even raise an error, they are simply ignored, and you drop back into the anonymous quota without noticing. For a real quota you go through OAuth2: you ask an authentication address for a token by sending it a client identifier and a client secret, then you present that token in the Authorization header of every call. A token is a long string that stands for "this caller is allowed", valid for a limited time only — which means your workflow has to know how to ask for a fresh one.

The nodes: two HTTP Request nodes instead of one. The first fetches the token with a POST, the verb used when you send something rather than merely ask for it; the second uses the token. Plenty of tutorials online predate the change, and that is why they no longer work, rather than you going about it badly.

What you learn: the difference between a key you paste once and a token you renew. That two-step shape is how most professional services are entered.

6 MCP, or how to stop writing one node per service

An hour to wire, longer to think through · hard in a different way

Why it closes the page: the five exercises before it add one service at a time. This one adds a whole family at once, and it changes what your bot is for.

What you want: to stop redoing the previous five exercises for every new idea. MCP, short for Model Context Protocol, is a convention by which a server publishes a list of tools, each described in words a language model can read, so that the model itself works out when to use them. n8n knows how to connect to such a server, and the documentation explains the settings without ever saying what the thing is good for.

The node: MCP Client Tool. It does not sit in the main line of the workflow; it hangs underneath an Agent node, as one more tool the agent can reach for. An Agent node is the node that hands the conversation to a language model and lets that model choose among the tools attached to it. You fill in the server address under Endpoint, you pick the authentication (none, bearer token, header, or OAuth2, depending on the server), and the agent discovers by itself what it can do.

The trap: the tool descriptions are sent to the model on every turn of the conversation. A server publishing thirty tools means thirty descriptions on every single message, and a bill that follows. The node offers Tools to Include and Tools to Exclude so that you expose only what you need. Use them on your first try, not after your first invoice.

The confusion to avoid: n8n has two nodes with neighbouring names. MCP Client Tool fetches tools from elsewhere for your bot. MCP Server Trigger does the reverse: it exposes the workflows sitting in your n8n to an outside agent. This exercise is the client. The server is the step after, and it is the more entertaining one, because that is where your task bot becomes a tool other assistants can call.

What you learn: where the ceiling of one-node-per-service sits, and what lies above it. This is the point where your bot stops being an exercise and becomes a piece of something larger.

Guard rails

Three habits that keep you from breaking what already works.

🛟

Anything that leaves your server can fall over

Continue On Fail on every calling node, without exception. A service that is down should produce a terse answer, never a silent bot.

🤝

Free does not mean unlimited

These services are run by public offices and by associations. Call them when someone asks you to, not every thirty seconds. Keeping the last answer for a few minutes is almost always enough.

🔑

A secret does not go inside a node

The moment an exercise asks for a token, go through Settings → Credentials, the place where n8n keeps secrets outside the workflow file, exactly as you did for the four accesses during installation. A secret written in plain sight inside a workflow travels with the file the day you share it.

Glossary

The eight words this page leans on.

Kept here so you can come back to one without rereading the exercise it first appeared in.

Workflow

The whole picture in the n8n editor: boxes joined by lines, running left to right when something sets them off. Your bot is one workflow, and the exercises above extend it.

Node

One box in that picture, doing one job: receiving a message, calling an address, writing a sentence, saving a row. Joining nodes together is how you say what happens in which order.

Webhook

An address your workflow keeps open so that another service can push events to it the moment they happen, instead of your workflow asking over and over. Telegram uses one to hand each new message to your bot.

API and endpoint

An API is a web address built to answer with data rather than with a page for human eyes. An endpoint is one precise address inside it, with its parameters. Every exercise on this page calls a single endpoint.

HTTP request

One call to such an address. GET asks for data, POST sends some. The answer carries a status code, and 200 means the call itself went through, which says nothing at all about whether you asked the right question.

JSON

The text format the answers come back in: named fields holding values, lists, or further fields. null means a field exists but holds nothing, and [0] reaches the first item of a list. Reading JSON is most of the work in these exercises.

OAuth2 and tokens

A login method in two steps: you send a client identifier and a client secret to an authentication address, it hands back a token, and you show that token on every call afterwards. Tokens expire on purpose, so your workflow has to be able to ask for a fresh one.

MCP

Short for Model Context Protocol. A server publishes a list of tools with descriptions written for a language model to read, and the model decides when to call them. It replaces the habit of hand-building one node per service.

What now

You do not have the template yet?

These exercises start from the bot as delivered: the Switch node holding the commands and the Telegram node are already there, and you only have to connect to them. If you would rather see what there is to set up first, the installation guide is online, all seven steps of it.

The gadgets on this page are not in the file you download, and that is deliberate. What you buy is a bot that works, plus enough explanation to see how it works.