Why we don’t call AI directly from the browser
AI services (OpenAI, Anthropic, and others) require an API key – a secret code that identifies you and is used for billing. And here’s the catch:
Anything you put into JavaScript in the browser can be read by anyone (F12 → source code). If your key were there, anyone could call the AI using your money.
You already know the solution from Master: your own server. The key stays on the server, and the browser only talks to your server:
Browser → your server (the key is here!) → AI service
Browser ← your server ← AI service
Show me: the /zeptat-se endpoint
We’ll build on the Express server from Master. We’ll store the key in a .env file (this never goes on GitHub – add it to .gitignore!):
AI_KLIC=sk-your-secret-key-here
And the server gets a new endpoint:
require('dotenv').config();
const express = require('express');
const app = express();
app.use(express.json());
app.use(express.static('public'));
app.post('/zeptat-se', async (req, res) => {
const { otazka } = req.body;
const odpoved = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.AI_KLIC}`,
},
body: JSON.stringify({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: 'You are a friendly helper. Answer briefly in English.' },
{ role: 'user', content: otazka },
],
}),
});
const data = await odpoved.json();
res.json({ text: data.choices[0].message.content });
});
app.listen(3000, () => console.log('Server running at http://localhost:3000'));
What’s new here:
fetchcan also send data:method: 'POST'andbody.- The
headerswithAuthorization– that’s where the key gets presented. role: 'system'– that’s your prompt from the last lesson! It defines how the AI behaves.process.env.AI_KLIC– the key is read from.env, not written in the code.
Where do I get a key? AI services issue API keys after registration – and it’s usually paid (though cheap, just cents per answer). This is a job for a parent: ask them to create a key for you and add a small amount of credit (a few dollars is enough). Without a key, you can still test with a made-up response – see “Your turn” below.
Your turn 💪
- Add a line
.envto.gitignore– check it with thegit statuscommand (the.envfile must not show up). - Create the
/zeptat-seendpoint following the example. - Don’t have a key? No problem – just return a test response for now and continue to the next lesson:
app.post('/zeptat-se', (req, res) => {
res.json({ text: `Test answer to: "${req.body.otazka}"` });
});
- Try the endpoint from the browser (F12 console):
const r = await fetch('/zeptat-se', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ otazka: 'Hi, who are you?' }),
});
console.log(await r.json());
Check: The server responds to POST /zeptat-se (with a test or real AI answer), and the secret key is neither in the code nor on GitHub.
What to take away from this lesson
- Secret keys belong on the server in
.env, never in the browser or in Git. fetchcan do POST – it sends data inbody, and the key inheaders.- The system prompt shapes the personality of your AI helper.
© 2026 Ing. Martin Polak / AlgoRhino · Content usage terms