11 REST API Practice: Design Examples
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
- 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:
- First convert thermostat requirements into resource paths, methods, responses, and request load.
- Then handle an offline tracker without confusing stale data with missing resources.
- Next use the quizzes to test status codes, protocol choice, and byte-level overhead.
- After that use the calculators to scale requests, payloads, battery life, and fleet bandwidth.
- 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:
- REST API Design Patterns: API design best practices, versioning, payload formats
- Protocol Overview and Comparison: Technical comparison of HTTP, MQTT, and CoAP
- HTTP Basics: Request methods (GET, POST, PUT, DELETE), status codes, headers
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.
- Introduction and Why Lightweight Protocols Matter
- Protocol Overview and Comparison
- REST API Design for IoT (Index)
- Design Patterns
- Worked Examples and Quizzes (this chapter)
- Real-Time Protocol Workflows
- 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.
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:
-
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 -
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
-
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:
Each GET request (with HTTP/1.1 keep-alive) averages 250 bytes overhead + 120 bytes JSON payload = 370 bytes. Daily bandwidth:
For historical data queries returning 2,880 readings per thermostat per day (30-second intervals):
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.
Checkpoint: 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 Founderrors without changing the API shape.
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:
-
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 -
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 } } -
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.
Checkpoint: 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 OKfits cached location plus connectivity metadata;404is for unknown vehicles or missing data.503 Service Unavailableis reserved for cases where the service cannot fulfill the request and should usually include retry guidance.
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.
11.9 Key Takeaways
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, anddata_freshnessfields 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)
Checkpoint: Status and Protocol Choices
You now know:
201 Createdbelongs to successful device registration, while200 OKbelongs 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.
