Lesson 62 · APIs & Web Services 50–60 minutes Intermediate

Python REST APIs

Learn how modern applications communicate through REST APIs. Understand resources, endpoints, HTTP methods, JSON, authentication, pagination, errors and how to build a practical Python API client.

0%
01

Learning Objectives

REST APIs are one of the most common ways applications exchange information over the internet. By the end of this lesson, you will understand how REST APIs are designed and how Python applications consume them.

You will learn how to:

  • Understand APIs and REST architecture.
  • Work with API resources and endpoints.
  • Use HTTP methods correctly.
  • Exchange JSON data.
  • Build GET, POST, PUT, PATCH and DELETE requests.
  • Understand HTTP status codes.
  • Work with request headers.
  • Understand API authentication.
  • Handle pagination and filtering.
  • Handle API errors.
  • Build a reusable Python API client.
  • Apply REST concepts to ecommerce systems.
02

What Is an API?

API stands for Application Programming Interface.

An API provides a defined way for one software system to communicate with another software system.

For example, an ecommerce application might communicate with a payment service through an API.

Ecommerce Website
       ↓
   API Request
       ↓
Payment Service
       ↓
   API Response
       ↓
Ecommerce Website

Think of an API as a Contract

An API defines what requests can be made, what data should be supplied and what kind of response the client can expect.

03

What Is REST?

REST stands for Representational State Transfer.

REST is an architectural style for designing networked applications. REST APIs commonly use HTTP and represent information as resources.

A RESTful API generally uses:

  • HTTP methods
  • Resource-based URLs
  • Stateless requests
  • Standard HTTP status codes
  • Representations such as JSON

Important Concept

REST is not a programming language and it is not a Python library. It is a way of designing APIs.

04

REST Resources

REST APIs commonly organize data around resources.

In an ecommerce application, resources might include:

/products
/customers
/orders
/categories
/reviews

A particular product could be represented as:

/products/101

Here, 101 identifies a specific product.

05

HTTP Methods

REST APIs use HTTP methods to communicate the intended operation.

Common REST Operations

  • GET — retrieve resources
  • POST — create a resource
  • PUT — replace a resource
  • PATCH — partially update a resource
  • DELETE — remove a resource
GET     /products
POST    /products
GET     /products/101
PUT     /products/101
PATCH   /products/101
DELETE  /products/101
06

API URLs and Endpoints

An API endpoint is a specific URL through which a client interacts with a resource.

https://api.example.com/products

A versioned API might look like:

https://api.example.com/v1/products

A specific resource might be:

https://api.example.com/v1/products/25

Why API Versions Matter

API versions allow service providers to introduce changes while giving existing applications time to continue using an older interface.

07

JSON Data

REST APIs frequently use JSON to represent structured data.

{
    "id": 101,
    "name": "Laptop",
    "price": 1200,
    "stock": 15
}

Python can convert JSON responses into dictionaries and lists.

import requests

response = requests.get(
    "https://example.com/api/products"
)

data = response.json()

print(data["name"])

A JSON array may become a Python list.

[
    {
        "id": 1,
        "name": "Laptop"
    },
    {
        "id": 2,
        "name": "Phone"
    }
]
08

GET Requests

GET is commonly used to retrieve resources.

import requests

url = "https://example.com/api/products"

response = requests.get(
    url,
    timeout=10
)

response.raise_for_status()

products = response.json()

for product in products:
    print(product["name"])

This pattern is common when consuming an API:

Request
   ↓
Status Check
   ↓
JSON Parsing
   ↓
Python Data
   ↓
Application Logic
09

POST Requests

POST is commonly used to create a new resource.

import requests

product = {
    "name": "Laptop",
    "price": 1200,
    "stock": 10
}

response = requests.post(
    "https://example.com/api/products",
    json=product,
    timeout=10
)

print(response.status_code)

A successful resource creation commonly results in status code 201 Created.

Important

The endpoint above is illustrative. A real API must document the exact URL, fields and authentication requirements.

10

PUT Requests

PUT is commonly associated with replacing an existing resource with a new representation.

import requests

updated_product = {
    "name": "Laptop Pro",
    "price": 1500,
    "stock": 20
}

response = requests.put(
    "https://example.com/api/products/101",
    json=updated_product,
    timeout=10
)

print(response.status_code)

The exact behavior depends on the API implementation.

11

PATCH Requests

PATCH is generally used when only part of a resource needs to be changed.

import requests

changes = {
    "price": 1400
}

response = requests.patch(
    "https://example.com/api/products/101",
    json=changes,
    timeout=10
)

print(response.status_code)

PUT vs PATCH

A useful mental model is: PUT commonly represents a full replacement, while PATCH commonly represents a partial modification.

12

DELETE Requests

DELETE is commonly used to remove a resource.

import requests

response = requests.delete(
    "https://example.com/api/products/101",
    timeout=10
)

print(response.status_code)

Some APIs return 204 No Content after a successful deletion.

13

HTTP Status Codes

Status codes allow your application to determine what happened during an API request.

2xx — Success

  • 200 — OK
  • 201 — Created
  • 204 — No Content

4xx — Client Problems

  • 400 — Bad Request
  • 401 — Unauthorized
  • 403 — Forbidden
  • 404 — Not Found
  • 429 — Too Many Requests

5xx — Server Problems

  • 500 — Internal Server Error
  • 502 — Bad Gateway
  • 503 — Service Unavailable
14

Request Headers

Headers provide additional information about a request.

import requests

headers = {
    "Accept": "application/json",
    "User-Agent": "PyLearn-App"
}

response = requests.get(
    "https://example.com/api/products",
    headers=headers,
    timeout=10
)

print(response.status_code)

APIs may use headers to communicate content formats, authentication credentials and other metadata.

15

API Authentication

Public APIs may allow anonymous requests, while private APIs usually require authentication.

One common authentication pattern is a bearer token.

import requests

token = "YOUR_API_TOKEN"

headers = {
    "Authorization": f"Bearer {token}"
}

response = requests.get(
    "https://example.com/api/profile",
    headers=headers,
    timeout=10
)

response.raise_for_status()

print(response.json())

Security Rule

Never put real API tokens, passwords or private credentials directly into source code that may be published or committed to Git.

A better approach is to read secrets from environment variables or a dedicated secrets-management system.

16

Pagination

APIs may contain thousands or millions of records. Returning everything in one response would be inefficient.

APIs therefore commonly divide results into pages.

GET /products?page=1
GET /products?page=2
GET /products?page=3

A Python client might request multiple pages:

import requests

all_products = []

for page in range(1, 4):

    response = requests.get(
        "https://example.com/api/products",
        params={"page": page},
        timeout=10
    )

    response.raise_for_status()

    products = response.json()

    all_products.extend(products)

print("Products:", len(all_products))

Real-World Consideration

Different APIs implement pagination differently. You may encounter page numbers, offsets, cursors or links to the next page.

17

Filtering & Searching

APIs often provide query parameters that allow clients to request only the data they need.

params = {
    "category": "electronics",
    "min_price": 500,
    "page": 1
}

response = requests.get(
    "https://example.com/api/products",
    params=params,
    timeout=10
)

Search parameters might look like:

GET /products?search=laptop
GET /products?category=electronics
GET /products?sort=price

The exact parameter names are determined by the API.

18

Handling API Errors

A professional API client should expect failures.

import requests

try:

    response = requests.get(
        "https://example.com/api/products",
        timeout=10
    )

    response.raise_for_status()

    data = response.json()

except requests.exceptions.Timeout:

    print("The request timed out.")

except requests.exceptions.HTTPError as error:

    print("HTTP error:", error)

except requests.exceptions.ConnectionError:

    print("Could not connect to the server.")

except ValueError:

    print("The response was not valid JSON.")

except requests.exceptions.RequestException as error:

    print("Request failed:", error)

Think Beyond 200 OK

A robust application considers network failures, authentication errors, rate limits, invalid data and temporary server problems.

19

Building a Reusable API Client

Instead of repeating the same request logic throughout your program, you can create functions or classes that act as an API client.

import requests


def get_products(base_url):

    response = requests.get(
        f"{base_url}/products",
        timeout=10
    )

    response.raise_for_status()

    return response.json()


products = get_products(
    "https://example.com/api"
)

for product in products:
    print(product["name"])

This separates network communication from the rest of your application logic.

Why This Matters

  • Less duplicated code
  • Easier testing
  • Centralized error handling
  • Easier API changes
  • Cleaner application architecture
20

Practical Ecommerce Example

Imagine that an ecommerce application receives product information from an external API.

import requests


def fetch_products():

    url = "https://example.com/api/products"

    try:

        response = requests.get(
            url,
            params={
                "category": "electronics",
                "page": 1
            },
            timeout=10
        )

        response.raise_for_status()

        return response.json()

    except requests.exceptions.RequestException as error:

        print("API request failed:", error)

        return []


products = fetch_products()

for product in products:

    name = product.get("name", "Unknown")
    price = product.get("price", 0)

    print(f"{name}: ${price}")

This example demonstrates several professional concepts together:

  • Function abstraction
  • Query parameters
  • Timeouts
  • HTTP error handling
  • JSON parsing
  • Safe dictionary access

Architecture Connection

An ecommerce platform could use this same pattern to synchronize products, orders, customers, inventory or shipping information with another system.

21

REST API Best Practices

1. Use Timeouts

Never assume that a remote server will respond immediately.

2. Check Status Codes

Always determine whether the operation succeeded.

3. Handle Exceptions

Network failures are normal possibilities and should be handled.

4. Protect Credentials

Keep API keys and tokens outside public source code.

5. Respect Rate Limits

APIs may limit how many requests a client can make.

6. Read API Documentation

Never guess an API's endpoints, parameters or required fields when documentation is available.

7. Keep API Logic Organized

Put repeated API communication into reusable functions or classes.

22

Common REST API Mistakes

Mistake 1 — Assuming Every Request Succeeds

Always inspect the response status.

Mistake 2 — Ignoring API Documentation

Every API has its own endpoint structure, parameters and authentication requirements.

Mistake 3 — Hard-Coding Secrets

API credentials should be stored securely.

Mistake 4 — No Timeout

Network requests should have sensible timeout behavior.

Mistake 5 — Assuming JSON Is Always Valid

A server may return an error page, empty response or malformed data.

Mistake 6 — Ignoring Pagination

APIs often return only a portion of a large dataset.

23

Practice Exercises

Exercise 1 — Retrieve Products

Write a function that sends a GET request to a products endpoint and returns the JSON data.

Exercise 2 — Add Query Parameters

Modify your function so it accepts a category and page number.

Exercise 3 — Handle Errors

Add timeout handling, HTTP error handling and connection error handling.

Exercise 4 — Create a Product

Write a POST request that sends a product as JSON.

Exercise 5 — Pagination

Retrieve three pages of products and combine them into one Python list.

24

Mini Challenge — Ecommerce REST API Client

Build a small Python API client for an imaginary ecommerce platform.

Your Mission

  1. Create a function called get_products().
  2. Send a GET request.
  3. Add pagination using a page parameter.
  4. Set a timeout.
  5. Call raise_for_status().
  6. Parse the JSON response.
  7. Print each product's name and price.
  8. Filter products costing more than 500.
  9. Handle request failures gracefully.

Starter Code

import requests


def get_products(page=1):

    url = "https://example.com/api/products"

    try:

        response = requests.get(
            url,
            params={
                "page": page
            },
            timeout=10
        )

        response.raise_for_status()

        return response.json()

    except requests.exceptions.RequestException as error:

        print("API error:", error)

        return []


products = get_products(page=1)

for product in products:

    name = product.get("name", "Unknown")
    price = product.get("price", 0)

    if price > 500:
        print(
            f"{name} - ${price}"
        )

Advanced Extension

Extend your program so that it:

  • retrieves multiple pages,
  • counts the total products,
  • calculates the average price,
  • finds the most expensive product,
  • stores the results in SQLite.
REST API
    ↓
Requests
    ↓
JSON
    ↓
Python Data
    ↓
Data Processing
    ↓
SQLite
    ↓
Ecommerce Report

Professional Challenge

Try separating your project into an API client function, data-processing functions and database functions. This introduces a cleaner architecture similar to real software projects.

25

Knowledge Check

1. What does API stand for?

2. What is REST?

3. Which method commonly retrieves a resource?

4. Which method commonly creates a resource?

5. Which format is frequently used by REST APIs?

6. What does status code 404 mean?

7. Why is pagination used?

8. Why should API tokens not be hard-coded?

9. Which status code commonly indicates creation?

10. What is a REST resource?

26

Lesson Summary

REST APIs provide a structured way for applications to communicate over HTTP.

What You Learned

  • APIs allow software systems to communicate.
  • REST is an architectural style for designing networked APIs.
  • REST APIs organize information around resources.
  • HTTP methods describe operations on resources.
  • JSON is commonly used to exchange structured data.
  • GET retrieves information.
  • POST commonly creates resources.
  • PUT commonly replaces resources.
  • PATCH commonly performs partial updates.
  • DELETE commonly removes resources.
  • Status codes communicate request results.
  • Headers carry additional request information.
  • Authentication protects private APIs.
  • Pagination handles large datasets.
  • Query parameters support filtering and searching.
  • Robust clients need timeouts and exception handling.
  • API logic can be organized into reusable functions or classes.

You now understand the architecture behind many modern web services. In the next lesson, we will move from consuming APIs to another powerful Python skill: Web Scraping.

Ready to Continue?

You have completed the Python REST APIs lesson.