Skip to main content
How-to Getting started

Call an LLM API for the first time

Send your first request to a model from code instead of a chat window, and learn to read what comes back. One runnable example, plus what changes when you swap providers.

6 steps8 min readLast verified August 2026

What you’ll learn

  • Get an API key from a hosted provider, or skip the key entirely by pointing at a local Ollama server.
  • Install the SDK for the endpoint you are calling.
  • Send a first chat completion request from code and get a real reply back.
  • Read the response object: which field holds the reply text, and what the other fields tell you.
  • Store the API key in an environment variable instead of writing it into your code.
  • Recognize the OpenAI-compatible Chat Completions shape most providers share, and how Anthropic's Messages API differs.

So far you may have only talked to a model through a chat window: type a prompt into a page someone else built, read the reply on that same page. An API call is the same idea with the page removed. Your own code sends the prompt and gets the reply back as data, ready to use however you want. This walks through making that first call, reading what comes back, and keeping the key out of the code you write.

New to this? An API key is a long string that proves a request came from your account, the way a password proves who you are. An SDK, short for software development kit, is a small library you install that saves you from writing the raw network request by hand. Neither needs more Python or JavaScript than what appears in the code below.
Before you start: Python 3.8 or newer, or Node 18 or newer, already installed; a terminal; and either an API key from a hosted provider (a free account is enough to get one) or a local Ollama server already running, which needs no key at all. If you have not set up Ollama yet, Run your first local model with Ollama covers it in about ten minutes.

1. Get a key, or point at a local server instead

There are two ways to make this first call, and they lead to the exact same code in step 3. Hosted: create an account with a provider such as OpenAI, then generate a key from its dashboard, a string that starts with sk- and is shown to you exactly once.1 Local: install Ollama and it runs its own OpenAI-compatible server on your machine at http://localhost:11434/v1, no signup, no key, no per-token cost.4

Check: either you have a string starting with sk- saved somewhere safe, or running curl http://localhost:11434/v1/models on your machine returns a JSON list instead of a connection error.

2. Install the SDK

One package talks to any OpenAI-compatible endpoint, hosted or local, since the request and response shapes are the same either way.1

Python
pip install openai
JavaScript
npm install openai
Check: python -c "import openai; print(openai.__version__)" prints a version number, not an error.

3. Make the call

This is the same three lines whether you are pointed at a hosted account or a local server. Only the client setup changes.

Call a hosted model (Python)
from openai import OpenAI

client = OpenAI()  # reads the key from OPENAI_API_KEY automatically
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(response.choices[0].message.content)
Same code, pointed at a local Ollama server instead
from openai import OpenAI

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
response = client.chat.completions.create(
    model="qwen2.5-coder:7b",
    messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(response.choices[0].message.content)
The same call in JavaScript
import OpenAI from "openai";

const client = new OpenAI(); // reads OPENAI_API_KEY automatically
const response = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Say hello in one sentence." }],
});
console.log(response.choices[0].message.content);
Running the JavaScript version: save it as a file ending in .mjs, or add "type": "module" to your package.json, so the top-level await works. Then run it with node yourfile.mjs.
Check: the script prints a single sentence, not a stack trace. An authentication error here almost always means the key is not set where the SDK is looking, covered in step 5.

4. Read the response object

The reply is not just a string, it is an object with the text nested inside, plus metadata about the call.2 The fields that matter for a first call:

FieldWhat it tells you
response.choices[0].message.contentThe reply text. This is what you printed above.
response.choices[0].finish_reason"stop" for a natural end, "length" if it hit a token limit before finishing.
response.modelWhich model actually answered. Providers sometimes route a name to a specific dated snapshot.
response.usage.total_tokensInput tokens plus output tokens. On a hosted provider, this is what you are billed for.
Check: add print(response.model) and print(response.usage) next to the reply, and compare them against what you asked for.

5. Keep the key out of your code

Never write the key as a literal string inside a file you might commit. The SDK already looks for it in an environment variable, so set it there instead and the line OpenAI() from step 3 picks it up with no arguments.1

macOS or Linux (Terminal)
export OPENAI_API_KEY="sk-..."
Windows (PowerShell)
$env:OPENAI_API_KEY = "sk-..."

For a project you will reopen later, put the key in a .env file in the project folder and load it at the top of your script, instead of retyping the export every time you open a new terminal.

One extra package
pip install python-dotenv
Add above the client = OpenAI() line
from dotenv import load_dotenv
load_dotenv()  # reads .env into the environment before OpenAI() runs
Check: add .env to .gitignore before your first commit. A key that reaches a public repository should be treated as already compromised, rotate it from the provider dashboard rather than assuming no one found it.

6. One shape, many providers, and Anthropic's different one

The call in step 3, client.chat.completions.create with a list of {role, content} messages, is not specific to one company. Ollama's local server replies to the exact same shape, which is why step 3 only needed a different base_url and api_key, not different code.4 Other providers that describe themselves as "OpenAI-compatible" work the same way: swap base_url, api_key, and model, keep everything else.

Not every provider uses that shape, though. Anthropic's Messages API is a different one: max_tokens is a required field on every request rather than an optional limit, and the reply's text sits inside a list of typed content blocks instead of a plain string.3

The same idea, Anthropic's Messages API shape
import anthropic

client = anthropic.Anthropic()  # reads the key from ANTHROPIC_API_KEY automatically
message = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(message.content[0].text)
Check: compare message.content[0].text here against response.choices[0].message.content from step 3. Same intent, a different path to reach it, which is exactly the kind of difference to expect when a provider does not advertise OpenAI compatibility.
Key idea
An API call is a request your own code sends and a response it reads back, the same exchange as the chat window, minus the page in between. Get a key or point at a local server, install the SDK, call it, read the object that comes back, and keep the key in an environment variable rather than in a file. Once one shape works, most OpenAI-compatible providers are a base URL and a model name away; providers with their own shape, like Anthropic, need their own SDK and their own reading of the response, not just a swapped URL.
Going further: pass stream=True to get tokens back as they generate instead of waiting for the full reply; add a {"role": "system", "content": "..."} message to set behavior before the user turn; and keep appending to the same messages list across calls to hold a multi-turn conversation. That growing messages list is exactly what the loop in the next guide automates.

Troubleshooting

  • 401 or "invalid API key": the key is not set in the shell running your script, or you are calling a hosted client with no key set at all. Print os.environ.get("OPENAI_API_KEY") to confirm it is there before debugging anything else.
  • 429 or a quota error on a fresh hosted account: some providers require billing details on file before the first paid call succeeds, even for a small request. A local Ollama server has no rate limit or billing step.
  • ModuleNotFoundError: No module named 'openai': the package installed into a different Python than the one running your script. Run python -m pip install openai using the same python you use to run the file.
  • Connection refused against localhost:11434: Ollama is not running. Start it, then confirm with curl http://localhost:11434/v1/models before retrying the SDK call.

You now have working code that sends a prompt and reads a real reply, the same exchange every chat interface is built on top of. From here, Build your first agent takes this exact call and wraps it in a loop that lets the model request a tool and act on the result, and What an AI agent actually is covers the concepts underneath that loop.

Sources

Verified against primary sources: August 2026.

  1. Developer quickstart. OpenAI (official docs). https://developers.openai.com/api/docs/quickstart
  2. Chat Completions API reference. OpenAI (official docs). https://developers.openai.com/api/docs/api-reference/chat/create
  3. Messages API reference. Anthropic (official docs). https://platform.claude.com/docs/en/api/messages
  4. OpenAI compatibility. Ollama docs (official). https://docs.ollama.com/api/openai-compatibility
Read nextBuild your first agent