Messaging
How messages flow through agrirouter: capabilities, subscriptions, routing, addressing, and the message lifecycle
Messaging is the core function of agrirouter. Every piece of agricultural data (task files, telemetry positions, device descriptions, images, and more) travels through the agrirouter messaging system. Understanding how messages flow is essential for building a working integration.
Message Structure
A message is a standard HTTP request. The parts of the request each carry a different kind of information:
- URI (path and query) addresses the API operation you are invoking.
- Headers carry request metadata as
x-agrirouter-*parameters: the technical message type (x-agrirouter-message-type), addressing mode (x-agrirouter-is-publish), direct recipients (x-agrirouter-direct-recipients), sender identity, and other per-operation parameters, alongside standard HTTP headers for authentication. - Payload (request body) carries the agricultural data itself: a task file, a device description, a GPS position stream, and so on. The technical message type in the headers tells agrirouter how to interpret the payload.
For the exact headers and payload schema per operation, see the API Reference.
Capabilities
Before an endpoint can participate in any data exchange, it must declare its capabilities: the technical message types it can send or receive. Capabilities are how you tell agrirouter "I can produce GPS data" or "I can receive task files."
Capabilities serve two purposes:
- They tell agrirouter what the endpoint can do. The routing engine uses capabilities to validate that a message can actually be delivered to a recipient.
- They appear in the agrirouter UI. The end user sees each endpoint's capabilities when configuring routes, so they know what data each endpoint supports.
Declaring Capabilities
Capabilities are provided when creating an endpoint via PUT /endpoints/{externalId} and can be updated at any time by sending the same request again. Each capability entry specifies:
- A technical message type (e.g.,
iso:11783:-10:taskdata:zip) - A direction: send only, receive only, or send and receive
An endpoint without capabilities cannot send or receive any agricultural data. Capabilities are required when creating the endpoint.
Subscriptions
Subscriptions declare which published message types an endpoint wants to receive. Capabilities define what an endpoint can handle, subscriptions define what it wants to receive proactively. Subscriptions work like a newsletter opt-in: you tell agrirouter "notify me whenever anyone publishes GPS data", and only then will broadcast messages of that type be delivered to you.
Subscriptions only apply to the publish addressing mode. Directly addressed messages are delivered regardless of subscriptions (as long as a valid route and matching capabilities exist).
Recommended approach
An endpoint should subscribe to every message type it can handle. Skip subscription only if the endpoint must exclusively receive directly-addressed messages, the narrow case where any published message would be noise. Subscribing to everything you can receive is the default.
How Subscriptions Work
- Endpoint A declares a subscription for message type X
- Endpoint B publishes a message of type X
- The following conditions are checked: Is there a route from B to A? Does A have the capability to receive type X? Is A subscribed to type X?
- If all three conditions are met, the message is delivered to A's feed
Declaring Subscriptions
Subscriptions are included alongside capabilities in the PUT /endpoints/{externalId} request. Each subscription entry specifies:
- A technical message type to subscribe to
Each PUT request replaces all previous capabilities and subscriptions with the values in the request.
Routing
Routes are how the end user (farmer or contractor) controls data flow. They are configured in the agrirouter UI, not by the application. You do not create routes as a developer, but you need to understand them because they directly affect whether your messages are delivered.
A route specifies:
- A source endpoint
- A destination endpoint
- The information types that are allowed to flow from source to destination
Routes operate on information types: the semantic category of data being exchanged (for example, "task data" or "telemetry"). This is coarser than the technical message type, which identifies the exact payload format. One information type typically maps to several technical message types.
If no route exists between two endpoints for a given information type, the message will not be delivered, even if both endpoints have the correct capabilities and subscriptions.
Message Addressing
When sending a message, the application must choose how to address it. There are two addressing modes, and they can be combined. Direct addressing is like sending a letter to a specific person. Publishing is like posting a notice on a bulletin board that anyone interested can read.
Direct Addressing
The sender specifies one or more recipient endpoint IDs explicitly. The message is delivered to each specified recipient, provided:
- A route exists from sender to recipient for the information type
- The recipient has the capability to receive the message type
Direct addressing is used when the sender knows exactly who should receive the data, for example sending a task file to a specific machine.
This mode is most common for interactive, user-invoked messaging, where a user explicitly selects a recipient in the application's UI.
Discovering endpoints to address
Your application discovers the endpoints it can directly address from the
gateway itself: call GET /tenants at startup
to bootstrap the per-tenant endpoint list, and react to the
ENDPOINTS_LIST_CHANGED SSE event to
keep the local cache up to date without polling. To refresh a single tenant
out of band, call GET /tenants/{tenantId}/endpoints.
Publishing
The sender does not specify recipients. Instead, the message is delivered to all endpoints that are subscribed to the message type, provided:
- A route exists from the sender to the subscriber for the information type
- The subscriber has the capability to receive the message type
- The subscriber has an active subscription for the message type
Publishing is used when the sender does not know or care who specifically will receive the data, for example a VCU publishing telemetry data that any interested software can pick up.
This mode is most common for non-interactive, automated processes, such as continuous telemetry streaming from machines.
Combined Addressing
A single message can use both modes simultaneously: publish to all subscribers and directly address additional specific recipients. This is useful when you want broad distribution plus guaranteed delivery to specific endpoints.
Message Flow
Knowing the full flow helps you design your integration correctly.
Sender sends message
The application constructs a message with the payload, technical message type, and addressing information. It sends the message to agrirouter via the API.
The message is received
The message arrives at agrirouter for processing.
Routing engine processes the message
The addressing mode, routes, recipient capabilities, and subscriptions are evaluated to determine which endpoints should receive the message.
Message placed in recipient feeds
For each valid recipient, agrirouter places a copy of the message in that endpoint's feed.
Recipient receives the message
The recipient application receives messages via a Server-Sent Events (SSE) stream. agrirouter opens a long-lived HTTP connection and pushes an event to the client as each message arrives in the feed.
Recipient confirms the message
After processing a message, the recipient must confirm (acknowledge) it. This removes the message from the feed.
Feed Management
The feed stores messages that have been delivered to the recipient but not yet confirmed. After processing a message, the recipient must confirm (acknowledge) it to remove it from the feed.
Server-Sent Events (SSE)
Applications receive messages by opening a long-lived GET /events connection. agrirouter pushes events to the client as they arrive; the gateway exposes no poll-based message retrieval alternative. The connection accepts a types query parameter to restrict the stream to specific event types.
Chunking
agrirouter splits large message payloads into chunks of about 768 KB for internal transport and reassembles them before delivery. This is transparent to the API: you send one logical message and the recipient receives one logical message, up to the per-request body limit of 256 MB.
The chunking boundary is still visible outside the API: the endpoint detail view in the agrirouter UI lists each message the endpoint received, including chunk metadata, so a single chunked payload may show up as several entries there.
Technical Message Types
Every message in agrirouter has a technical message type (TMT) that identifies the format of the payload. TMTs are standardized across the platform so that all applications can interoperate.
TMT identifiers use a colon-delimited structure: standard:part:category:encoding. For example, iso:11783:-10:taskdata:zip means: ISO 11783 standard, part -10, task data category, ZIP-compressed encoding. The complete list of supported identifiers is in the Message Types reference.
Common categories include:
| Category | Examples |
|---|---|
| Task data | ISO 11783 TaskData (task files for machines) |
| Telemetry | EFDI Device Descriptions (TeamSets), EFDI TimeLog (live telemetry) |
| Positioning | GPS position data |
| Geospatial | Shape files (field boundaries, application maps, as-applied/as-harvested maps) |
| Documents | PDF files, images (PNG, JPEG), video |
See the Message Types reference for the complete list of supported technical message types and their identifiers.
1 minCommon Failure Modes
Knowing what can go wrong helps you design a resilient integration from the start.
No route to recipient
Capabilities are checked both when a route is created and again at send time. At route creation, agrirouter refuses to build a route for an information type if the sender's sending capabilities and the receiver's receiving capabilities do not intersect on it. If a recipient later trims its capabilities, existing routes are not removed automatically, but the send-time check filters them out, so a stale route behaves the same as no route at all. From the sender's perspective, you are only ever in one of two situations at send time: the message is routed, or it is not. You will never see a distinct "capability mismatch" failure.
The behavior when no route exists depends on the addressing mode:
Publish with no matching subscribers
When you send a message in publish mode (x-agrirouter-is-publish: true with no direct recipients) and no subscribed endpoint is reachable by a route for that information type, agrirouter returns HTTP 200 and the message is dropped. This is intentional: publishing with nobody listening is a no-op, not an error. This is the most common cause of "missing messages": check that the end user has configured a route before assuming there is a bug in your code.
Direct send with unroutable recipients
When you send a message with direct recipients (x-agrirouter-direct-recipients: <endpointId>) and no route exists from your endpoint to one or more of the named recipients for that information type, agrirouter rejects the request with HTTP 400 and a human-readable message field in the JSON error body. Treat this as "the end user has not configured a route to one of the recipients you named". See the Errors reference for the full HTTP status code list.
Communication Protocol
agrirouter uses:
- REST over HTTPS for sending messages and managing endpoints (HTTP POST / PUT / DELETE on
/messages,/confirmations,/endpoints/{externalId}) - Server-Sent Events over HTTPS for receiving messages (
GET /events)
Note for developers who previously evaluated agrirouter
MQTT is no longer used. All communication with agrirouter now happens over HTTPS: REST for sending, SSE for receiving. If you previously bounced off the integration because of MQTT, it is worth another look.
See the API Reference for endpoint specifications, request/response formats, and authentication details.
1 minAPI Reference
Open the operations that carry a message from sender to recipient in the API playground:
Send one or several messages1 min Receive events1 min Confirm received messages1 min