The ceiling of other people's products
Everything so far has been about using tools someone else built. Those tools are good, and they have a hard ceiling: they do what their designer imagined. The moment you want AI inside your thing — triaging your support queue, tagging your photos, summarising your database rows at 3am — no product will do it, because your thing is yours.
That's what the API is for. It's the same model you've been talking to, minus the interface, addressable from code.
A chat window is one application built on the API. You're about to build the second one.
The key, and the one mistake that matters
Access starts with an API key — a long secret string you generate in your provider's console. Every request carries it, and the bill follows it.
Which means the key is your credit card. And there's exactly one mistake that accounts for most leaked keys: putting it somewhere the browser can see.
Anything in frontend JavaScript is public. Not obscured, not hard to find — public. "View source" public. If your key is in the browser bundle, strangers will spend your money with it, usually within days.
So: where does the key go?
.env to .gitignore before you create it, not after.Anatomy of a call
Underneath every AI product is one HTTP POST. Here's a complete request. Click any highlighted part to see what it does.
The response comes back as JSON. Two fields matter immediately — the text, and what it cost you:
content is an array of blocks, not a string. Today it might hold one text block; with tools or thinking enabled it holds several of different types. Code that does content[0].text works until the day it doesn't — filter by type instead.
What it actually costs
You're billed per token, separately for what you send and what you get back — and output costs several times more than input. Tokens are chunks of text; roughly one token ≈ 4 characters, so ~750 words is about 1,000 tokens.
The surprise for most people isn't the per-request price, it's the multiplication. Pennies times a thousand users a day is a real number. Try it:
Three levers, in the order worth pulling them. Send less — most prompts carry padding nobody needs. Cache the repeated part — if every request shares the same long instructions, prompt caching makes that prefix far cheaper on repeat. Then consider a smaller model, measuring quality rather than assuming.
Why streaming matters
A model generates one token at a time. You can either wait for all of them and show the finished answer, or forward each one as it arrives. The total time is identical. The felt time is not.
Run both and watch the timers:
Same model, same answer, same finish time. One of them felt broken for two seconds. That gap is why nearly every chat interface streams — and it's a one-word change:
The response arrives as a sequence of server-sent events rather than one JSON body, so your code reads it as a stream and appends each fragment as it lands. There's a second, unglamorous reason to stream: long responses on a non-streaming request can hit HTTP timeouts. Streaming avoids that entirely.
Your first feature
Put the pieces together. A server route that takes text and returns a one-line summary — the smallest complete AI feature, and the shape of almost every one you'll build after it:
That's the whole thing. Note what it does not do: no key in the browser, no content[0], and a max_tokens low enough that a runaway response can't quietly cost you.
fetch — it handles retries, timeouts, streaming and typed errors for you. Raw HTTP is shown here because it makes the shape of the request visible; the SDK is the same call with the sharp edges filed off.
What you can build now
You can now put a model inside anything that can make an HTTP request — a cron job, a webhook, a form handler, a CLI. That's a genuinely different position than picking between other people's products.
What you can't do yet is give the model access to your information. It knows what you paste into it and nothing else. That's the next problem.
- The key is a credit card. Server-side only, never in the browser, never in git. Set a spend limit today.
- One POST, four fields. Model, max_tokens, messages, and your key in a header.
- Read the response properly.
contentis an array of typed blocks. - Cost multiplies. Send less, cache the repeated prefix, then consider a smaller model.
- Stream anything a human waits for. Same total time, completely different experience.