3 CoAP Messages: Codes, Tokens, and Options
3.1 Start With the Decision
A CoAP request can share a message ID yet belong to a different exchange. Codes, tokens, and options must each keep their own job.
3.2 Route Overview
This is part 2 of 3. Review CoAP Messages: Format Foundations for the preceding evidence.
3.3 Learning Objectives
- Map CoAP method and response codes to their wire values.
- Decode tokens and delta-encoded options from a message.
3.4 Chapter Roadmap
- The CoAP Message Format
- Minimum Viable Understanding: CoAP Message Structure
- The 4-Byte Fixed Header
- Message in a Bottle
- Checkpoint: Header Decisions
- CoAP Method Codes
- Idempotent Methods
- Response Codes
- Checkpoint: Methods and Codes
- Token: Request-Response Matching
- Token Security Consideration
- CoAP Options
- CBOR vs JSON for IoT
- Checkpoint: Tokens and Options
- Worked Example: Parsing a CoAP Message
- Worked Example: Decoding a GET Request
- Worked Example: GET /sensors/temp with JSON Response
- Putting Numbers to It
- Knowledge Check: Matching and Sequencing
3.5 The CoAP Message Format
Core Concept: A CoAP message consists of a 4-byte fixed header, optional token (0-8 bytes), zero or more options, and an optional payload. The fixed header contains version, message type, token length, method/response code, and message ID.
Why It Matters: Understanding the binary format is essential for debugging network captures, implementing CoAP libraries, and optimizing message sizes for constrained networks where every byte counts.
Key Takeaway: The 4-byte header efficiency is CoAP’s main advantage over HTTP - it encodes everything needed for request-response matching, reliability selection, and method identification in just 32 bits.
CoAP messages follow a compact binary format designed for efficiency:
CoAP message layout: compact fixed header followed by optional fields
4-byte fixed header
Ver, Type, TKL, Code, Message ID
Token
0-8 bytes for request-response matching
0xFF
Payload marker
Payload
Application data such as JSON, CBOR, sensor values, or firmware bytes
Header: always present and only 32 bits long, which is where most of CoAP’s efficiency starts.
Token: optional, but critical when multiple exchanges are in flight at once.
Options: sorted numerically so each option can encode only its delta from the previous one.
Payload: present only when the message carries application content after the 0xFF marker.
CoAP message structure showing the 4-byte fixed header followed by optional token, delta-encoded options, the payload marker (0xFF), and application payload.
3.6 The 4-Byte Fixed Header
Now move from design pressure to the packet: byte 0 through byte 3.
The fixed header contains all essential message metadata in just 32 bits:
- Byte 0: Version (2 bits), Type (2 bits), and Token Length (4 bits)
- Byte 1: Code
- Bytes 2-3: Message ID
| Field | Bits | Description |
|---|---|---|
| Ver | 2 | Version (always 01 for CoAP 1.0) |
| T | 2 | Type: CON (00), NON (01), ACK (10), RST (11) |
| TKL | 4 | Token Length (0-8 bytes) |
| Code | 8 | Method (0.xx) or Response (2.xx-5.xx) |
| Message ID | 16 | For deduplication and ACK matching |
3.6.1 Header Fields Explained
Version (Ver): Always 01 binary (value 1) for CoAP RFC 7252.
Type (T): Determines reliability and message flow:
| Type | Binary | Name | Purpose |
|---|---|---|---|
| CON | 00 | Confirmable | Reliable, requires ACK |
| NON | 01 | Non-confirmable | Fire-and-forget |
| ACK | 10 | Acknowledgment | Confirms CON receipt |
| RST | 11 | Reset | Rejects message |
Token Length (TKL): Number of token bytes (0-8). Tokens correlate responses to requests.
Code: Split into class (3 bits) and detail (5 bits), formatted as class.detail:
| Class | Range | Meaning |
|---|---|---|
| 0 | 0.01-0.04 | Methods (GET, POST, PUT, DELETE) |
| 2 | 2.01-2.05 | Success responses |
| 4 | 4.00-4.15 | Client error |
| 5 | 5.00-5.05 | Server error |
Message ID: 16-bit identifier for:
- Matching ACK/RST to CON messages
- Detecting duplicate messages (server caches for ~247 seconds)
3.6.2 When to Use Each Message Type: A Decision Guide
Choosing between CON and NON is one of the most important decisions in a CoAP implementation. The wrong choice either wastes battery on unnecessary retransmissions or silently loses critical commands.
| IoT Scenario | Recommended Type | Rationale |
|---|---|---|
| Temperature reading every 5 min | NON | Missing one reading out of 288/day is acceptable. Retransmission doubles airtime and battery cost for negligible benefit. |
| Firmware update chunk | CON | Every 256-byte block must arrive. A single missing block corrupts the entire firmware image. The cost of retransmission is far less than the cost of a bricked device. |
| Smoke alarm triggered | CON | Life-safety event. The server must acknowledge receipt. Use exponential backoff (2s, 4s, 8s, 16s) per RFC 7252 Section 4.2. |
| Soil moisture (LoRaWAN, 1% duty cycle) | NON | Duty cycle constraints mean retransmission may violate regulatory limits. Design the application to tolerate 5-10% packet loss. |
| Door lock command | CON | User expects confirmation that the lock state changed. Without ACK, the app cannot show “Locked” reliably. |
| Parking sensor heartbeat | NON | Heartbeats are periodic. If one is lost, the next one arrives in minutes. Only escalate to CON if the server hasn’t heard from the device in 3x the heartbeat interval. |
| HVAC setpoint change | CON | Changing from 22C to 18C is a deliberate user action. The system must confirm the setpoint was applied, not silently ignored. |
Rule of thumb: If losing the message would require human intervention to notice or correct, use CON. If the next periodic message will convey equivalent information, use NON.
Temperature Terry says: “Imagine sending a message in a bottle! The CoAP header is like the label you put on the bottle.”
The label tells you:
- Type: “Please write back!” (CON) or “No reply needed” (NON)
- Code: What you want - “Can I have the temperature?” (GET)
- Message ID: A number so you know which bottle they’re answering
Just like how a bottle label is tiny compared to the letter inside, CoAP’s header is tiny (4 bytes!) compared to HTTP’s headers (hundreds of bytes!).
Checkpoint: Header Decisions
You now know:
- Byte 0 splits into Version, Type, and TKL; byte 1 is Code; bytes 2-3 are Message ID.
- CON needs an ACK; NON fits readings where the next sample can recover from loss.
- Message ID supports ACK matching and duplicate detection for about 247 seconds.
3.7 CoAP Method Codes
With transport behavior decoded, ask what the endpoint was told to do.
CoAP methods mirror HTTP methods but use numeric codes:
| Code | Method | Description | Idempotent |
|---|---|---|---|
| 0.01 | GET | Retrieve resource | Yes |
| 0.02 | POST | Create resource or submit data | No |
| 0.03 | PUT | Update/replace resource | Yes |
| 0.04 | DELETE | Remove resource | Yes |
An idempotent method produces the same result regardless of how many times it’s called:
GET /temperaturereturns current temperature (safe to retry)PUT /led {"on": true}sets LED on (calling twice = same result)DELETE /alarm/5removes alarm 5 (calling twice = same result, even if already deleted)
POST is NOT idempotent - POST /log {"event": "click"} creates new entry each time.
Why this matters: When a CON message times out, CoAP can safely retry idempotent methods. For POST, the application must handle potential duplicates.
3.8 Response Codes
CoAP uses a structured response code system similar to HTTP:
3.8.1 Success (2.xx)
| Code | Name | HTTP Equivalent | Use Case |
|---|---|---|---|
| 2.01 | Created | 201 Created | POST created new resource |
| 2.02 | Deleted | 200 OK (for DELETE) | Resource removed |
| 2.03 | Valid | 304 Not Modified | Cached response still valid |
| 2.04 | Changed | 200 OK (for PUT) | Resource updated |
| 2.05 | Content | 200 OK | GET successful with payload |
3.8.2 Client Error (4.xx)
| Code | Name | HTTP Equivalent | Cause |
|---|---|---|---|
| 4.00 | Bad Request | 400 | Malformed request |
| 4.01 | Unauthorized | 401 | Missing authentication |
| 4.03 | Forbidden | 403 | Access denied |
| 4.04 | Not Found | 404 | Resource doesn’t exist |
| 4.05 | Method Not Allowed | 405 | Wrong method for resource |
| 4.12 | Precondition Failed | 412 | ETag mismatch |
| 4.15 | Unsupported Content-Format | 415 | Unknown payload format |
3.8.3 Server Error (5.xx)
Server errors mean the request was understood but the server or an upstream hop could not complete it. Read the class from general to specific: 5.00 Internal Server Error covers an unexpected local failure, 5.01 Not Implemented says the requested method capability is absent, and 5.03 Service Unavailable signals a temporary overload. The gateway-specific 5.02 Bad Gateway and 5.04 Gateway Timeout preserve whether the upstream reply was invalid or never arrived, which determines whether a client should retry, fall back, or escalate.
| Code | Name | HTTP Equivalent | Cause |
|---|---|---|---|
| 5.00 | Internal Server Error | 500 | Server crashed |
| 5.01 | Not Implemented | 501 | Method not supported |
| 5.02 | Bad Gateway | 502 | Proxy error |
| 5.03 | Service Unavailable | 503 | Server overloaded |
| 5.04 | Gateway Timeout | 504 | Proxy timeout |
Checkpoint: Methods and Codes
You now know:
- Method codes 0.01 through 0.04 map to GET, POST, PUT, and DELETE.
- Successful PUT returns 2.04 Changed; successful GET with payload returns 2.05 Content.
- Client and server failures remain visible as 4.xx and 5.xx responses.
3.9 Token: Request-Response Matching
Code tells you the operation; Token ties the response back to a request.
The Token correlates responses to requests, especially important when multiple requests are in flight:
Client sends: GET /temperature, Token=0xAB12, MsgID=0x5678
Client sends: GET /humidity, Token=0xCD34, MsgID=0x5679
Server sends: 2.05 Content, Token=0xCD34, "65%" (humidity response)
Server sends: 2.05 Content, Token=0xAB12, "22.5" (temperature response)
Token vs. Message ID:
| Aspect | Token | Message ID |
|---|---|---|
| Purpose | Match response to request | Deduplication, ACK matching |
| Scope | Application-level | Transport-level |
| Length | 0-8 bytes (TKL field) | Fixed 16 bits |
| Persistence | Across retransmissions | Changes on each transmission |
| Generated by | Client | Client |
In secure deployments (DTLS), tokens should be unpredictable (randomly generated) to prevent response spoofing attacks. A malicious actor who can predict tokens could inject fake responses.
# BAD: Sequential tokens
token = counter
counter += 1
# GOOD: Random tokens
import os
token = os.urandom(4)
3.10 CoAP Options
After header and token, parse sorted options first and payload only after the marker.
Options carry metadata similar to HTTP headers but use efficient binary encoding:
3.10.1 Common Options
| Option Number | Name | Length | Purpose |
|---|---|---|---|
| 3 | Uri-Host | String | Target host |
| 7 | Uri-Port | 0-2 bytes | Target port |
| 11 | Uri-Path | String | Path segments (/sensors/temp) |
| 12 | Content-Format | 0-2 bytes | Payload MIME type |
| 14 | Max-Age | 0-4 bytes | Cacheability (seconds) |
| 17 | Accept | 0-2 bytes | Acceptable response format |
| 35 | Proxy-Uri | String | For proxied requests |
3.10.2 Option Delta Encoding
Options are sorted by number and use delta encoding to minimize bytes:
Read these points as one connected sequence: start with Option delta (OD): 4 bits storing the difference from the previous option number; then Option length (OL): 4 bits storing the number of value bytes; then Extended delta: 0, 1, or 2 extra bytes when the delta does not fit in 4 bits; and finish with Value: the option payload bytes.
- Option delta (OD): 4 bits storing the difference from the previous option number
- Option length (OL): 4 bits storing the number of value bytes
- Extended delta: 0, 1, or 2 extra bytes when the delta does not fit in 4 bits
- Value: the option payload bytes
Example: Encoding Uri-Path /sensors/temp
Read these points as one connected sequence: start with Option 1: Uri-Path = "sensors" uses delta 11, length 7, and encodes as 0xB7 | "sensors"; then Option 2: Uri-Path = "temp" uses delta 0, length 4, and encodes as 0x04 | "temp"; and finish with Total size: 13 bytes vs HTTP GET /sensors/temp HTTP/1.1\r\n at 27 bytes.
- Option 1:
Uri-Path = "sensors"uses delta11, length7, and encodes as0xB7 | "sensors" - Option 2:
Uri-Path = "temp"uses delta0, length4, and encodes as0x04 | "temp" - Total size: 13 bytes vs HTTP
GET /sensors/temp HTTP/1.1\r\nat 27 bytes
3.10.3 Content-Format Codes
The Content-Format option tells the receiver how to decode the payload, so select it as part of the resource contract rather than after serialization. 0 text/plain fits a human-readable scalar, while 50 application/json supports familiar structured objects. On constrained links, 60 application/cbor carries structured data in a compact binary representation; 40 application/link-format has the separate job of encoding discovery links. A receiver must interpret the numeric code before parsing payload bytes.
| Code | MIME Type | Description |
|---|---|---|
| 0 | text/plain | Simple text |
| 40 | application/link-format | Resource discovery |
| 41 | application/xml | XML data |
| 42 | application/octet-stream | Binary data |
| 47 | application/exi | Efficient XML |
| 50 | application/json | JSON data |
| 60 | application/cbor | Compact Binary (CBOR) |
CBOR (Concise Binary Object Representation) is to JSON what CoAP is to HTTP - a compact binary alternative:
# JSON (42 bytes)
{"device":"temp42","value":23.5,"unit":"C"}
# CBOR (~20 bytes) - same data, half the size
A3 66 64 65 76 69 63 65 66 74 65 6D 70 34 32...
When to use:
- CBOR: Production deployments, battery-powered devices, constrained networks
- JSON: Development, debugging, cloud integration with JSON-native APIs
Checkpoint: Tokens and Options
You now know:
- Tokens are 0-8 bytes and correlate responses to requests.
- Uri-Path 11 and Content-Format 12 are sorted delta options, not text headers.
- Content-Format 50 for JSON and 60 for CBOR tells the receiver how to parse payload.
3.11 Worked Example: Parsing a CoAP Message
For the examples, keep the order fixed: header, token, options, marker, payload.
3.11.1 Worked Example: Complete Sensor Reading – CoAP vs HTTP
3.12 Continue to the Next Part
Carry this evidence into CoAP Messages: Parsing and Validation, which begins with Label the Diagram.
