The weather page in this series uses Open-Meteo, which is free for non-commercial use and doesn't need a key. That's unusual. Most APIs want to know who's asking, and that's where keys come in. This part explains how they work, why some must be kept secret and where they should live, then covers the limits and costs that come with them.
Every key in this post is made up. They look like DEMO-KEY-0000-NOT-REAL so there's no doubt.
An API key is a membership card
When you sign up with an API provider, they give you a key: a long, random string that you send with every request. It doesn't prove what you are. It proves which account you belong to, so the provider can apply the right plan, count your usage and send you the bill.
An API key is a membership card
LikeShowing your card at the gym door
GET /v1/forecast?city=welwynAuthorization: Bearer DEMO-KEY-0000-NOT-REAL
LikeThe front desk scans it
Whose key is this? Is it still valid? What does their plan allow? How much have they used this month?
LikeIn you go, or "your membership has lapsed"
- 200 with the data, counted against your allowance
- 401 no key or a wrong one
- 429 over the limit
Because a key is tied to an account, anyone who has it can use that account. That's why the next question matters most: who can see it?
Public and private keys
Some keys are designed to be public, and some must never be. The difference is a bit like your house number and your house key.
Your house number versus your house key
LikeYour house number. It's on the front door, and that's fine.
- Everything in a web page or app: the HTML, the JavaScript, the network requests
- Anything in the browser's developer tools
- OK here: "publishable" or "site" keys made to be public, such as the reCAPTCHA site key and the Formspree form ID on this site's contact form
LikeYour house key. Whoever has a copy can let themselves in.
- Your own server, or a serverless function
- A secrets store, such as GitHub Secrets
- Belongs here: secret keys, passwords and anything that can spend money, read customer data or change things
The rule of thumb is simple: anything sent to the browser is public. Web pages, scripts and app code can all be opened and read by anyone who's curious, and some people go looking for keys on purpose.
Where a secret key travels
So if a secret key can't be in the page, how does the page use the API? It asks your own server, and your server adds the key on the way out.
Where a secret key travels
Don't
Browser
JavaScript holds DEMO-KEY-0000-NOT-REAL
The API
Works, but anyone who opens the page's code can copy the key and use your allowance
View this page's code, like a curious visitor would
fetch("https://api.example.com/v1/forecast?city=welwyn", {
headers: { Authorization: "Bearer DEMO-KEY-0000-NOT-REAL" }
})There it is, highlighted. Copy, paste, and someone else is using your account.
Do
Browser
Asks your server, with no key
Your server
Adds the key from its secret settings, checks the request is reasonable
The API
Answers your server, which passes the data back
View this page's code now
fetch("/api/weather?city=welwyn")
// No key in here. It lives on the server.LikeA customer never gets the key to the till. They pay the cashier, and the cashier opens the till.
The server in the middle is often tiny: a single "serverless" function that does nothing but take the request, add the key and pass the answer back. It's also a good place to check the request is sensible and to stop anyone using it to run up your bill.
Keeping keys out of the code with GitHub Secrets
The other place a key must never be is in the code itself. Code gets copied, shared, reviewed and stored in the history forever. A key pasted into a file is still in the history after someone deletes it.
The usual answer is a secrets store. Code on GitHub can use GitHub Secrets: you save the key once in the repository's settings, and the code refers to it only by name. This site's own deploy works the same way: the details it needs to upload the site are saved as secrets, so they never appear in the code.
How a key gets from the provider to your server
Sign up, open their dashboard and create a key. Copy it once. Treat it like a password.
In the repository: Settings, then Secrets and variables, then Actions, then New repository secret. Name it WEATHER_API_KEY, paste the value and save. From then on nobody, you included, can read it back in GitHub. They can only replace it.
When code is released, GitHub Actions hands the secret to the server as a setting, referring to it only by name: ${{ secrets.WEATHER_API_KEY }}. If it ever appears in a log, GitHub blanks it out.
Reads the setting when it calls the API: process.env.WEATHER_API_KEY. The code, and everyone who can read it, only ever sees the name.
LikeA key safe by the door. Everyone knows there's a key in it and what it's for, but only the people you give the code to can open it, and you can change the code without changing the lock.
One catch is worth knowing. GitHub Secrets keeps a key out of the code, but it doesn't make a key safe to put in a web page. If a build step pasted a secret into the HTML or JavaScript, it would be public again the moment someone visited. A secret should only ever reach server code, as in step 4.
And if a key does leak, the fix is the same as for a lost house key: change the locks. Create a new key in the provider's dashboard, save it over the old secret, release, then cancel the old one.
Limits, quotas and costs
Most APIs come with small print. In restaurant terms:
The small print, in restaurant terms
A buffet where you take one plate at a time
The most requests allowed per second or minute. Go over and you get a 429.
A set-menu deal: ten lunches a month
A daily or monthly allowance. When it runs out, requests fail or start to cost extra.
À la carte: you pay for each dish
Often free up to a point, then priced per thousand requests, so cost grows with your traffic.
"No outside food, and no reselling our cakes"
What you may do with the data. Open-Meteo's free tier, for example, is for non-commercial use only.
Try it: run into a rate limit
LikeA buffet that lets you take five plates every ten seconds. Keep pressing and see what the kitchen says.
These matter most at the worst possible moment. A rate limit that's fine on a normal Tuesday can bite on Black Friday, and a free tier that covers a prototype may not cover a launch.
Questions to ask before you integrate
Next time an API turns up in a feature, these questions are worth asking early:
- Do we need a key, and is it public or secret? If it's secret, where will it live and who can see it?
- Who owns the account? Whose card is on it, who gets the alerts, and what happens when that person leaves?
- What are the limits? Compare them with your expected traffic at its busiest, not on average.
- What will it cost at ten times today's usage?
- What do the terms allow? Commercial use, storing the data, showing it alongside a competitor's?
- What data are we sending? If it includes anything personal, check it with whoever owns privacy.
- How reliable is it? Is there a status page, and a promise on uptime?
- How do they handle change? How much notice do they give before retiring a version?
- Is there a test mode? Can the team build against pretend data before going live?
- What does our product do when it fails? Agree it now and write it into the acceptance criteria.
Part 5 brings it all together, taking the weather page apart from end to end.