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

Source: https://skills101.in/learn/ai-engineering/claude-api-python-first-call — Skills101 free tutorial (AI Engineering — Building Apps with Large Language Models). Updated 2026-11-09.

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

```text
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](https://skills101.in/learn-img/ai-engineering/api-call.svg)

```python
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:

```text
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

```python
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)
```

```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:

```python
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")
```

```text
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

```python
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.")
```

```text
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](https://skills101.in/tutorial-files/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 quiz and free certificate: https://skills101.in/learn/ai-engineering/claude-api-python-first-call