11 REST API Practice: Design Examples
More
Depth: Practitioner
Progress saves as you read. Mark sections complete as you go; your progress appears in the sidebar.
Start with the story: A smart thermostat needs a web address, or URL, for its reading. A method says what the app asks it to do. A status code says how the request went; a payload is the data sent with it. These choices are part of an API, the agreed set of requests an app can make. Each worked example turns an IoT situation, such as an offline device, into a choice you can test.
11.1 Start With the Decision
This section: Start With the Decision — The mathematical gist.
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 section: Route Overview — This is part 1 of 2.
This is part 1 of 2. Continue with REST API Practice: Protocol Review.
11.3 Part Objectives
This section: 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
This section: 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
This section: 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
This section: 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
This section: Worked Examples: REST API Design for IoT — These worked examples demonstrate practical REST API design decisions for real-world IoT scenarios.
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:
Assume each thermostat sends one report request every 30 seconds, with a 250-byte request/response overhead allowance and a 120-byte JSON body: 370 bytes per report. The allowance is illustrative and excludes lower-layer bytes. Daily application-byte traffic:
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.6 kB = 69.12 MB/day for historical query payloads, assuming one device-day per user. The two modeled components total 532.8 + 69.12 = 601.92 MB/day (decimal), before history-response headers, other app requests, and network overhead.
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
This section: Key Takeaways
11.10 Summary
REST API Design Principles:
First name resources and versions; then choose status codes and freshness fields so clients can distinguish cached data from missing devices.
- 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:
Show when cached data was last fresh. Then choose a device link and gateway role.
- 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:
CoAP and MQTT serve different traffic patterns; a hybrid can preserve both, while the listed API mistakes show where semantics fail.
- 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:
These errors mix up lost data with a missing resource. They also skip payload and battery cost.
- Returning 503 for offline devices when cached data is available (confuses mobile apps)
- Using HTTP for battery-constrained sensors (headers and handshakes swamp tiny payloads; even minimal CoAP/UDP/IPv4/Ethernet is 92% headers for 4 bytes)
- 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 the explicit minimal-header CoAP/UDP/IPv4/Ethernet example, 46 of 50 counted bytes are headers (92%); actual frames may include options, security, and more link overhead.
- 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
This section: Knowledge Check: Matching and Sequencing
11.12 Quiz: Comprehensive Protocol Review
This section: Quiz: Comprehensive Protocol Review
11.13 Continue to the Next Part
This section: Continue to the Next Part — Carry this evidence into REST API Practice: Protocol Review, which begins with Quiz 2: Comprehensive Review.
Carry this evidence into REST API Practice: Protocol Review, which begins with Quiz 2: Comprehensive Review.
Find help
3 reviewed answers.
Where should I start in a module?
Open the module page from the sidebar to see its chapters in order. Use the module map to return to a topic you need.
Modules and pathsReviewed
What can I try when a project does not work?
Check the symptom, then work through the diagnostic steps. Keep the error message and the smallest example that reproduces it.
When you are stuckReviewed
How do interactive examples work?
Use the interactive guide to check how examples and simulations work before changing your project.
Interactive examples guideReviewed
