Build on your Teqlogy devices
Read live data, switch relays, set meter quotas, schedule resets and listen to every change — from your own scripts, dashboards and systems. A plain REST API with JSON, a WebSocket for live events, and personal API keys with clear access levels.
https://teqhome.teqlogy.comChoose your device
Each device has its own page with every endpoint, field, command and event that applies to it.
PowerMatrix-8
8-channel smart relay controller
- Switch each of the 8 relays over REST or live over a WebSocket
- Auto-off timers and weekly or one-shot automations
- Relay names, icons and scenes
- Learn and store IR remote codes
- Relay history and statistics
EnergyMate
Smart auto changeover for 3 to 5 meters (3 · 3A · 4 · 3X · 4X · 5X)
- Live voltage, current, power, power factor and energy for every meter
- Meter quotas: set limits, switch and reset meters
- Hourly and daily energy history
- Scheduled resets with reports; OFF / ON schedules on the X models
- Amp (overcurrent) protection and meter readings on the X models
Quick start
export KEY=tk_live_…
curl "https://teqhome.teqlogy.com/api/devices/me" \
-H "Authorization: Bearer $KEY"{
"ok": true,
"devices": [
{
"deviceId": "aabbcc112233",
"name": "Living Room",
"type": "PowerMatrix-8",
"status": true,
"relays": [1, 0, 1, 0, 0, 0, 0, 0]
},
"…"
]
}Authentication
Every request carries your personal API key in the Authorization header. There is nothing else to sign.
Authorization: Bearer tk_live_<your key>
Content-Type: application/json| Format | tk_live_ followed by 64 hex characters (72 characters in all) |
| Header | Authorization: Bearer tk_live_… |
| Storage | only a SHA-256 hash is kept on our side; the key itself is shown once, when you create it |
| Limit | up to 10 keys per account — use one key per integration so you can revoke one without touching the others |
| Types | read-only or full (read-write), chosen when the key is created and never changed afterwards |
| Lifetime | valid for as long as the API access of your account is valid; revoking a key stops it immediately |
Get an API key
What a key can do
Keys come in two types, and some things are never available to a key at all. The rules are enforced by the server on every request, on the REST API and on the WebSocket alike — a read-only key cannot change anything, however it asks.
For dashboards, reports and monitoring. 14 endpoints.
- Read your devices, their state and settings
- Read energy history, relay history and statistics
- Read meter readings, schedules and reports
- Read notifications and the Away Mode state
- Listen to every live event on the WebSocket
Cannot change anything: every write answers 403 API_KEY_READONLY, and its WebSocket sends nothing.
For the integration that has to act. All 33 endpoints.
- Everything a read-only key can do
- Switch relays, set timers, manage IR codes
- Change device names and settings
- Create and cancel meter schedules and resets
- Record meter readings, manage notifications
- Turn Away Mode on and off
- Send the device commands on the WebSocket
Still limited to your own devices and to what a share allows: a view-only share stays view-only.
Never available to any key. Sign in to the app or the dashboard.
- Your account — profile, rooms, account deletion
- API keys — creating, listing and revoking keys (a key can never create another key)
- Owning a device — registering, claiming, transferring and deleting a device, factory reset
- Sharing — sharing a device with other people and withdrawing it
- Activity log and push tokens — the audit trail of your account and your phone notification tokens
- Firmware updates (OTA) — checking, triggering and uploading firmware
- Store, Google Home, admin — orders, voice-assistant linking and everything in the admin panel
These answer 403 API_KEY_NOT_ALLOWED.
Every endpoint at a glance
Conventions
- Requests and answers are JSON. Send
Content-Type: application/jsonwith a body. - Every answer has
ok:trueorfalse. - Dates are ISO 8601 in UTC, for example
2026-10-03T14:20:00.000Z. - Energy in kWh unless the name says Wh; voltage in V, current in A, power in W, frequency in Hz.
Numbering: where counting starts
| Where | Rule |
|---|---|
| Relays (PowerMatrix-8) | 0-based: relay 1 on the device = index 0 … relay 8 = index 7 |
| meters[].index in a device | 1-based, exactly as the device reports it: Meter 1 = 1 |
| meterIndex in REST requests and answers (schedules, resets, reports, readings) | 0-based: Meter 1 = 0 |
| meter in WebSocket commands (switchMeter, resetMeter, ampRestart) | 1-based: Meter 1 = 1 |
Rate limits
| Scope | Limit | Window | When exceeded |
|---|---|---|---|
| HTTP, all endpoints | 200 requests | 15 minutes per IP address (default; the operator may change it) | 429 RATE_LIMITED with a Retry-After header; RateLimit-Remaining / RateLimit-Reset tell you where you are |
| Meter OFF / ON schedules (create, delete) | 30 requests | 10 minutes per account | 429 RATE_LIMITED |
| Meter readings (POST calibrations) | 30 requests | 10 minutes per account | 429 RATE_LIMITED |
| WebSocket messages you send | 30 messages | 10 seconds per connection | extra messages are ignored |
| Request body | 1 MB | per request | — |
Errors
Errors use the HTTP status first, and most carry a stable code you can switch on. The message is for humans and may change.
{
"ok": false,
"code": "API_KEY_READONLY",
"message": "This API key is read-only: it can read data but cannot change anything.",
"requestId": "req_a1b2c3d4e5f6g7h8"
}{ ok: false, message } without a code (the endpoint pages mark them “message only”). For those, rely on the HTTP status. The X-Request-Id response header carries the same id as requestId: quote it when you contact support.| code | HTTP | When |
|---|---|---|
| AUTH_MISSING | 401 | No Authorization header |
| AUTH_INVALID | 401 | The key is not recognised (typo, revoked, or not a Teqlogy key) |
| API_ACCESS_DISABLED | 403 | API access is not enabled for this account |
| API_ACCESS_EXPIRED | 403 | The API access period of this account has ended |
| AUTH_BANNED | 403 | The account is suspended |
| AUTH_DELETED | 410 | The account has been deleted |
| API_KEY_READONLY | 403 | A read-only key tried to change something (REST or WebSocket) |
| API_KEY_NOT_ALLOWED | 403 | The endpoint (or WebSocket command) is login-only: no key can use it |
| DEVICE_NOT_FOUND | 404 | The device does not exist or is not yours — both look the same on purpose |
| DEVICE_ACCESS_DENIED | 403 | The device is shared with you as view-only |
| DEVICE_OFFLINE | 503 | The device is not connected, so the command could not be delivered |
| AWAY_MODE_ACTIVE | 403 | Away Mode is on for the device: turning something ON is blocked, turning OFF always works |
| VALIDATION_ERROR | 400 | A field is missing or invalid; message says which |
| RELAY_INDEX_INVALID | 400 | relay is not a non-negative integer |
| METER_OFF_UNSUPPORTED | 409 | The meter has never reported the OFF flag (firmware without scheduled OFF) |
| METER_OFF_OVERLAP | 409 | Another schedule of that meter already covers the time |
| CALIBRATION_UNSUPPORTED | 409 | The firmware has no lifetime register yet |
| CALIBRATION_EPOCH_MISMATCH | 409 | The device counters were reset since the snapshot you used |
| CALIBRATION_STALE | 409 | The snapshot is more than 1 kWh older than the latest report of the device |
| RATE_LIMITED | 429 | Too many requests — wait for Retry-After |
| NOT_FOUND | 404 | The endpoint or the id does not exist |
| SERVER_ERROR | 500 | Unexpected error on our side — safe to retry |
Real time (WebSocket)
A WebSocket pushes every change as it happens, so you do not have to poll. Open it with a one-time ticket from POST /api/ws-ticket. Each device page lists the commands and events of that device.
// 1. exchange the key for a one-time ticket (valid 30 s, works once)
const { ticket } = await fetch('https://teqhome.teqlogy.com/api/ws-ticket', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.TEQLOGY_KEY },
}).then((r) => r.json())
// 2. open the socket with it
const ws = new WebSocket('wss://teqhome.teqlogy.com/ws/app?ticket=' + ticket)
ws.onmessage = ({ data }) => console.log(JSON.parse(data))
ws.onclose = () => { /* get a NEW ticket, then connect again */ }
// 3. keep it alive and (full key only) send commands
setInterval(() => ws.send(JSON.stringify({ type: 'ping' })), 25000)
ws.send(JSON.stringify({ type: 'toggleRelay', deviceId: 'aabbcc112233', relay: 0, state: true }))- You receive the events of every device you own and of every device shared with you, as soon as they happen.
- A socket opened with a read-only key only listens. Every command it sends is answered with an error frame (API_KEY_READONLY) and nothing reaches a device.
- A socket opened with a full key may send the commands below. Anything else — factoryReset, deleteDevice, an unknown type — is refused with API_KEY_NOT_ALLOWED: those need a login.
- At most 30 messages per 10 seconds per connection; extra messages are ignored. The server does not ping app connections and proxies close idle ones, so send { "type": "ping" } every 25–30 seconds.
- A command is addressed with deviceId and goes to the device only if it is yours or shared with you with control access. There is no answer to a command that worked: watch for telemetryUpdate.
A refused command
The socket stays open and tells you why:
{
"type": "error",
"code": "API_KEY_READONLY",
"message": "This API key is read-only: it can read data but cannot change anything.",
"command": "toggleRelay"
}Address: wss://teqhome.teqlogy.com/ws/app?ticket=…
Using keys safely
- Use a read-only key for dashboards, reports and monitoring. Give a full key only to the integration that really has to switch things.
- Keep keys on a server. A key in a web page or a phone app can be read by anybody who opens it. (Browsers on other websites are also stopped by CORS.)
- One key per integration, named after it. Revoke a key the moment it is lost, leaked or no longer used — it stops working at once.
- Always use HTTPS / WSS. Never put a key in a URL or in a log; send it in the Authorization header only.
- Your key acts as you: it only sees and changes your own devices and the devices shared with you, and never more than your share allows.