What you’ll learn
- What an API is, using an everyday example
- What a request and a response contain
- What JSON is and how it relates to Python dictionaries
- What status codes like 200, 401 and 429 mean
- What an API key is and why you must keep it secret
What is an API?
API stands for Application Programming Interface. That’s a fancy name for a simple idea: a way for one program to ask another program for something.
Think of a restaurant. You don’t walk into the kitchen and cook. You tell the waiter what you want from the menu, the waiter takes your order to the kitchen, and brings your food back.
- You are your Python app.
- The menu is the list of things the API can do.
- The waiter is the API.
- The kitchen is the AI model on the provider’s computers.
Your app never touches the AI model directly. It always goes through the API.
Requests and responses
Every time your app talks to an API, it sends a request and gets back a response.
A request has four main parts:
- Address (URL): where to send it, for example https://api.openai.com/v1/responses
- Method: what kind of request it is. AI APIs use POST, which means “here’s some data, please process it.”
- Headers: extra information about the request, including your API key.
- Body: the actual data, like the model name and your messages.
The response has two main parts:
- Status code: a number that says whether it worked.
- Body: the data that came back, like the AI’s answer.
What is JSON?
APIs send data as JSON (JavaScript Object Notation). Good news: JSON looks almost exactly like a Python dictionary.
Here’s a request body in JSON:
{"model": "example-model", "messages": [{"role": "user", "content": "Hello"}]}
The difference is that JSON is text, while a dictionary is a Python object. Python’s built-in json module converts between them:
import json
body = {"model": "example-model", "messages": [{"role": "user", "content": "Hello"}]}
json_text = json.dumps(body) # dictionary -> JSON text, to send
back_again = json.loads(json_text) # JSON text -> dictionary, to use
You’ll use json.dumps in today’s practice file.
Status codes
Every response comes with a status code. These are the ones you’ll see most:
|
Code |
Meaning |
What to do |
|---|---|---|
|
200 |
OK, it worked |
Use the answer |
|
400 |
Bad request: something in your request is wrong |
Check the body, such as the model name |
|
401 |
Unauthorized: the API key is missing or wrong |
Check your API key |
|
429 |
Too many requests, or you’ve used up your credit |
Wait a moment, or check your billing |
|
500 |
Server error: a problem on the provider’s side |
Wait and try again |
A quick rule: codes starting with 2 mean success, 4 means the problem is on your side, and 5 means it’s on theirs.
What is an API key?
An API key is a long secret code that identifies you to the API, like a password and a membership card in one. It looks something like this (this one is fake):
sk-proj-Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56
Your app sends the key in a header with every request:
headers = {"Authorization": "Bearer sk-proj-Ab12Cd34..."}
The word Bearer just means “the person holding this key.” The provider uses the key to:
- Check that you’re allowed to use the API
- Know whose account to charge
- Apply your limits, like how many requests per minute
Keep your key secret
Anyone who has your key can use the API and you pay the bill. So:
- Never share it in a screenshot, email, forum post or video.
- Never put it directly in code you share or upload to GitHub.
- Never print the whole key. Show only the first and last few characters if you need to check it.
- If a key leaks, delete it in your account and create a new one.
In the next lesson, you’ll create your real OpenAI key and store it safely in a .env file, so it never appears in your code.
Do I have to write all this myself?
No. In Lesson 5, you’ll install the official openai Python package. It builds the URL, headers and JSON for you, so a request takes just a few lines. Understanding what happens underneath, though, makes error messages much easier to fix.
Common mistakes
- Forgetting “Bearer ” before the key. The header must be Bearer, then a space, then the key. Without it you get a 401.
- Copying the key with an extra space or a missing character. Also a 401. Copy it again carefully.
- Sending a dictionary when the API expects JSON text. Use json.dumps to turn it into text.
- Treating 429 as a bug in your code. It usually means “slow down” or “add credit.”
- Printing or sharing the full key. Treat it like a password.
Try it, exercise and practice file
Try it: Send an API Request
Students choose which key their app sends (correct key, wrong key, no key, or the key without “Bearer “), type a prompt, and click Send. They see the full request (URL, headers with the key masked, JSON body) next to the response (status code badge and JSON body), with a plain-language explanation of what happened. A checkbox simulates 100 requests in one second to trigger a 429. A tracker at the bottom challenges them to find 200, 401 and 429.
Placement: after “Common mistakes,” before “Hands-on exercise.” Add a heading “Try it: Send an API Request,” then a Custom HTML block with the whole contents of lesson3_try_it_widget.html. Install it the same way as before (WP Editor, logged in as an admin).
Text above the widget: Your app’s job is to send good requests. Try each kind of key and watch what the API sends back. Can you get a 200, a 401 and a 429? Notice that the key in the request is always masked.
Hands-on exercise
- Download api_basics.py into your ai-app-course folder and open it in VS Code.
- Run it once before changing anything. Every check fails, and that’s expected.
- TODO 1: finish make_headers so it returns the Authorization header (Bearer, a space, the key) and the Content-Type header.
- TODO 2: finish make_body so it builds the request dictionary and returns it as JSON text with json.dumps.
- TODO 3: finish explain_status with if / elif / else for 200, 401, 429 and everything else.
- TODO 4: finish mask_key so it returns the first 3 characters, “…”, and the last 4 characters.
- Run the file again. The demo should show a 200 with an answer, a 401 for the wrong key, and a 429 for too many requests, with every key masked.
Practice file
- api_basics.py (give to students): four TODOs, a pretend API that checks the key and the JSON body like a real one, a three-request demo, and six automatic checks. The key in the file is fake, and no internet is needed.
- api_basics_solution.py (for you only): the finished version. Don’t attach it to the lesson.
You’re done when: the last line says “All 6 checks passed! You can speak API.”
Example of a finished run:
--- Request 1: correct key ---
POST https://api.example.com/v1/chat
Key sent: sk-...Gh78
Status: 200 - OK
Answer: You asked "What is an API?" (pretend AI answer)
--- Request 2: wrong key ---
POST https://api.example.com/v1/chat
Key sent: sk-...0000
Status: 401 - Check your API key
--- Request 3: too many requests ---
POST https://api.example.com/v1/chat
Key sent: sk-...Gh78
Status: 429 - Too many requests - wait and try again
Check 1: PASS - make_headers sends the key as Bearer <key>
Check 2: PASS - make_headers sets Content-Type to application/json
Check 3: PASS - make_body returns JSON text with the model and message
Check 4: PASS - explain_status handles 200, 401, 429 and others
Check 5: PASS - mask_key hides the middle of the key
Check 6: PASS - the demo got 200, 401 and 429 back
All 6 checks passed! You can speak API.
Solution code (for your support replies):
def make_headers(api_key):
return {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
def make_body(prompt):
body = {"model": MODEL, "messages": [{"role": "user", "content": prompt}]}
return json.dumps(body)
def explain_status(status_code):
if status_code == 200:
return "OK"
elif status_code == 401:
return "Check your API key"
elif status_code == 429:
return "Too many requests - wait and try again"
else:
return "Something went wrong"
def mask_key(api_key):
return api_key[:3] + "..." + api_key[-4:]
Key takeaways
- An API is a way for one program to ask another for something. Your app is the customer, the API is the waiter, and the AI model is the kitchen.
- A request has a URL, a method (POST), headers (including your key) and a body (the model and messages).
- A response has a status code and a body.
- JSON is text that looks like a Python dictionary. json.dumps turns a dictionary into JSON, and json.loads turns it back.
- 200 means OK, 401 means a key problem, 429 means too many requests or no credit, and 5xx means a problem on the provider’s side.
- An API key is sent as “Bearer <key>” in the Authorization header. Anyone with it can spend your money, so never share it or print it in full.