All API Endpoints
Complete reference of all REST and WebSocket endpoints in HxTP Cloud.
Base URLâ
https://api.hestialabs.in/api/v1
WebSocketâ
wss://api.hestialabs.in/ws/state?token=<jwt>
Authentication Endpointsâ
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /auth/me | Get current user context | Yes |
| GET | /auth/cli?code={handshakeId} | CLI device handshake init | Yes |
| GET | /auth/handshake/:code | CLI handshake poll | No |
| GET | /auth/csrf | Get CSRF token | No |
| POST | /auth/logout | Logout and clear session | No |
| GET | /auth/api-keys | List API keys | Yes |
| POST | /auth/api-keys | Create API key | Yes |
| POST | /auth/api-keys/revoke | Revoke API key | Yes |
| POST | /auth/api-keys/rotate | Rotate API key | Yes |
Request/Responseâ
# Get user context
GET /auth/me
Authorization: Bearer <token>
Response:
{
"authenticated": true,
"has_tenant": true,
"user": {
"id": "uuid",
"neon_id": "string",
"email": "user@example.com",
"role": "owner|admin|user|viewer|none",
"tenant_id": "uuid",
"tenant_slug": "string"
}
}
# Create API key
POST /auth/api-keys
{
"name": "my-key",
"scopes": ["read:devices", "write:devices"]
}
Response:
{
"status": "created",
"key": "hxtp_abc123...",
"prefix": "abc123...xyz",
"name": "my-key"
}
Health Endpointsâ
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /health | Full health check | No |
| GET | /health/live | Liveness probe | No |
| GET | /health/ready | Readiness probe | No |
Request/Responseâ
GET /health
Response (200):
{
"status": "ok",
"timestamp": "2026-01-01T00:00:00Z",
"services": {
"api": { "status": "operational" },
"database": { "status": "operational" },
"redis": { "status": "operational" },
"mqtt": { "status": "operational" },
"worker": { "status": "operational" },
"build_service": { "status": "operational" },
"cloud_editor": { "status": "operational" }
},
"metrics": { "active_devices": 0 }
}
Response (503):
{
"status": "degraded",
"checks": { "database": false, "redis": true, ... }
}
Device Endpointsâ
| Method | Endpoint | Description | Auth Required | Role |
|---|---|---|---|---|
| POST | /device/register | Register new device | Yes | admin |
| GET | /devices | List all devices | Yes | user |
| GET | /devices/:id | Get device details | Yes | user |
| POST | /device/:id/rotate-secret | Rotate device secret | Yes | admin |
| GET | /device/:id/key-history | Get key rotation history | Yes | admin |
| POST | /device/:id/revoke | Revoke device | Yes | admin |
Request/Responseâ
# Register device
POST /device/register
{
"device_type": "esp32",
"home_id": "uuid",
"room_id": "uuid"
}
Response (201):
{
"status": "registered",
"device_id": "uuid",
"tenant_id": "uuid",
"api_base_url": "https://api.hestialabs.in/api/v1",
"device_secret": "abc123...",
"initial_sequence": 0,
"home_id": "uuid",
"room_id": "uuid"
}
# List devices
GET /devices
Response:
{
"devices": [
{
"id": "uuid",
"device_type": "esp32",
"home_id": "uuid",
"room_id": "uuid",
"firmware": "0.0.0",
"last_seen": "timestamp",
"revoked": false
}
],
"count": 1
}
# Rotate secret
POST /device/:id/rotate-secret
Response:
{
"device_id": "uuid",
"new_secret": "abc123...",
"key_version": 2
}
Command Endpointsâ
| Method | Endpoint | Description | Auth Required | Role |
|---|---|---|---|---|
| POST | /device/:deviceId/command | Execute command | Yes | user |
| POST | /device/:deviceId/command/confirm | Confirm dry-run | Yes | user |
| POST | /devices/command | Batch command | Yes | user |
| POST | /rooms/:roomId/command | Room command | Yes | user |
| POST | /groups/:groupSlug/command | Group command | Yes | user |
| GET | /device/:deviceId/commands | Command history | Yes | user |
Request/Responseâ
# Execute command
POST /device/:deviceId/command
{
"action": "light_on",
"params": {
"brightness": 100
},
"dry_run": false
}
Response (202):
{
"success": true,
"command_id": "abc123",
"message_id": "uuid"
}
# Dry run required (409):
{
"status": "dry_run_required",
"reason": "Critical action requires confirmation",
"dry_run_token": "uuid"
}
# Confirm dry-run token
POST /device/:deviceId/command/confirm
{
"dry_run_token": "uuid"
}
Response (202):
{
"success": true,
"command_id": "abc123",
"message_id": "uuid"
}
# Batch command
POST /devices/command
{
"device_ids": ["uuid1", "uuid2"],
"action": "light_on",
"params": { "brightness": 100 }
}
Response:
{
"results": [
{ "device_id": "uuid1", "success": true, "message_id": "uuid" },
{ "device_id": "uuid2", "success": false, "error": "Device is revoked" }
]
}
# Room command
POST /rooms/:roomId/command
{
"action": "light_on",
"capability": "light"
}
Response:
{
"results": [...]
}
# Group command
POST /groups/:groupSlug/command
{
"action": "light_on"
}
Response:
{
"results": [...]
}
# Command history
GET /device/:deviceId/commands
Response:
{
"commands": [
{
"id": "uuid",
"action": "light_on",
"params": { "brightness": 100 },
"timestamp": "2026-01-01T00:00:00Z",
"status": "dispatched"
}
]
}
Home & Room Endpointsâ
| Method | Endpoint | Description | Auth Required | Role |
|---|---|---|---|---|
| POST | /homes | Create home | Yes | admin |
| GET | /homes | List homes | Yes | - |
| PATCH | /homes/:homeId | Update home | Yes | admin |
| DELETE | /homes/:homeId | Delete home | Yes | admin |
| POST | /homes/:homeId/rooms | Add room | Yes | admin |
| GET | /homes/:homeId/rooms | List rooms | Yes | - |
| DELETE | /homes/:homeId/rooms/:roomId | Delete room | Yes | admin |
Request/Responseâ
# Create home
POST /homes
{
"home_name": "My Home",
"timezone": "America/New_York"
}
Response (201):
{
"status": "created",
"id": "uuid"
}
# Add room
POST /homes/:homeId/rooms
{
"name": "Living Room"
}
Response (201):
{
"status": "created",
"id": "uuid"
}
Manifest Endpointsâ
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /manifest/capabilities | Global capability registry | Yes |
| GET | /manifest/types | Device type to capability mapping | Yes |
| GET | /devices/:deviceId/manifest | Get device manifest | Yes |
| POST | /devices/:deviceId/manifest | Register initial manifest | Yes |
| PUT | /devices/:deviceId/manifest | Update manifest | Yes |
Request/Responseâ
# Global capabilities
GET /manifest/capabilities
Response:
{
"capabilities": [
{ "id": 1, "action": "light_on", "description": "Turn light on", ... },
...
]
}
# Device type mapping
GET /manifest/types
Response:
{
"categories": {
"light": ["light_on", "light_off", "light_brightness"],
"climate": ["temp_set", "mode_auto"],
...
}
}
# Get device manifest
GET /devices/:deviceId/manifest
Response:
{
"deviceId": "uuid",
"tenantId": "uuid",
"version": 1,
"capabilities": [
{
"id": 1,
"action": "light_on",
"safetyClass": "normal",
"paramSchema": { "properties": {...} },
"supportsDryRun": false
}
]
}
Intent Endpointsâ
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/v1/intent | Route intent to HX47 | Yes |
Request/Responseâ
# Route intent
POST /api/v1/intent
{
"type": "device.control",
"payload": {
"device_id": "uuid",
"action": "light_on",
"params": { "brightness": 100 }
}
}
Response:
{
"status": "SUCCESS",
"mode": "CLOUD_ENHANCED",
"commands_executed": 1,
"commands_rejected": 0,
"results": [
{
"device_id": "uuid",
"action": "light_on",
"status": "dispatched",
"command_id": "abc123"
}
]
}
Firmware Endpointsâ
| Method | Endpoint | Description | Auth Required | Role |
|---|---|---|---|---|
| POST | /firmware/check | Check firmware version | Yes | user |
| POST | /firmware/release | Create release | Yes | admin |
| GET | /firmware/:id | Get firmware details | Yes | - |
| POST | /firmware/:id/release | Release firmware | Yes | admin |
Request/Responseâ
# Check firmware
POST /firmware/check
{
"device_type": "esp32",
"current_version": "0.0.1"
}
Response:
{
"update_available": true,
"target_version": "0.0.2",
"url": "https://...",
"checksum": "sha256..."
}
Group Endpointsâ
| Method | Endpoint | Description | Auth Required | Role |
|---|---|---|---|---|
| GET | /groups | List groups | Yes | user |
| POST | /groups | Create group | Yes | admin |
| POST | /groups/:slug/join | Join group | Yes | user |
Request/Responseâ
# Create group
POST /groups
{
"name": "Living Room Lights",
"description": "All lights in living room",
"device_ids": ["uuid1", "uuid2"]
}
Response (201):
{
"status": "created",
"slug": "living-room-lights"
}
Tenant Endpointsâ
| Method | Endpoint | Description | Auth Required | Role |
|---|---|---|---|---|
| POST | /tenant/register | Register new tenant | Yes | - |
Request/Responseâ
# Register tenant
POST /tenant/register
{
"tenant_name": "My Smart Home"
}
Response (201):
{
"tenant_id": "uuid",
"user_id": "uuid"
}
System Endpointsâ
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /status | System status | No |
| GET | /version | Protocol version | No |
| GET | /changelog | Changelog | No |
| GET | /metrics | Prometheus metrics | No |
Request/Responseâ
GET /status
Response:
{
"system": "HXTP Cloud",
"status": "operational",
"beta": true,
"version": "1.0.0",
"protocol": "HxTP/3.0"
}
GET /version
Response:
{
"version": "1.0.0",
"protocol": "HxTP/3.0"
}
WebSocket Endpointsâ
| Endpoint | Description | Auth Required |
|---|---|---|
WS /ws/state | Real-time state streaming | Yes |
Request/Responseâ
// Connect
const ws = new WebSocket('wss://api.hestialabs.in/ws/state?token=<jwt>');
// Incoming messages
{
"type": "state_update",
"device_id": "uuid",
"state": { "light": "on", "brightness": 100 },
"timestamp": 1704067200000
}
// Send ping
ws.send('ping');
// Response
ws.on('message', (data) => {
if (data === 'pong') {
console.log('Keepalive response');
}
});
Error Codesâ
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden (missing tenant context) |
| 404 | Not Found |
| 409 | Conflict |
| 429 | Too Many Requests |
| 500 | Internal Error |
| 503 | Service Unavailable |
Gateway Rejection Codesâ
| Code | Description |
|---|---|
MANIFEST_NOT_FOUND | No capability manifest for device |
ACTION_NOT_IN_MANIFEST | Action not in capability allowlist |
PARAMS_INVALID | Invalid parameters for action |
RESTRICTED_ACTION | Protocol-internal action |
RATE_LIMIT_EXCEEDED | Too many requests |
DRY_RUN_REQUIRED | Critical action requires confirmation |
GATEWAY_ERROR | Internal gateway error |
Rate Limitsâ
| Tier | Requests/min |
|---|---|
| Free | 60 |
| Pro | 300 |
Rate limits are enforced per tenant. Exceeded requests return 429 Too Many Requests.
Cognitive Endpoints (HX47)â
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/v1/intent | High-level cognitive intent | Yes |
| POST | /api/v1/devices/:id/command | Sidecar-orchestrated cmd | Yes (Admin) |
| POST | /api/v1/cognition/observation | Submit environment data | Yes |
Request/Responseâ
# Submit Cognitive Observation
POST /api/v1/cognition/observation
{
"device_id": "uuid",
"data": { "temperature": 22.5, "occupancy": true },
"context": "room_entry"
}
Response (202):
{ "status": "OBSERVATION_RECEIVED", "proposal_id": "uuid" }
Protocol Versionsâ
| Header | Value |
|---|---|
X-API-Version | 1 |
X-Protocol-Version | HxTP/3.0 |
X-Request-ID | UUID |