#1 Data Analytics Program in India
₹2,499₹1,499Enroll Now
6 min read min read

Making API Requests

Learn to send data and make different types of API requests

Making API Requests

GET Requests

GET retrieves data from the server. We covered basics earlier, here's more detail.

code.py
import requests

response = requests.get("https://jsonplaceholder.typicode.com/posts/1")

if response.status_code == 200:
    post = response.json()
    print("Title:", post["title"])
    print("Body:", post["body"])

What this does: Gets post with ID 1 from test API.

POST Requests

POST sends data to create new resources.

code.py
import requests

new_post = {
    "title": "My New Post",
    "body": "This is the content",
    "userId": 1
}

response = requests.post(
    "https://jsonplaceholder.typicode.com/posts",
    json=new_post
)

if response.status_code == 201:
    print("Created successfully!")
    created = response.json()
    print("New ID:", created["id"])

What this does:

  • Sends data as JSON
  • Creates new post
  • Server responds with created resource
  • Status 201 means created

PUT Requests

PUT updates existing resources completely.

code.py
import requests

updated_post = {
    "id": 1,
    "title": "Updated Title",
    "body": "Updated content",
    "userId": 1
}

response = requests.put(
    "https://jsonplaceholder.typicode.com/posts/1",
    json=updated_post
)

if response.status_code == 200:
    print("Updated successfully!")
    print(response.json())

What this does: Replaces entire post with ID 1.

PATCH Requests

PATCH updates only specific fields.

code.py
import requests

partial_update = {
    "title": "New Title Only"
}

response = requests.patch(
    "https://jsonplaceholder.typicode.com/posts/1",
    json=partial_update
)

if response.status_code == 200:
    print("Partial update successful!")

Difference between PUT and PATCH:

  • PUT: Replace entire resource
  • PATCH: Update only specified fields

DELETE Requests

DELETE removes resources.

code.py
import requests

response = requests.delete(
    "https://jsonplaceholder.typicode.com/posts/1"
)

if response.status_code == 200:
    print("Deleted successfully!")
elif response.status_code == 204:
    print("Deleted (no content returned)")

What status 204 means: Deleted successfully, no data to return.

Sending Form Data

Some APIs expect form data instead of JSON.

code.py
import requests

form_data = {
    "username": "john",
    "email": "john@example.com"
}

response = requests.post(
    "https://api.example.com/register",
    data=form_data
)

Difference:

  • json= sends JSON
  • data= sends form data

Query Parameters

Add parameters to URL for filtering and searching.

code.py
import requests

params = {
    "userId": 1,
    "completed": "false"
}

response = requests.get(
    "https://jsonplaceholder.typicode.com/todos",
    params=params
)

todos = response.json()
print("Found", len(todos), "todos")

What this creates: URL: /todos?userId=1&completed=false

Custom Headers

Add headers for authentication or content type.

code.py
import requests

headers = {
    "Authorization": "Bearer your_token_here",
    "Content-Type": "application/json",
    "User-Agent": "MyApp/1.0"
}

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

Common headers:

  • Authorization: API key or token
  • Content-Type: Data format you're sending
  • Accept: Data format you want back
  • User-Agent: Your application name

API Authentication

API Key in Header

code.py
import requests

headers = {
    "X-API-Key": "your_api_key_here"
}

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

API Key in URL

code.py
import requests

params = {
    "api_key": "your_api_key_here"
}

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

Bearer Token

code.py
import requests

headers = {
    "Authorization": "Bearer your_access_token"
}

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

Uploading Files

Send files to API.

code.py
import requests

files = {
    "file": open("document.pdf", "rb")
}

response = requests.post(
    "https://api.example.com/upload",
    files=files
)

print("Upload status:", response.status_code)

Important: Use "rb" mode for binary files.

Session Objects

Use sessions for multiple requests to same API.

code.py
import requests

session = requests.Session()

session.headers.update({
    "Authorization": "Bearer your_token"
})

response1 = session.get("https://api.example.com/users")
response2 = session.get("https://api.example.com/posts")

session.close()

Why use sessions:

  • Reuse authentication
  • Keep cookies
  • Connection reuse (faster)

Handling Redirects

code.py
import requests

response = requests.get(
    "https://api.example.com/old-url",
    allow_redirects=True
)

print("Final URL:", response.url)
print("History:", response.history)

What this shows: If API redirects to new URL, shows where you ended up.

Practice Example

The scenario: Build a simple blog post manager using API.

code.py
import requests

BASE_URL = "https://jsonplaceholder.typicode.com"

def get_all_posts():
    response = requests.get(BASE_URL + "/posts")

    if response.status_code == 200:
        posts = response.json()
        print("Total posts:", len(posts))
        return posts
    else:
        print("Error getting posts")
        return []

def get_post(post_id):
    response = requests.get(BASE_URL + "/posts/" + str(post_id))

    if response.status_code == 200:
        post = response.json()
        print("Title:", post["title"])
        print("Body:", post["body"])
        return post
    else:
        print("Post not found")
        return None

def create_post(title, body, user_id):
    new_post = {
        "title": title,
        "body": body,
        "userId": user_id
    }

    response = requests.post(
        BASE_URL + "/posts",
        json=new_post
    )

    if response.status_code == 201:
        created = response.json()
        print("Post created with ID:", created["id"])
        return created
    else:
        print("Failed to create post")
        return None

def update_post(post_id, title, body):
    updates = {
        "title": title,
        "body": body
    }

    response = requests.patch(
        BASE_URL + "/posts/" + str(post_id),
        json=updates
    )

    if response.status_code == 200:
        print("Post updated successfully")
        return response.json()
    else:
        print("Failed to update post")
        return None

def delete_post(post_id):
    response = requests.delete(
        BASE_URL + "/posts/" + str(post_id)
    )

    if response.status_code == 200:
        print("Post deleted successfully")
        return True
    else:
        print("Failed to delete post")
        return False

posts = get_all_posts()

post = get_post(1)

new_post = create_post("My Title", "My Content", 1)

if new_post:
    update_post(new_post["id"], "Updated Title", "Updated Content")

delete_post(1)

What this program does:

  1. Gets all posts
  2. Gets specific post
  3. Creates new post
  4. Updates the new post
  5. Deletes a post
  6. All operations with error handling

Retry Logic

Automatically retry failed requests.

code.py
import requests
import time

def make_request_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.get(url, timeout=5)
            response.raise_for_status()
            return response

        except requests.exceptions.RequestException as e:
            if attempt < max_retries - 1:
                wait_time = 2 * (attempt + 1)
                print("Retry in", wait_time, "seconds...")
                time.sleep(wait_time)
            else:
                print("Max retries reached")
                raise

response = make_request_with_retry("https://api.example.com/data")

What this does: Retries up to 3 times with increasing wait time.

Key Points to Remember

GET retrieves data, POST creates, PUT updates completely, PATCH updates partially, DELETE removes.

Use json= parameter to send JSON data. Use data= for form data.

Add headers= for authentication and custom headers. Most APIs require API keys or tokens.

Use Session objects for multiple requests to same API. Faster and cleaner than individual requests.

Always check status_code before processing response. Use try-except for error handling.

Common Mistakes

Mistake 1: Wrong method

code.py
requests.get(url, json=data)  # GET doesn't send body!
requests.post(url, json=data)  # Correct for sending data

Mistake 2: Forgetting json=

code.py
requests.post(url, data)  # Sends as form data
requests.post(url, json=data)  # Sends as JSON

Mistake 3: Not handling authentication

code.py
requests.get(url)  # May get 401 error
requests.get(url, headers={"Authorization": token})  # Correct

Mistake 4: Exposing API keys Don't put API keys in code. Use environment variables.

What's Next?

You now know how to make API requests. Next, you'll learn about API authentication and pagination - handling auth tokens and working with large datasets.

SkillsetMaster - AI, Web Development & Data Analytics Courses