Chapters

11 REST API Practice: Design Examples

app-protocols
rest
api

Start with the story: The design rules become real when you have to choose the exact URL, method, status code, and payload for a smart thermostat or offline device. Each worked example turns an IoT situation into an API decision you can test.

11.1 Start With the Decision

The mathematical gist. A 1000 mAh nameplate becomes 2.52 Wh usable at 3.6 V after the chapter’s illustrative 30% reserve.

11.2 Route Overview

This is part 1 of 2. Continue with REST API Practice: Protocol Review.

11.3 Part Objectives

  • Test how this chapter fits with a concrete scenario and pass criteria.
  • Validate match the concepts with a concrete scenario and pass criteria.
In 60 Seconds

Design the Offline Case First

Picture a heating app that shows a successful change while the room unit is offline. The screen accepted the request, but the physical setting never changed. A clear service design must separate accepting work, completing work, and reporting an old state.

A protocol is a shared set of message rules. An application programming interface is a defined way for software parts to request work or data; it is often shortened to API. Hypertext Transfer Protocol (HTTP) is a web message protocol. Constrained Application Protocol (CoAP) is a compact web-style option for small devices. Telemetry means device readings and status. Message Queuing Telemetry Transport (MQTT) is a publish-and-subscribe message protocol. Bandwidth is the amount of data a link can carry in a set time.

For one resource, write the address, allowed action, request body, reply, permission, and offline rule. Test a valid request, bad input, denied user, missing device, repeated change, late result, and reconnect. The stored state and the real device must tell the same honest story.

These examples cannot choose one method for every product. The deeper sections compare status, resource shape, message cost, and asynchronous work so each interface exposes uncertainty instead of hiding it. This chapter provides hands-on practice designing RESTful IoT APIs through worked examples covering resource hierarchies, proper HTTP status codes for device states, offline device handling, protocol selection between CoAP/MQTT/HTTP, and calculating protocol overhead impact on battery life.

The mathematical gist. A 1000 mAh nameplate becomes 2.52 Wh usable at 3.6 V after the chapter’s illustrative 30% reserve. A 44.7 mA burst through 15 Ω sags by 0.671 V, and adding 10.0 mAh/year self-discharge gives about 30.9 CoAP years versus 26.9 MQTT years—not the idealised 79 versus 62.5.

Math Bridge · guided foundationsWhy does a 79-year estimate become about 31 years?Let Bex add voltage sag, reserved charge, and self-discharge to the protocol ledger.
Chapter Roadmap
  • In 60 Seconds
  • Phoebe’s Field Notes: What The Idealised 79-Year Battery Number Leaves Out
  • Key Concepts
  • For Beginners: REST API Examples
  • Building a Real API
  • Prerequisites
  • How This Chapter Fits
  • Worked Examples: REST API Design for IoT
  • Worked Example: Designing a Smart Thermostat REST API
  • Putting Numbers to It
  • Checkpoint: Resource Modeling
  • Worked Example: Handling Device Offline State in REST APIs
  • Checkpoint: Offline Devices
  • Quick Check: Offline Device Handling
  • Code Challenge
  • Key Takeaways
  • Label the Diagram
  • Order the Steps
  • Match the Concepts
  • Summary
  • Checkpoint: Status and Protocol Choices
  • Knowledge Check: Matching and Sequencing
  • Quiz: Comprehensive Protocol Review

This is a long worked-example chapter, so use it as a sequence of design decisions:

  1. First convert thermostat requirements into resource paths, methods, responses, and request load.
  2. Then handle an offline tracker without confusing stale data with missing resources.
  3. Next use the quizzes to test status codes, protocol choice, and byte-level overhead.
  4. After that use the calculators to scale requests, payloads, battery life, and fleet bandwidth.
  5. Finally read one HTTP exchange like a device contract and design the parking API yourself.

Checkpoints recap what each section has established, and the longer calculators can be treated as deep-dive tools on a first pass.

11.4 Learning Objectives

By the end of this chapter, you will be able to:

  • Design RESTful IoT APIs: Construct resource hierarchies that apply REST constraints to multi-device deployments
  • Implement Proper Error Handling: Select and apply the correct HTTP status codes for all device states including offline and missing resources
  • Diagnose Offline Device Scenarios: Distinguish between “no data” (404), “stale data” (200 with metadata), and “service unavailable” (503) in IoT REST APIs
  • Compare Protocol Trade-offs: Evaluate CoAP, MQTT, and HTTP against deployment constraints such as battery life, latency, and network topology
  • Calculate Protocol Overhead: Assess the byte-level impact of protocol choice on battery life and justify the selection for constrained IoT devices

Read these points as one connected sequence: start with Core Concept: Fundamental principle underlying REST API Practice — understanding this enables all downstream design decisions; then Key Metric: Primary quantitative measure for evaluating REST API Practice performance in real deployments; then Trade-off: Central tension in REST API Practice design — optimizing one parameter typically degrades another; then Protocol/Algorithm: Standard approach or algorithm most commonly used in REST API Practice implementations; then Deployment Consideration: Practical factor that must be addressed when deploying REST API Practice in production; then Common Pattern: Recurring design pattern in REST API Practice that solves the most frequent implementation challenges; and finish with Performance Benchmark: Reference values for REST API Practice performance metrics that indicate healthy vs. problematic operation.

  • Core Concept: Fundamental principle underlying REST API Practice — understanding this enables all downstream design decisions
  • Key Metric: Primary quantitative measure for evaluating REST API Practice performance in real deployments
  • Trade-off: Central tension in REST API Practice design — optimizing one parameter typically degrades another
  • Protocol/Algorithm: Standard approach or algorithm most commonly used in REST API Practice implementations
  • Deployment Consideration: Practical factor that must be addressed when deploying REST API Practice in production
  • Common Pattern: Recurring design pattern in REST API Practice that solves the most frequent implementation challenges
  • Performance Benchmark: Reference values for REST API Practice performance metrics that indicate healthy vs. problematic operation

11.5 For Beginners: REST API Examples

This chapter walks through complete REST API designs for real IoT scenarios. You will see how to create endpoints for reading sensor data, controlling actuators, and managing device fleets. Each example includes the URL structure, request format, and response format, so you can use them as templates for your own projects.

“Let’s build an actual API for our smart garden!” said Max the Microcontroller, rolling up his sleeves. “Sammy, you’re the temperature sensor at /api/v1/sensors/garden-temp. When someone sends a GET request to your URL, you reply with your current reading in JSON.”

Sammy practiced: “GET /api/v1/sensors/garden-temp and I respond with {\"value\": 24.5, \"unit\": \"celsius\", \"timestamp\": \"2026-02-07T10:30:00Z\"}. Easy!”

“Now for the sprinkler control,” Lila the LED continued. “POST to /api/v1/actuators/sprinkler/commands with a body like {\"action\": \"water\", \"duration_minutes\": 15}. The sprinkler turns on and returns a 202 Accepted status — meaning ‘got it, working on it’ — because watering takes time.”

Bella the Battery added the fleet management angle: “And GET /api/v1/devices?status=low-battery returns all devices that need charging. See how the URL pattern is consistent? Resources are nouns, actions use HTTP verbs, and filters go in query parameters. Follow the pattern and every developer who sees your API will instantly understand it!”

11.6 Prerequisites

Before diving into this chapter, you should be familiar with:

11.7 How This Chapter Fits

REST API Design Series Navigation:

Read these points as one connected sequence: start with Introduction and Why Lightweight Protocols Matter; then Protocol Overview and Comparison; then REST API Design for IoT (Index); then Design Patterns; then Worked Examples and Quizzes (this chapter); then Real-Time Protocol Workflows; and finish with Protocol Selection Worked Examples.

  1. Introduction and Why Lightweight Protocols Matter
  2. Protocol Overview and Comparison
  3. REST API Design for IoT (Index)
  4. Real-Time Protocol Workflows
  5. Protocol Selection Worked Examples

This chapter provides hands-on practice with REST API design through worked examples and comprehensive quizzes.


11.8 Worked Examples: REST API Design for IoT

These worked examples demonstrate practical REST API design decisions for real-world IoT scenarios.

The first example is deliberately concrete: one thermostat fleet, one mobile app, and a few endpoints that must stay predictable as the deployment grows.

Worked Example: Designing a Smart Thermostat REST API

Scenario: You are building a REST API for a smart thermostat system that allows mobile apps to read current temperature, set target temperature, and retrieve historical data. The system has 500 deployed thermostats.

Given:

  • Thermostat reports temperature every 30 seconds
  • Users want real-time display and control from mobile app
  • Historical data retention: 30 days
  • Expected concurrent mobile app users: 2,000

Steps:

  1. Define resource hierarchy - Organize resources around the device:

    /api/v1/thermostats/{device_id}              # Device info
    /api/v1/thermostats/{device_id}/temperature  # Current reading
    /api/v1/thermostats/{device_id}/setpoint     # Target temperature
    /api/v1/thermostats/{device_id}/history      # Historical readings
  2. Choose HTTP methods for each operation:

    • GET /thermostats/thermo-42/temperature - Read current temp (idempotent)
    • PUT /thermostats/thermo-42/setpoint - Set target (full update, idempotent)
    • GET /thermostats/thermo-42/history?start=2025-01-01&end=2025-01-15 - Query with filters
  3. Design response format with proper status codes:

    // GET /thermostats/thermo-42/temperature
    // Response: 200 OK
    {
      "device_id": "thermo-42",
      "current_temp_c": 22.5,
      "humidity_pct": 45,
      "timestamp": "2025-01-15T10:30:00Z",
      "unit": "celsius"
    }
    
    // PUT /thermostats/thermo-42/setpoint with body {"target_c": 21.0}
    // Response: 200 OK (or 204 No Content)
    {
      "device_id": "thermo-42",
      "target_c": 21.0,
      "estimated_time_minutes": 15
    }
    
    // GET /thermostats/nonexistent/temperature
    // Response: 404 Not Found
    {
      "error": "DEVICE_NOT_FOUND",
      "message": "Device 'nonexistent' is not registered",
      "timestamp": "2025-01-15T10:30:00Z"
    }

Result: A clean, RESTful API with predictable endpoints, proper HTTP semantics, and clear error handling. The hierarchy /thermostats/{id}/resource scales to thousands of devices while remaining intuitive for developers.

For a deployment of 500 thermostats reporting every 30 seconds, calculate the API request load:

Requests per second=500 devices30 s16.67 req/s\text{Requests per second} = \frac{500 \text{ devices}}{30 \text{ s}} \approx 16.67 \text{ req/s}

Each GET request (with HTTP/1.1 keep-alive) averages 250 bytes overhead + 120 bytes JSON payload = 370 bytes. Daily bandwidth:

Daily data=16.67reqs×370bytesreq×86400sday=533 MB/day\text{Daily data} = 16.67 \frac{\text{req}}{\text{s}} \times 370 \frac{\text{bytes}}{\text{req}} \times 86400 \frac{\text{s}}{\text{day}} = 533 \text{ MB/day}

For historical data queries returning 2,880 readings per thermostat per day (30-second intervals):

Query payload=2880×120 bytes=345 KB per device per day\text{Query payload} = 2880 \times 120 \text{ bytes} = 345 \text{ KB per device per day}

With 2,000 concurrent users, if 10% query historical data daily, that’s 200 users × 345 KB = 69 MB/day for historical queries. Total bandwidth: 533 + 69 = 602 MB/day, well within most cloud tier limits.

Key Insight: REST API design should follow the principle of resource-oriented design - model your API around nouns (thermostat, temperature, setpoint) not verbs (getTemperature, setTarget). The HTTP methods (GET, PUT, POST, DELETE) provide the verbs. This makes the API self-documenting and consistent across all resources.

Broker BexCheckpoint: Resource Modeling

You now know:

  • A 500-thermostat fleet reporting every 30 seconds produces about 16.67 requests per second.
  • Keeping resources as nouns lets GET, PUT, and query filters carry the action without inventing verb-style URLs.
  • The same hierarchy can return current readings, setpoints, history, and clean 404 Not Found errors without changing the API shape.

Worked Example: Handling Device Offline State in REST APIs

Scenario: A fleet management system has 1,000 GPS trackers on delivery trucks. Some trucks lose cellular connectivity in remote areas. Your REST API must handle requests for offline devices gracefully without confusing mobile app users.

Given:

  • GPS trackers report location every 60 seconds when connected
  • Some trucks go offline for hours in low-coverage areas
  • Mobile dispatch app needs last known location even when device is offline
  • App users must clearly understand device connectivity status

Steps:

  1. Define “offline” threshold and track last-seen timestamp:

    OFFLINE_THRESHOLD_SECONDS = 180  # 3 minutes without heartbeat
    
    def is_device_online(device_id):
        last_seen = get_last_heartbeat(device_id)
        age_seconds = (now() - last_seen).total_seconds()
        return age_seconds < OFFLINE_THRESHOLD_SECONDS
  2. Include connectivity metadata in every response:

    // GET /api/v1/vehicles/truck-42/location
    // Response: 200 OK (even if offline - we have cached data)
    {
      "vehicle_id": "truck-42",
      "latitude": 37.7749,
      "longitude": -122.4194,
      "speed_kmh": 0,
      "heading_degrees": 90,
      "timestamp": "2025-01-15T08:15:00Z",
      "connectivity": {
        "status": "offline",
        "last_seen": "2025-01-15T08:15:00Z",
        "offline_duration_minutes": 135
      }
    }
  3. Use appropriate HTTP status codes for different scenarios:

    @app.route('/api/v1/vehicles/<vehicle_id>/location')
    def get_location(vehicle_id):
        vehicle = db.get_vehicle(vehicle_id)
    
        if not vehicle:
            # Device never registered
            return {"error": "VEHICLE_NOT_FOUND"}, 404
    
        location = cache.get_last_location(vehicle_id)
    
        if not location:
            # Device registered but never reported location
            return {"error": "NO_LOCATION_DATA",
                    "message": "Device has not reported location yet"}, 404
    
        # Return cached location with connectivity status
        # Use 200 OK - we have valid data, just stale
        return {
            "vehicle_id": vehicle_id,
            "latitude": location.lat,
            "longitude": location.lng,
            "timestamp": location.timestamp.isoformat(),
            "connectivity": get_connectivity_status(vehicle_id)
        }, 200

Result: The API returns 200 OK with the last known location and explicit connectivity metadata, allowing the mobile app to display “Last seen 2 hours ago at [location]” rather than showing an error. The 404 status is reserved for truly missing resources (unknown vehicle ID).

Key Insight: For IoT REST APIs, distinguish between “no data” and “stale data”. A device being offline is not an error condition - it’s expected state information. Return cached/stale data with metadata about freshness rather than failing with 503 Service Unavailable. This keeps mobile apps functional even with intermittent device connectivity.

Broker BexCheckpoint: Offline Devices

You now know:

  • A tracker can be considered offline after 180 seconds without heartbeat, but that does not make the resource disappear.
  • 200 OK fits cached location plus connectivity metadata; 404 is for unknown vehicles or missing data.
  • 503 Service Unavailable is reserved for cases where the service cannot fulfill the request and should usually include retry guidance.
Quick Check: Offline Device Handling

The next few quizzes switch from reading examples to making choices. Treat each answer as a client-behavior contract: the status code tells firmware whether to retry, fix input, refresh credentials, or stop.

Code Challenge

11.9 Key Takeaways

Label the Diagram
Order the Steps
Match the Concepts

11.10 Summary

REST API Design Principles:

Read these points as one connected sequence: start with Model APIs around resources (nouns), not actions (verbs) — use HTTP methods (GET, PUT, POST, DELETE) as the verbs; then Organize resource hierarchies: /api/v1/{collection}/{id}/{sub-resource} scales to thousands of devices; and finish with Include API versioning in the URL path (e.g., /api/v1/) for backward compatibility.

  • Model APIs around resources (nouns), not actions (verbs) — use HTTP methods (GET, PUT, POST, DELETE) as the verbs
  • Organize resource hierarchies: /api/v1/{collection}/{id}/{sub-resource} scales to thousands of devices
  • Include API versioning in the URL path (e.g., /api/v1/) for backward compatibility

Offline Device Handling:

Read these points as one connected sequence: start with Return 200 OK with stale data plus connectivity metadata for offline devices with cached data; then Reserve 404 for truly missing resources (unknown device ID) and 503 for temporarily unavailable services; and finish with Include last_seen, offline_duration, and data_freshness fields so clients can make informed decisions.

  • Return 200 OK with stale data plus connectivity metadata for offline devices with cached data
  • Reserve 404 for truly missing resources (unknown device ID) and 503 for temporarily unavailable services
  • Include last_seen, offline_duration, and data_freshness fields so clients can make informed decisions

Protocol Selection for IoT:

Read these points as one connected sequence: start with CoAP over UDP: Best for battery-powered sensors with sporadic transmission (4-byte header, no TCP handshake); then MQTT over TCP: Best for publish-subscribe patterns with multiple subscribers (dashboards, cloud analytics); and finish with Hybrid architectures (CoAP local + MQTT cloud) combine the strengths of both patterns.

  • CoAP over UDP: Best for battery-powered sensors with sporadic transmission (4-byte header, no TCP handshake)
  • MQTT over TCP: Best for publish-subscribe patterns with multiple subscribers (dashboards, cloud analytics)
  • Hybrid architectures (CoAP local + MQTT cloud) combine the strengths of both patterns

Common Pitfalls:

Read these points as one connected sequence: start with Returning 503 for offline devices when cached data is available (confuses mobile apps); then Using HTTP for battery-constrained sensors (92% protocol overhead for small payloads); and finish with Designing verb-based endpoints (/getTemperature) instead of resource-based (/temperature).

  • Returning 503 for offline devices when cached data is available (confuses mobile apps)
  • Using HTTP for battery-constrained sensors (92% protocol overhead for small payloads)
  • Designing verb-based endpoints (/getTemperature) instead of resource-based (/temperature)
Broker BexCheckpoint: Status and Protocol Choices

You now know:

  • 201 Created belongs to successful device registration, while 200 OK belongs to successful reads or cached stale data.
  • For a 4-byte payload over CoAP/UDP/IPv4/Ethernet, the chapter’s 46 header bytes make protocol overhead 92%.
  • CoAP fits constrained request-response sensors; MQTT fits publish-subscribe monitoring; HTTP is useful but expensive for tiny battery messages.

11.11 Knowledge Check: Matching and Sequencing

11.12 Quiz: Comprehensive Protocol Review

11.13 Continue to the Next Part

Carry this evidence into REST API Practice: Protocol Review, which begins with Quiz 2: Comprehensive Review.