Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

Calling an API for the first time

Python, From Zero, For AI · lesson 10 of 10 · 9 min

An API is a front desk for a program

When you open a web page, your browser sends a request to a server and gets a page back. An API is the same conversation, but the reply is data meant for a program rather than a layout meant for eyes. You send a request. You get a response. The response has a status code and a body, and the body is usually JSON, which lesson eight showed you how to turn into a dict.

That is the entire idea. Everything else is detail.

A call you can run right now

Inside an activated virtual environment with requests installed:

python
import requests

r = requests.get("https://api.github.com/repos/python/cpython", timeout=10)

print(r.status_code)
data = r.json()
print(data["full_name"])
print(data["stargazers_count"])
print(data["language"])

No account, no key. Four things to notice.

requests.get sends the request and waits. timeout=10 says give up after ten seconds; without it a program can hang indefinitely, and a hang is harder to debug than a failure. Always pass a timeout.

r.status_code is the server's one-word summary of how the conversation went:

  • 200 — fine
  • 401 — your credentials are missing or wrong
  • 403 — recognised, but not allowed
  • 404 — no such thing at that address
  • 429 — too many requests, slow down
  • 500 and up — the server broke, not you

r.json() parses the response body into Python dicts and lists. It fails if the body is not JSON, which is what happens when an error page comes back as HTML. If you are unsure what arrived, print r.text first.

Add r.raise_for_status() after the call and any 4xx or 5xx becomes an exception instead of quietly flowing into code that expects data.

Sending data, and sending a key

AI APIs need two more things: you send a body with POST instead of asking with GET, and you identify yourself with a key.

python
import os
import requests

API_KEY = os.environ["ANTHROPIC_API_KEY"]
MODEL = "claude-sonnet-4-5"   # model ids change; check the provider's docs

r = requests.post(
    "https://api.anthropic.com/v1/messages",
    headers={
        "x-api-key": API_KEY,
        "anthropic-version": "2023-06-01",
        "content-type": "application/json",
    },
    json={
        "model": MODEL,
        "max_tokens": 300,
        "messages": [
            {"role": "user", "content": "Explain gravity in one sentence."}
        ],
    },
    timeout=60,
)

print(r.status_code)
reply = r.json()
print(reply["content"][0]["text"])

You have seen every piece of that before. headers is a dict. json= takes a dict and requests converts it for you. The messages value is a list of dicts, exactly the structure you built in lessons four and six. The reply is a dict, and reply["content"][0]["text"] is a lookup, a position, and another lookup.

This one costs money and needs an account, so it may not be the one you run today. Every provider's shape differs slightly; read their docs for the exact keys. The pattern does not differ.

Keys

A key is a password that spends your money. Three rules.

Never type it into your code. Put it in the environment instead:

bash
export ANTHROPIC_API_KEY="sk-..."     # macOS or Linux
$env:ANTHROPIC_API_KEY = "sk-..."     # Windows PowerShell

Never commit it. If a key has ever been in a file you pushed anywhere public, treat it as leaked and replace it at the provider. Deleting the line in a later commit does not help; the old commit is still in the history, and automated scanners find published keys within minutes.

Never paste it into a chat, a screenshot, or a support ticket.

What the status code does and does not tell you

A 200 means the request was well formed and the server answered. It says nothing about whether the answer is true, complete, or sensible.

An AI model can return a confident, well-written, wrong answer with a 200. It can also stop mid-sentence because it hit your max_tokens limit, and that is still a 200, with a field in the response body such as stop_reason telling you why it ended. The status code describes the delivery. The body is where the content, and any problem with the content, lives.

Try this now

Run the GitHub call. Change cpython to something that does not exist and print the status code. Then wrap it:

python
import requests

def repo_stars(full_name):
    r = requests.get(f"https://api.github.com/repos/{full_name}", timeout=10)
    if r.status_code != 200:
        return None
    return r.json()["stargazers_count"]

for name in ["python/cpython", "pallets/flask", "no/such-repo"]:
    print(name, repo_stars(name))

A function, a loop, a dict, a list, a conversion, and an API call. That is the whole course in nine lines.

Before you move on

You call an AI API. `r.status_code` is 200, and the text in the response contains a confident claim that turns out to be false. What does the 200 actually tell you?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly