Module 2: Programming for the Web

NSWSoftware EngineeringSyllabus dot point

Inquiry Question 2: How can data be better visualised using a web browser?

Design and consume RESTful APIs that exchange JSON, including resource modelling, request methods and status codes

A focused answer to the HSC Software Engineering Module 2 dot point on REST APIs. Resource modelling, JSON, HTTP methods mapped to CRUD, status codes, the worked example, and the traps markers look for.

Generated by Claude OpusReviewed by Better Tuition Academy5 min answer

Have a quick question? Jump to the Q&A page

What this dot point is asking

NESA wants you to design a REST API: resource paths, HTTP methods, JSON payloads, status codes. You should also be able to consume one from JavaScript (in the browser) or Python (requests).

The answer

What REST is

REST (Representational State Transfer) is an architectural style for APIs:

  • Resources are the nouns of the system: users, posts, tasks, products.
  • Each resource has a URL (/api/tasks, /api/tasks/42).
  • HTTP methods are the verbs: GET reads, POST creates, PUT/PATCH updates, DELETE removes.
  • The representation of a resource (the body returned by the server) is typically JSON.
  • The API is stateless: each request carries everything needed to process it (usually a token in the Authorization header).

Designing endpoints

Use plural nouns for collections, IDs for items:

Method Path Action Success status
GET /api/tasks List tasks (optionally filtered) 200
POST /api/tasks Create a task 201
GET /api/tasks/{id} Read one task 200
PUT /api/tasks/{id} Replace a task 200
PATCH /api/tasks/{id} Update some fields 200
DELETE /api/tasks/{id} Delete a task 204

Avoid verbs in URLs (/api/getTasks, /api/deleteTask). The HTTP method already conveys the action.

JSON

The standard payload format:

{
  "id": 42,
  "title": "Study Module 2",
  "due": "2026-06-15",
  "done": false,
  "tags": ["software-engineering", "study"]
}

Use camelCase or snake_case consistently. Use ISO 8601 (2026-06-15, 2026-06-15T10:00:00Z) for dates and times.

Status codes

  • 2xx success: 200 OK, 201 Created (with Location header), 204 No Content.
  • 4xx client error: 400 Bad Request, 401 Unauthorized (missing or invalid credentials), 403 Forbidden (logged in but not allowed), 404 Not Found, 409 Conflict (duplicate), 422 Unprocessable Entity, 429 Too Many Requests.
  • 5xx server error: 500 Internal Server Error, 503 Service Unavailable.

A worked endpoint

A Flask handler for POST /api/tasks:

@app.post("/api/tasks")
@require_login
def create_task():
    data = request.get_json(silent=True) or {}
    title = (data.get("title") or "").strip()
    due = (data.get("due") or "").strip()
    if not (1 <= len(title) <= 200):
        abort(400, "title length 1-200")
    with db() as conn:
        cur = conn.execute(
            "INSERT INTO tasks (user_id, title, due) VALUES (?, ?, ?)",
            (request.user_id, title, due or None),
        )
        task_id = cur.lastrowid
    return jsonify(
        id=task_id, title=title, due=due or None, done=False
    ), 201, {"Location": f"/api/tasks/{task_id}"}

Consuming from the browser

async function createTask(title, due) {
  const response = await fetch("/api/tasks", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({title, due}),
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  return response.json();
}

Consuming from Python

From a Python script or another back-end service, the requests library is the conventional choice for calling a REST API. It handles connection pooling and JSON parsing for you.

import requests

response = requests.post(
    "https://api.example.com/tasks",
    headers={"Authorization": f"Bearer {token}"},
    json={"title": "Study Module 2", "due": "2026-06-15"},
)
response.raise_for_status()
task = response.json()

Filtering and pagination

GET on a collection takes query string filters:

GET /api/tasks?done=false&due_before=2026-07-01&limit=20&offset=40

The server applies the filters in the WHERE clause and limits the page size.

Versioning

Plan for change. Include the version in the URL prefix:

GET /api/v1/tasks
GET /api/v2/tasks

or in a custom header (X-API-Version: 2).

Security

  • HTTPS only.
  • Authenticate every request (Authorization header).
  • Validate every field of the request body.
  • Authorise object-by-object (does this user own this task?).
  • Rate limit per token and per IP.

Past exam questions, worked

Real questions from past NESA papers on this dot point, with our answer explainer.

2024 HSC5 marksDesign a RESTful API for a simple todo list. List the endpoints, methods and status codes. Show one example request and response in JSON.
Show worked answer →

Endpoints:

Method Path Purpose Success status
GET /api/tasks List all tasks 200 OK
POST /api/tasks Create a task 201 Created
GET /api/tasks/:id Read one task 200 OK
PUT /api/tasks/:id Replace a task 200 OK
PATCH /api/tasks/:id Update fields 200 OK
DELETE /api/tasks/:id Delete a task 204 No Content

Error cases: 400 (bad input), 401 (not logged in), 403 (not allowed), 404 (not found).

Example - creating a task:

POST /api/tasks
Authorization: Bearer ...
Content-Type: application/json

{"title": "Study Module 2", "due": "2026-06-15"}

Response:

HTTP/1.1 201 Created
Location: /api/tasks/42
Content-Type: application/json

{"id": 42, "title": "Study Module 2", "due": "2026-06-15", "done": false}

Markers reward consistent resource-named paths (plural noun for the collection), correct method/code combinations (POST returning 201 with Location header, DELETE returning 204), a real JSON example with status line, and recognising that PATCH (partial update) and PUT (full replace) are distinct.

Related dot points