العربية

Module 11: APIs

Course: Programming with Free AI Tools — Build Real Websites and Apps | Module: 11 of 17 | Audience: Ages 15–25, beginners | Focus: REST basics, HTTP verbs, consuming APIs with JavaScript fetch, and building a simple API with PHP.

Core principle: Always verify AI-generated code. Run it, read the output, and understand what each line does before trusting it.

Table of Contents

Lesson 11.1: What is an API and REST Basics

Duration: 45 minutes

Learning Objectives

Instructor Notes

Use a real-world analogy: an API is like a restaurant waiter — you (client) give an order, the kitchen (server) prepares it, and the waiter returns the food (response). Open a public API like https://jsonplaceholder.typicode.com/posts in the browser to show raw JSON.

Emphasize that REST is a convention, not a strict rule. Many APIs follow it loosely. Warn students: never hard-code secret API keys in client-side JavaScript that goes to the browser.

Presentation Outline

  1. What is an API? (5 min)
  2. Client–server model and request/response (10 min)
  3. REST concepts: resources, URLs, statelessness (10 min)
  4. HTTP verbs table: GET / POST / PUT / DELETE (10 min)
  5. JSON and HTTP status codes (10 min)

Demonstration

  1. Open https://jsonplaceholder.typicode.com/posts/1 in the browser.
  2. Show the JSON object and point out the keys (userId, id, title, body).
  3. Open DevTools → Network tab and reload to show the request method (GET) and status (200).
  4. Demonstrate a 404 by visiting /posts/99999 style broken endpoint.
  5. Summarize: the browser sent GET, the server replied 200 with JSON.

AI Prompts

Starter Code

{
  "message": "This is what a JSON API response looks like.",
  "lesson": 11.1,
  "items": ["GET", "POST", "PUT", "DELETE"]
}

Final Code

GET https://jsonplaceholder.typicode.com/posts/1

HTTP/1.1 200 OK
Content-Type: application/json

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati",
  "body": "quia et suscipit suscipit recusandae"
}

Exercises

  1. Visit three different REST API endpoints and write down their status codes.
  2. Draw a diagram showing a client, an API, and a database, with arrows for request and response.
  3. List which HTTP verb you would use for: reading a user, creating a user, updating a user, deleting a user.

Homework

  1. Find one free public API (e.g., weather, cat facts, countries) and write a one-paragraph explanation of what it returns.
  2. Create a table of 5 endpoints from that API with their HTTP method and a sample response field.

Quiz

  1. What does API stand for?
    • a) Application Programming Interface ✅
    • b) Automated Process Integration
    • c) Applied Program Instruction
    • d) Array Pointer Index
  2. Which HTTP verb is used to request data from a server?
    • a) POST
    • b) PUT
    • c) GET ✅
    • d) DELETE
  3. Which HTTP verb is typically used to create a new resource?
    • a) GET
    • b) POST ✅
    • c) DELETE
    • d) PATCH-less PUT
  4. What does an HTTP status code of 404 mean?
    • a) Server error
    • b) Resource not found ✅
    • c) Success
    • d) Unauthorized
  5. What format do most modern web APIs use to send data?
    • a) XML only
    • b) CSV
    • c) JSON ✅
    • d) Plain text

Lesson 11.2: Consuming APIs with JavaScript fetch

Duration: 60 minutes

Learning Objectives

Instructor Notes

Start with the older .then() syntax, then show the cleaner async/await version. Stress that fetch does NOT throw on HTTP errors (like 404) — you must check response.ok. Show how to render a list of items using map() and innerHTML or createElement.

Remind students to verify the response shape before accessing properties (avoid undefined crashes).

Presentation Outline

  1. Recap JSON and endpoints (5 min)
  2. Introducing fetch() (10 min)
  3. .then() promise chain (15 min)
  4. async/await + try/catch (15 min)
  5. Rendering data into HTML (15 min)

Demonstration

  1. Create index.html with a <ul id="posts">.
  2. Write a fetch('https://jsonplaceholder.typicode.com/posts?_limit=5') call.
  3. Parse with .json(), then loop and append <li> elements.
  4. Convert the code to async/await and add a try/catch that shows an error message in the page.
  5. Break the URL on purpose to demonstrate error handling.

AI Prompts

Starter Code

<!DOCTYPE html>
<html>
<head><title>API Demo</title></head>
<body>
  <h1>Posts</h1>
  <ul id="posts"></ul>
  <script src="app.js"></script>
</body>
</html>
// TODO: fetch posts and display them

Final Code

async function loadPosts() {
  const list = document.getElementById('posts');
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
    if (!response.ok) {
      throw new Error('HTTP ' + response.status);
    }
    const posts = await response.json();
    list.innerHTML = '';
    posts.forEach(post => {
      const li = document.createElement('li');
      li.textContent = post.title;
      list.appendChild(li);
    });
  } catch (error) {
    list.innerHTML = '<li>Error loading posts: ' + error.message + '</li>';
  }
}

loadPosts();

Exercises

  1. Modify the code to show each post's body text under its title.
  2. Add a button that reloads the posts when clicked.
  3. Fetch users instead of posts and display names and emails.

Homework

  1. Build a small page that fetches and displays weather or country data from a free API of your choice.
  2. Add error handling and a "Loading..." message that appears before data arrives.

Quiz

  1. What does await do inside an async function?
    • a) Stops the whole browser
    • b) Pauses execution until the promise resolves ✅
    • c) Loops forever
    • d) Throws an error
  2. How do you convert a fetch response to a JavaScript object?
    • a) response.text()
    • b) response.json() ✅
    • c) JSON.parse(response)
    • d) response.object()
  3. Does fetch() reject on an HTTP 404 by default?
    • a) Yes, always
    • b) No, you must check response.ok ✅
    • c) Only in Firefox
    • d) Only with POST
  4. Where should API error messages be shown to the user?
    • a) Nowhere
    • b) In the browser console only
    • c) In the page UI with try/catch handling ✅
    • d) In an alert that never closes
  5. Which method is used to send a request that may fail without crashing the app?
    • a) try/catch with async/await ✅
    • b) goto
    • c) while(true)
    • d) system.exit

Lesson 11.3: Building a Simple API with PHP

Duration: 60 minutes

Learning Objectives

Instructor Notes

Use XAMPP so students can run PHP locally at http://localhost/. Show header('Content-Type: application/json') before any output. Use json_encode() / json_decode() for data conversion. Demonstrate reading the request body with file_get_contents('php://input'). Reinforce: validate input even in a tiny API — security awareness starts here.

Presentation Outline

  1. What a server-side API looks like (5 min)
  2. PHP header() and json_encode() (10 min)
  3. Handling GET requests (15 min)
  4. Handling POST with request body (15 min)
  5. Testing with browser + fetch (15 min)

Demonstration

  1. Create api.php that returns a list of products as JSON on GET.
  2. Add a POST handler that appends a new product to an array.
  3. Test GET via browser: http://localhost/api.php.
  4. Test POST via a small HTML form or fetch call from another page.
  5. Return 201 Created on successful POST and 400 on missing fields.

AI Prompts

Starter Code

<?php
header('Content-Type: application/json');

$products = [
    ['id' => 1, 'name' => 'Book', 'price' => 10],
];

// TODO: handle GET and POST
echo json_encode($products);

Final Code

<?php
header('Content-Type: application/json');

$products = [
    ['id' => 1, 'name' => 'Book', 'price' => 10],
];

$method = $_SERVER['REQUEST_METHOD'];

if ($method === 'GET') {
    echo json_encode($products);
    exit;
}

if ($method === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    if (!isset($input['name']) || !isset($input['price'])) {
        http_response_code(400);
        echo json_encode(['error' => 'name and price required']);
        exit;
    }
    $input['id'] = count($products) + 1;
    $products[] = $input;
    http_response_code(201);
    echo json_encode($input);
    exit;
}

http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);

Exercises

  1. Add a DELETE handler that removes a product by id and returns 204.
  2. Add a PUT handler that updates a product's price by id.
  3. Return a 404 when a requested product id does not exist.

Homework

  1. Extend the PHP API to store products in a JSON file (products.json) instead of a variable, so data survives restarts.
  2. Write a JavaScript page that uses fetch to GET and POST products to your API.

Quiz

  1. Which PHP function converts an array to a JSON string?
    • a) to_json()
    • b) json_encode() ✅
    • c) serialize()
    • d) echo_json()
  2. How do you set the response content type to JSON in PHP?
    • a) set_header(...)
    • b) header('Content-Type: application/json') ✅
    • c) content_type('json')
    • d) <?json ?>
  3. How do you read the raw POST body in PHP?
    • a) $_POST['body']
    • b) file_get_contents('php://input') ✅
    • c) request()->body
    • d) $_GET['body']
  4. What status code should a successful POST that created a resource return?
    • a) 200
    • b) 201 ✅
    • c) 404
    • d) 500
  5. Why must you validate input in an API?
    • a) It makes the code longer
    • b) To prevent bad or unsafe data from breaking the app ✅
    • c) PHP requires it
    • d) It is optional decoration

Lesson 11.4: Securing and Testing Your API

Duration: 45 minutes

Learning Objectives

Instructor Notes

Demonstrate the danger of putting a key in client JS by showing "View Source". Teach htmlspecialchars() / filter_var() for sanitization basics. Introduce a lightweight testing habit: call the endpoint and confirm the JSON shape. Tie back to the grading rubric: security awareness is 10% of the grade.

Presentation Outline

  1. Why secrets must stay on the server (10 min)
  2. Input validation with filter_var (10 min)
  3. Consistent status codes (10 min)
  4. Manual API testing workflow (10 min)
  5. Common mistakes review (5 min)

Demonstration

  1. Show a .env-style config holding a fake API key, required by PHP only.
  2. Add validation: price must be numeric using filter_var($price, FILTER_VALIDATE_FLOAT).
  3. Reject invalid data with 400 and a clear JSON error.
  4. Test GET and POST from the browser and from a fetch page.
  5. Review one buggy student-style API and fix it live.

AI Prompts

Starter Code

<?php
header('Content-Type: application/json');

// TODO: load config, validate input, return proper status codes

Final Code

<?php
header('Content-Type: application/json');

$apiKey = getenv('API_KEY') ?: 'demo-secret-key';

$data = json_decode(file_get_contents('php://input'), true) ?? [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($data['name'] ?? '');
    $price = $data['price'] ?? null;

    if ($name === '' || !filter_var($price, FILTER_VALIDATE_FLOAT) || $price < 0) {
        http_response_code(400);
        echo json_encode(['error' => 'Invalid name or price']);
        exit;
    }

    http_response_code(201);
    echo json_encode([
        'api' => 'secure-demo',
        'received' => ['name' => htmlspecialchars($name), 'price' => (float)$price]
    ]);
    exit;
}

echo json_encode(['status' => 'ok', 'key_present' => !empty($apiKey)]);

Exercises

  1. Add a GET endpoint that requires a token header and returns 401 if missing.
  2. Sanitize a description field with htmlspecialchars before echoing it back.
  3. Write three test cases (valid, missing field, negative price) and record the status codes.

Homework

  1. Refactor your Module 11.3 API to validate all inputs and return meaningful status codes.
  2. Write a short checklist (5 items) of how you will keep API keys safe in your final project.

Quiz

  1. Where should an API secret key live?
    • a) In the browser JavaScript
    • b) In a server-side config, never sent to the client ✅
    • c) In a public GitHub repo
    • d) In the HTML
  2. What does filter_var($price, FILTER_VALIDATE_FLOAT) return if invalid?
    • a) 0
    • b) false ✅
    • c) "invalid"
    • d) Throws an error
  3. What status code means "Unauthorized"?
    • a) 400
    • b) 401 ✅
    • c) 403
    • d) 500
  4. Why sanitize user input with htmlspecialchars?
    • a) To make it shorter
    • b) To prevent XSS by escaping HTML special chars ✅
    • c) To encrypt it
    • d) It is required by JSON
  5. Which is a good API testing habit?
    • a) Assume it works
    • b) Call it and check the JSON shape and status code ✅
    • c) Never test POST
    • d) Only test in production

End of Module 11. Remember: verify every AI-generated snippet by running it and reading the output.