Skills101

AI Engineering — Building Apps with Large Language Models · Lesson 2 of 12 · Updated ·

Your First LLM API Call — Keys, the Python SDK, Responses, Tokens and Cost

Chat websites are for people. APIs are for programs: your app sends a request and gets the model's answer back as data. We use Claude (by Anthropic) and its official Python SDK; other providers' APIs follow the same ideas.

1. Setup and keys

pip install anthropic

Create an API key in the provider's console and keep it secret:

  • Put it in an environment variable — ANTHROPIC_API_KEY — never in your code.
  • Never commit it to GitHub (bots scan public repos for keys within minutes).
  • Never put it in a website or mobile app: anyone can extract it. Calls go through your server.
  • Set a monthly spending limit in the console.

2. A first call

A request has a model, max_tokens, an optional system prompt and messages; the response has content blocks, a stop reason and token usage

import anthropic

client = anthropic.Anthropic()          # reads ANTHROPIC_API_KEY from the environment

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1000,                    # upper limit on the answer's length
    messages=[{"role": "user", "content": "Explain recursion to a first-year student in one sentence."}],
)

for block in response.content:          # the answer is a list of content blocks
    if block.type == "text":
        print(block.text)
print("stop reason:", response.stop_reason)
print("tokens in/out:", response.usage.input_tokens, response.usage.output_tokens)

Output:

Recursion is when a function solves a problem by calling itself on a smaller version of the same problem, until it reaches a simple case it can answer directly (the base case).
stop reason: end_turn
tokens in/out: 38 51

(Output from our local stand-in API — a real model's wording will differ; the structure is identical.)

  • messages is the conversation: alternating user and assistant turns.
  • content is a list of blocks — usually text; later you'll see tool calls too. Always check block.type.
  • stop_reason: end_turn (finished), max_tokens (cut off — raise the limit), tool_use (wants a tool), refusal (declined for safety).
  • usage reports the tokens you pay for.

Older tutorials set temperature. On current Claude models sampling settings like temperature are no longer accepted — you steer the output with the prompt (and, for reasoning depth, an effort setting).

3. System prompts

import anthropic

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=500,
    system="You are a patient programming tutor for Indian college students. Never give full solutions; ask a guiding question.",
    messages=[{"role": "user", "content": "My loop prints numbers forever. Help?"}],
)
print(response.content[0].text)
Good question! Think about what changes each time the loop runs — what should the loop stop on?

The system prompt sets the role, rules and tone for the whole conversation; the user message is the specific request.

4. What does it cost?

Prices are per million tokens (MTok), different for input and output. Always check the provider's current pricing page; at the time of writing, Claude's models were priced like this:

PRICES_USD_PER_MTOK = {             # (input, output) — check the current pricing page before you budget
    "claude-opus-5-5": (4.00, 20.00),
    "claude-sonnet-5-5": (2.00, 10.00),
    "claude-haiku-5-5": (0.10, 0.50),
}
USD_TO_INR = 85                     # use today's rate

def cost_inr(model, input_tokens, output_tokens):
    price_in, price_out = PRICES_USD_PER_MTOK[model]
    usd = input_tokens / 1e6 * price_in + output_tokens / 1e6 * price_out
    return usd * USD_TO_INR

# a help-desk answer: 2,000 tokens of instructions + documents in, 300 tokens out
for model in PRICES_USD_PER_MTOK:
    one = cost_inr(model, 2000, 300)
    print(f"{model:18s} ₹{one:.3f} per answer   ₹{one * 10_000:,.0f} per 10,000 answers")
claude-opus-5-5    ₹1.190 per answer   ₹11,900 per 10,000 answers
claude-sonnet-5-5  ₹0.595 per answer   ₹5,950 per 10,000 answers
claude-haiku-5-5   ₹0.030 per answer   ₹298 per 10,000 answers

Rules of thumb: input tokens usually dominate (long instructions and documents), so keep prompts lean; use the most capable model where quality matters and test whether a smaller one is good enough for simple, high-volume tasks. Lesson 10 covers caching and other ways to cut costs.

5. Errors and retries

import anthropic

client = anthropic.Anthropic(max_retries=3, timeout=60)   # the SDK retries 429/5xx automatically
try:
    response = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=300,
        messages=[{"role": "user", "content": "Summarise: the team shipped login, found two payment bugs, fixing by Friday."}],
    )
    print(response.content[0].text)
except anthropic.RateLimitError:
    print("Too many requests — slow down or queue them.")
except anthropic.APIStatusError as e:
    print("API error", e.status_code, e.message)
except anthropic.APIConnectionError:
    print("Network problem — check the connection.")
Summary: the team shipped the login feature, found two bugs in payments, and will fix them before Friday.

Catch specific errors: rate limits (429) need backing off, bad requests (400) need a code fix, server errors (5xx) can be retried.

6. Practise for free

Our lessons' code was checked against a small local stand-in for the API that answers in the same format (fixed, canned answers — not real intelligence). You can use it too when you don't have a key or credit yet: download llm_stub.py, run python llm_stub.py, then set ANTHROPIC_API_KEY=test and ANTHROPIC_BASE_URL=http://127.0.0.1:4010. Your code runs unchanged — later, remove those two settings and use a real key.

Common mistakes

  • API key in the source code or in the browser.
  • Reading response.content[0].text without checking the block type or stop_reason.
  • max_tokens too small → answers cut off (stop_reason == "max_tokens").
  • No spending limit while experimenting with loops.

Quick recap

  • Key in an environment variable; calls go through your server.
  • client.messages.create(model, max_tokens, system, messages).
  • Read content blocks, check stop_reason, watch usage.
  • Cost = input tokens × input price + output tokens × output price; catch specific errors.

Practice what you learned

📝 Quiz: First API Call5 questions · instant answers & explanations · +10 XP · counts towards your free certificateTake the quiz →