REST API Documentation
Overview
This document outlines the REST API endpoints used for entity communication. These APIs complement the WebSocket protocol and provide HTTP-based access to core messaging functionality.
For a comprehensive understanding of entities, roles, and the RBAC communication model, see Entities Documentation.
Authentication
All API endpoints require authentication using a Bearer token in the Authorization header:
Authorization: Bearer your-api-key
Required Permissions
- entity:CheckMessages - Required for checking messages
- entity:WriteMessages - Required for publishing messages
Base URL
https://app.tendrl.com/api
Endpoints
GET /entities/check_messages
Retrieves pending messages for the authenticated entity.
Authorization Required: entity:CheckMessages
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer |
No | Maximum number of messages to retrieve (default: 1) |
Request Example
GET /api/entities/check_messages?limit=5
Authorization: Bearer your-api-key
Response
Success (200 OK):
When messages are available:
[
{
"msg_type": "publish",
"source": "/entities/device-123",
"dest": "entity-456",
"timestamp": "2025-01-09T10:30:00Z",
"data": {
"action": "status_update",
"value": "online"
},
"context": {
"tags": ["status", "health"]
}
}
]
When no messages are available:
[]
Error Responses:
{
"error": "Unauthorized",
"message": "Invalid API key or missing entity:CheckMessages permission"
}
{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please try again later."
}
POST /entities/messages
Publishes a message from the authenticated entity. This endpoint supports all message types including regular messages, heartbeats, and other custom message types.
Authorization Required: entity:WriteMessages
Request Body
{
"msg_type": "publish",
"data": {
// Your message payload (any JSON type)
},
"dest": "1234567891:us-1:entity:test-esp32-1", //send to another entity
"context": {
"tags": ["tag1", "tag2"],
"wait": false
}
}
| Field | Type | Required | Description |
|---|---|---|---|
msg_type |
string |
Yes | Message type (typically "publish") |
data |
any |
Yes | Message payload (can be any JSON type) |
dest |
string |
No | Destination entity identifier |
context |
object |
No | Additional message context |
timestamp |
string |
No | ISO 8601 timestamp (auto-generated if not provided) |
Context Object
| Field | Type | Description | Constraints |
|---|---|---|---|
tags |
string[] |
Tags for message categorization | Max 10 tags |
wait |
boolean |
Whether to wait for server response | Default: false |
Request Examples
Basic Message:
POST /api/entities/messages
Authorization: Bearer your-api-key
Content-Type: application/json
{
"msg_type": "publish",
"data": {
"sensor": "temperature",
"value": 23.5,
"unit": "celsius"
},
"context": {
"tags": ["sensors", "environment"]
}
}
Message with Synchronous Response:
POST /api/entities/messages
Authorization: Bearer your-api-key
Content-Type: application/json
{
"msg_type": "publish",
"data": {
"command": "get_status",
"target": "device-123"
},
"context": {
"wait": true,
"tags": ["commands"]
}
}
Message to Specific Destination:
POST /api/entities/messages
Authorization: Bearer your-api-key
Content-Type: application/json
{
"msg_type": "publish",
"dest": "device-456",
"data": {
"action": "reboot",
"scheduled_time": "2025-01-09T15:00:00Z"
},
"context": {
"tags": ["maintenance", "commands"]
}
}
Heartbeat Message:
POST /api/entities/messages
Authorization: Bearer your-api-key
Content-Type: application/json
{
"msg_type": "heartbeat",
"data": {
"mem_free": 2097152,
"mem_alloc": 524288,
"disk_free": 1073741824,
"disk_size": 2147483648
},
"timestamp": "2024-03-15T14:30:45Z"
}
For detailed heartbeat message format and implementation examples, see: Heartbeat Message Format
Response
Asynchronous Message (wait: false):
{
"status": "accepted"
}
Synchronous Message (wait: true):
{
"message_id": "msg-789",
"timestamp": "2025-01-09T10:30:00Z",
"result": {
"id": "msg-789",
"actionResult": {
"name": "validation-rule",
"valid": true,
"message": "Message processed successfully"
}
}
}
Error Responses:
{
"error": "Validation Failed",
"message": "Message size exceeds the limit for your plan. Basic plans are limited to 2KB messages."
}
{
"error": "Rate Limit Exceeded",
"message": "Monthly data limit exceeded"
}
{
"error": "Bad Request",
"message": "Invalid message format: msg_type is required"
}
Error Codes
| Status Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - Invalid message format or missing required fields |
| 401 | Unauthorized - Invalid API key or insufficient permissions |
| 403 | Forbidden - Access denied |
| 413 | Payload Too Large - Message exceeds size limits |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Server processing error |
Rate Limits
- Message Publishing: 100 requests per minute per API key
- Message Checking: 200 requests per minute per API key
- Data Limits: Vary by plan (Basic: 2KB per message, Pro: 64KB per message)
SDKs Usage
These endpoints are used internally by all Tendrl SDKs:
- JavaScript SDK:
TendrlClient.publish()andTendrlClient.checkMessages() - Python SDK:
Client.publish()andClient.check_messages() - Go SDK:
Client.Publish()andClient.CheckMessages() - MicroPython SDK:
Client.publish()andClient.check_messages()
For most use cases, we recommend using the SDKs rather than calling these REST endpoints directly, as the SDKs provide additional features like:
- Automatic batching and queuing
- Connection management and retry logic
- WebSocket fallback for real-time communication
- Built-in error handling and validation
Migration from WebSocket
If you're currently using WebSocket connections, these REST endpoints provide the same functionality with HTTP semantics:
| WebSocket Message | REST Endpoint |
|---|---|
{"msgType": "publish", ...} |
POST /entities/messages |
{"msgType": "msg_check", ...} |
GET /entities/check_messages |
{"msgType": "heartbeat", ...} |
POST /entities/messages |
The main differences:
- REST is stateless (no persistent connection)
- REST has higher latency but better reliability
- REST is easier to integrate with HTTP-based workflows
- WebSocket provides real-time bidirectional communication