3Accessing Claude with the API

Making a request

4 min read700 words

Your .env file has a key in it and your editor is open to an empty notebook. The next twenty lines of code will get Claude talking back to you. This lesson walks through every one of them.

1. Install the packages

In your notebook or shell:

%pip install anthropic python-dotenv

anthropic is the official Python SDK. python-dotenv reads the .env file you set up in the previous lesson.

2. Load the environment and create a client

from dotenv import load_dotenv
load_dotenv()

from anthropic import Anthropic

client = Anthropic()
model = "claude-sonnet-4-0"

Three things are happening here:

  • load_dotenv() pulls ANTHROPIC_API_KEY from .env into the process environment.
  • Anthropic() constructs a client. Because ANTHROPIC_API_KEY is already in the environment, you don't have to pass it in — the SDK finds it.
  • model is hoisted to a variable so you can swap tiers in one place instead of chasing string literals through your code.

3. Call client.messages.create()

This is the core function you'll use for every non-streaming request in the course. It takes three required arguments:

  • model — the Claude model to run (e.g. "claude-sonnet-4-0").
  • max_tokens — a ceiling on the response length, in tokens.
  • messages — the conversation history you're sending in.
message = client.messages.create(
    model=model,
    max_tokens=1000,
    messages=[
        {
            "role": "user",
            "content": "What is quantum computing? Answer in one sentence.",
        }
    ],
)

max_tokens is a ceiling, not a target

This trips up everyone once. max_tokens=1000 does not mean "aim for 1000 tokens." It means "stop at 1000 tokens if you're still going." Claude writes what it thinks is appropriate for the prompt and stops. The parameter exists as a safety rail — an upper bound on cost and latency — not as a length hint.

If the response ends mid-sentence and the stop_reason is max_tokens, that's your cue to raise the ceiling. If Claude is returning something shorter than you expected, the fix is in the prompt, not in max_tokens.

What a message looks like

Each entry in messages is a dict with exactly two fields:

  • role"user" for content you send, "assistant" for content Claude has previously generated.
  • content — the text itself (and, later in the course, other block types).

For a first call with a single question, messages is a list of one user message. For anything multi-turn you append assistant and user messages alternately, which is what the next lesson covers.

4. Extract the response text

message.content[0].text

The response object has more on it than just text — we'll get to usage and stop_reason in a moment — but for the happy path, the generated string lives at message.content[0].text. The content is a list because Claude can return multiple content blocks (text, tool calls, images). For a plain text answer there's exactly one block at index zero.

Putting the whole thing together:

from dotenv import load_dotenv
load_dotenv()

from anthropic import Anthropic

client = Anthropic()
model = "claude-sonnet-4-0"

message = client.messages.create(
    model=model,
    max_tokens=1000,
    messages=[
        {"role": "user", "content": "What is quantum computing? Answer in one sentence."}
    ],
)

print(message.content[0].text)
print("stop_reason:", message.stop_reason)
print("usage:", message.usage)

Run that. You should see a one-sentence definition, a stop_reason of end_turn, and an object telling you exactly how many input and output tokens that call cost you.

That's your first real Claude request. Everything else in this course is a more elaborate version of this same three-argument call.

Key Takeaways

  • 1Every Claude request comes down to client.messages.create() with three arguments: model, max_tokens, and messages.
  • 2max_tokens is a safety ceiling, not a target length — Claude writes as much as the prompt warrants and stops, unless truncated by the limit.
  • 3Messages are dicts with a role (user or assistant) and content, and for a first call you send a list containing a single user message.
  • 4The response text lives at message.content[0].text because content is a list that can also carry tool calls and other block types you will meet later.
  • 5The Anthropic SDK picks up ANTHROPIC_API_KEY from the environment automatically, so Anthropic() with no arguments is the standard way to construct a client.