Your First LLM API Call
From zero to a working request, plus the four errors that catch everyone on the way.
On this page
Every provider’s API has the same shape. Learn one and the rest are variations.
The anatomy of a request
Four parts, always:
Endpoint and authentication. An HTTPS URL plus an API key in a header.
Model identifier. Which model, as a string.
Messages. A list of role-tagged messages — system, then alternating user and assistant turns.
Parameters. Temperature, maximum output tokens, and whatever else you want to control.
The response comes back with the generated message, a reason it stopped, and a token count for input and output.
The minimal shape
Conceptually, in any language:
POST https://api.provider.com/v1/messages
Authorization: Bearer $API_KEY
{
"model": "<model-id>",
"max_tokens": 1024,
"system": "You are a concise technical assistant.",
"messages": [
{"role": "user", "content": "Explain what a token is in one sentence."}
]
}
Provider SDKs wrap this, and using one is worth it — they handle retries, streaming, and error types for you. The raw shape is worth knowing anyway, because it explains what the SDK is doing.
Exact endpoints, model IDs, and parameter names differ per provider and change over time. Read the current docs for those specifics rather than trusting any example, including this one.
Keys
Never put a key in your source code, and never in client-side code. A key in a frontend bundle is public the moment you deploy.
Use an environment variable, and add your env file to .gitignore before writing the key into it. If a key is ever committed, rotate it — deleting the commit does not un-leak it.
For browser or mobile applications, calls must go through your own backend. The client talks to your server; your server holds the key and talks to the provider. This is not optional, and it also gives you the only place where rate limiting and abuse controls can live.
The four errors everyone hits
401 — authentication failed
The key is wrong, missing, expired, or has stray whitespace. Check that your environment variable is actually loaded — this is more often the cause than a bad key.
429 — rate limited
You exceeded a request or token limit. Retry with exponential backoff and jitter: wait, double the wait each time, add randomness so concurrent clients do not retry in lockstep. Respect a retry-after header if one is present.
This is not an edge case. Build backoff in from the beginning, because it is the error you will hit most in production. Most SDKs include it — confirm rather than assume.
400 — context length exceeded
Your input plus requested output exceeds the model’s context window. Remember output shares that budget.
Fix by trimming input, capping conversation history, or retrieving less.
Truncated output
Not an error — the response simply stopped. Check the stop reason field. If it indicates a length limit, your max_tokens was too low. This confuses people because the request succeeded and the answer is just missing its ending.
Things worth getting right immediately
Set max_tokens deliberately. Too low truncates; too high permits an expensive runaway. It is a cap, not a target.
Temperature 0 for anything extractive. Classification, extraction, structured output. Save higher values for conversational or creative work.
Handle timeouts. Long generations take time. Set a generous timeout and expect the occasional hang.
Log token counts from the start. The response includes them. Logging them is how you discover cost problems before the bill does.
Retry only what is retryable. 429 and 5xx: retry. 400 and 401: retrying is pointless, the request itself is wrong.
Cost, mechanically
You pay per token, input and output priced separately, with output the more expensive.
The trap is conversation history. Because the model has no memory between calls, every turn resends the entire transcript — so cost grows with the square of conversation length. Cap history deliberately rather than letting it grow until something breaks.
See Which Model Should You Use? and Cutting Your API Bill.
What to remember
- Every request is endpoint + auth, model ID, messages, parameters.
- Keys belong in environment variables and on servers — never in client code.
- Four errors: 401 auth, 429 rate limit (needs backoff), 400 context overflow, and silent truncation from a low
max_tokens. - Set
max_tokensdeliberately, use temperature 0 for extraction, and log token counts from day one. - Conversation cost grows quadratically because history is resent every turn.