Skip to main content

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​

MethodEndpointDescriptionAuth Required
GET/auth/meGet current user contextYes
GET/auth/cli?code={handshakeId}CLI device handshake initYes
GET/auth/handshake/:codeCLI handshake pollNo
GET/auth/csrfGet CSRF tokenNo
POST/auth/logoutLogout and clear sessionNo
GET/auth/api-keysList API keysYes
POST/auth/api-keysCreate API keyYes
POST/auth/api-keys/revokeRevoke API keyYes
POST/auth/api-keys/rotateRotate API keyYes

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​

MethodEndpointDescriptionAuth Required
GET/healthFull health checkNo
GET/health/liveLiveness probeNo
GET/health/readyReadiness probeNo

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​

MethodEndpointDescriptionAuth RequiredRole
POST/device/registerRegister new deviceYesadmin
GET/devicesList all devicesYesuser
GET/devices/:idGet device detailsYesuser
POST/device/:id/rotate-secretRotate device secretYesadmin
GET/device/:id/key-historyGet key rotation historyYesadmin
POST/device/:id/revokeRevoke deviceYesadmin

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​

MethodEndpointDescriptionAuth RequiredRole
POST/device/:deviceId/commandExecute commandYesuser
POST/device/:deviceId/command/confirmConfirm dry-runYesuser
POST/devices/commandBatch commandYesuser
POST/rooms/:roomId/commandRoom commandYesuser
POST/groups/:groupSlug/commandGroup commandYesuser
GET/device/:deviceId/commandsCommand historyYesuser

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​

MethodEndpointDescriptionAuth RequiredRole
POST/homesCreate homeYesadmin
GET/homesList homesYes-
PATCH/homes/:homeIdUpdate homeYesadmin
DELETE/homes/:homeIdDelete homeYesadmin
POST/homes/:homeId/roomsAdd roomYesadmin
GET/homes/:homeId/roomsList roomsYes-
DELETE/homes/:homeId/rooms/:roomIdDelete roomYesadmin

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​

MethodEndpointDescriptionAuth Required
GET/manifest/capabilitiesGlobal capability registryYes
GET/manifest/typesDevice type to capability mappingYes
GET/devices/:deviceId/manifestGet device manifestYes
POST/devices/:deviceId/manifestRegister initial manifestYes
PUT/devices/:deviceId/manifestUpdate manifestYes

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​

MethodEndpointDescriptionAuth Required
POST/api/v1/intentRoute intent to HX47Yes

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​

MethodEndpointDescriptionAuth RequiredRole
POST/firmware/checkCheck firmware versionYesuser
POST/firmware/releaseCreate releaseYesadmin
GET/firmware/:idGet firmware detailsYes-
POST/firmware/:id/releaseRelease firmwareYesadmin

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​

MethodEndpointDescriptionAuth RequiredRole
GET/groupsList groupsYesuser
POST/groupsCreate groupYesadmin
POST/groups/:slug/joinJoin groupYesuser

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​

MethodEndpointDescriptionAuth RequiredRole
POST/tenant/registerRegister new tenantYes-

Request/Response​

# Register tenant
POST /tenant/register
{
"tenant_name": "My Smart Home"
}

Response (201):
{
"tenant_id": "uuid",
"user_id": "uuid"
}

System Endpoints​

MethodEndpointDescriptionAuth Required
GET/statusSystem statusNo
GET/versionProtocol versionNo
GET/changelogChangelogNo
GET/metricsPrometheus metricsNo

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​

EndpointDescriptionAuth Required
WS /ws/stateReal-time state streamingYes

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​

CodeDescription
200Success
201Created
400Bad Request
401Unauthorized
403Forbidden (missing tenant context)
404Not Found
409Conflict
429Too Many Requests
500Internal Error
503Service Unavailable

Gateway Rejection Codes​

CodeDescription
MANIFEST_NOT_FOUNDNo capability manifest for device
ACTION_NOT_IN_MANIFESTAction not in capability allowlist
PARAMS_INVALIDInvalid parameters for action
RESTRICTED_ACTIONProtocol-internal action
RATE_LIMIT_EXCEEDEDToo many requests
DRY_RUN_REQUIREDCritical action requires confirmation
GATEWAY_ERRORInternal gateway error

Rate Limits​

TierRequests/min
Free60
Pro300

Rate limits are enforced per tenant. Exceeded requests return 429 Too Many Requests.


Cognitive Endpoints (HX47)​

MethodEndpointDescriptionAuth Required
POST/api/v1/intentHigh-level cognitive intentYes
POST/api/v1/devices/:id/commandSidecar-orchestrated cmdYes (Admin)
POST/api/v1/cognition/observationSubmit environment dataYes

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​

HeaderValue
X-API-Version1
X-Protocol-VersionHxTP/3.0
X-Request-IDUUID