Your first LLM API call: a key, one request, and the reply
Before an agent, one call. Create an OpenRouter account and API key, send a single request with curl, and read every part of the reply that comes back, from the answer itself to what it cost.
This page works on one stage of the loop
- 1Build the request
- 2Call the model (this page)
- 3Run the tools
- 4Decide
An agent makes many calls to a model, but each one is an ordinary HTTP request: some JSON goes out, some JSON comes back. Making one by hand first, before any Go, shows exactly what your program will be sending and reading.
Why OpenRouter
The examples on this site call models through OpenRouter, a service that puts hundreds of models from different companies behind one API. Its API uses the chat completions format that OpenAI introduced and most providers and local model servers now accept, so the code you write for it works elsewhere with a different address and key. Switching models is a change to one string, which makes it easy to compare them.
Calling a provider directly, such as Anthropic or OpenAI, works the same way in principle; Providers and SDKs covers what changes.
An account and a key
- Create an account at openrouter.ai.
- Add a few dollars of credit. Credit is prepaid, so when it runs out, requests fail with a 402 error instead of running up a bill. Five dollars covers every early example many times over.
- Create an API key, the secret string that identifies your account on every request. Give the key its own credit limit, so a bug in your agent can’t spend more than you set aside for it.
- Put the key in your shell’s environment:
$ export OPENROUTER_API_KEY=sk-or-...
Keep the key out of your code and out of git. A key that lands in a public repository is often found and used by someone else within minutes.
One request
Here is a complete request, sent with curl.
It asks one question, with one instruction about how to answer:
$ curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-haiku-5.5",
"messages": [
{"role": "system", "content": "You are a helpful assistant for Go programmers. Answer in a few sentences."},
{"role": "user", "content": "What is a goroutine?"}
]
}'
The body has two parts:
modelnames the model, as the company that made it, a slash, and the model’s name.messagesis the conversation so far, in order. Each message has a role and some content. Thesystemmessage holds your instructions; theusermessage holds the question. Messages, roles, and the system prompt covers all four roles.
The reply
This is the reply to exactly that request, recorded in October 2026 and kept in the companion code:
"response": {
"id": "gen-1792089532-o8GmWe9RWmRogh5nKozP",
"object": "chat.completion",
"created": 1792089532,
"model": "anthropic/claude-haiku-5.5",
"provider": "Claude Platform on AWS",
"system_fingerprint": null,
"service_tier": "default",
"choices": [
{
"index": 0,
"logprobs": null,
"finish_reason": "stop",
"native_finish_reason": "end_turn",
"message": {
"role": "assistant",
"content": "A goroutine is a lightweight thread of execution managed by the Go runtime rather than the operating system. You start one by placing the `go` keyword before a function call, such as `go doSomething()`, and it runs concurrently with the rest of your program. Goroutines are cheap to create (they start with a small, growable stack), so a Go program can run thousands or even millions of them at once.",
"refusal": null,
"reasoning": null
}
}
],
"usage": {
"prompt_tokens": 43,
"completion_tokens": 122,
"total_tokens": 165,
"cost": 0.0000653,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 0.0000653,
"upstream_inference_prompt_cost": 0.0000043,
"upstream_inference_completions_cost": 0.000061
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
}
}
Most of it you can ignore at first. The parts an agent reads:
choices[0].messageis the model’s reply: a message with the roleassistantand the answer incontent. To continue the conversation, you append this message to your list and add the nextusermessage after it.finish_reasonsays why the model stopped writing.stopmeans it finished on its own.lengthmeans it ran out of room and the answer is cut off; an agent has to check this on every reply, as Common first errors shows. Later,tool_callswill mean the model wants your program to run tools.usagecounts the tokens, the pieces of text the model reads and writes: 43 in, which covers both messages plus some formatting, and 122 out.costis what this call cost in dollars: $0.0000653, or about 15,000 calls like it per dollar.modelandprovidersay which model answered and which company’s servers ran it. OpenRouter may send the same model to different hosts on different calls.
The model remembers nothing
Send the same request again and the model has no idea it answered before. Each request carries the whole conversation, and the model reads only what’s in it. To ask a follow-up question, your program sends the system message, the first question, the model’s answer, and the new question, all together.
That one fact shapes everything an agent does: its requests grow with every turn, and so does what each turn costs. Tokens, cost, and context measures how fast.
The same call from Go
The chat program in the companion code makes exactly this call, and continues the conversation for as long as you type:
$ go run ./ch02
With OPENROUTER_API_KEY set, it talks to the live model and prints the tokens and cost of each reply.
Without the key, it replays the recorded conversation above, so you can see the output first:
No OPENROUTER_API_KEY: replaying a saved conversation.
> What is a goroutine?
A goroutine is a lightweight thread of execution managed by the Go
runtime rather than the operating system. You start one by placing the
`go` keyword before a function call, such as `go doSomething()`, and
it runs concurrently with the rest of your program. Goroutines are
cheap to create (they start with a small, growable stack), so a Go
program can run thousands or even millions of them at once.
[43 tokens in, 122 out, $0.000065; total $0.000065]
Calling a model from Go builds that client in under two hundred lines of standard-library Go.