Skip to content

API Access

Beta

The Connexa API is currently in Beta. It is available to all users, but endpoints, response fields and limits may change as we gather feedback, so it should not be relied upon for mission critical business logic.

The Connexa API lets you read your own devices, their historical telemetry and their alerts from your own scripts and applications. It is read-only and only ever returns data for devices on your account.

Base URL: https://cloud.connexa.com/public-api/v1

Get an API key

  1. Open your profile and scroll to the bottom of the page. The API Keys panel is below the billing section, under the View Billing Portal button.
  2. Click the + Generate Key button at the bottom of that panel, give the key a label that says what it is for (for example "Grafana dashboard"), and choose how long it should last.
  3. Copy the key immediately. It is shown only once and cannot be retrieved later. If you lose it, revoke it and generate a new one.

Keys look like cxa_live_ followed by random characters. Treat one like a password: keep it out of source control, screenshots and client-side code.

Keys always expire

Every key has an expiry date. The default is 90 days, and you can choose 30 days, 90 days, 180 days or 1 year when you generate it. There is no option for a key that never expires.

  • The expiry date is shown in the Expires column of your key list.
  • After that date the API answers 403 with a message that the key has expired. Generate a replacement before then, and update your integration to use it.
  • You can have up to 10 active keys, so a new key can run alongside the old one while you switch over.
  • To stop a key working early, click Revoke. This takes effect immediately.

Make your first request

Send the key in an Authorization header.

curl -H "Authorization: Bearer cxa_live_YOUR_KEY" \
  https://cloud.connexa.com/public-api/v1/devices

The response lists your devices, and each one includes a deviceId. Use it to read that device's data. The device endpoints also need a deviceid header containing the same ID.

curl -H "Authorization: Bearer cxa_live_YOUR_KEY" \
     -H "deviceid: YOUR_DEVICE_ID" \
  "https://cloud.connexa.com/public-api/v1/devices/YOUR_DEVICE_ID/data?window=7d&limit=100"

Endpoints

Request Returns
GET /devices Your devices (id, name, status).
GET /devices/:deviceId Full detail for one device.
GET /devices/:deviceId/data Historical telemetry, newest first. Add object= to filter to one metric type.
GET /devices/:deviceId/data/:object The same telemetry, already filtered to one metric type.
GET /devices/:deviceId/alerts Historical alerts, newest first.

Choosing a time range

Data and alert requests take one of:

  • window=7d or window=30d, relative to now. The default is 7d.
  • startDate and endDate together, in ISO 8601 format such as 2025-01-23T00:00:00.000Z. The range can be at most 366 days. If you send both, the explicit range wins.

Pages of results

Results come in pages. Use limit to set the page size (data: default 100, maximum 500; alerts: default 50, maximum 200). Each response includes nextCursor. If it is a string, pass it back as cursor= to fetch the next page, keeping every other parameter the same. When nextCursor is null you have everything.

curl -H "Authorization: Bearer cxa_live_YOUR_KEY" -H "deviceid: YOUR_DEVICE_ID" \
  "https://cloud.connexa.com/public-api/v1/devices/YOUR_DEVICE_ID/data?window=30d&limit=500"
# => { "success": true, "data": [ ... ], "nextCursor": "eyJ2Ijoi..." }

curl -H "Authorization: Bearer cxa_live_YOUR_KEY" -H "deviceid: YOUR_DEVICE_ID" \
  "https://cloud.connexa.com/public-api/v1/devices/YOUR_DEVICE_ID/data?window=30d&limit=500&cursor=eyJ2Ijoi..."

Each record contains sampled_at, published_at, object, slave, event, data, fw_version and cc_firmware.

Each device in /devices and /devices/:deviceId contains deviceId, deviceName, deviceStatus, sparkStatus, chargeControllerModel, firmware, fw_version, loadState, loadSetting, batteryVoltage, signalStrength, lastHeard, daytimeOnlyState, pauseAlerts, alertResumeTime, tag1, tag2, tag3, siteId and siteName. Billing and account details are never included.

Example: download a month of data (Python)

import requests

BASE = "https://cloud.connexa.com/public-api/v1"
KEY = "cxa_live_YOUR_KEY"
DEVICE = "YOUR_DEVICE_ID"

headers = {"Authorization": f"Bearer {KEY}", "deviceid": DEVICE}
params = {"window": "30d", "limit": 500}

records = []
while True:
    r = requests.get(f"{BASE}/devices/{DEVICE}/data", headers=headers, params=params)
    r.raise_for_status()
    body = r.json()
    records.extend(body["data"])
    if not body["nextCursor"]:
        break
    params["cursor"] = body["nextCursor"]

print(len(records), "records")

Limits

  • Device endpoints: 100 requests per 15 minutes per account.
  • Signing in with a password (POST /auth/token, an alternative to API keys): 10 requests per 15 minutes. Prefer an API key for anything automated.

Responses include X-RateLimit-Remaining and X-RateLimit-Reset headers. If you go over, you get 429 with a Retry-After header: wait that many seconds and try again. Asking for larger pages (up to the maximum) uses fewer requests than many small ones.

Errors

Every error has the same shape. error is the standard HTTP reason and message says what went wrong:

{ "success": false, "status": 400, "error": "Bad Request",
  "message": "limit must be a positive integer (max 500)." }
Status Meaning
400 A parameter is missing or invalid; the message says which.
403 The key is missing, invalid, revoked or expired, or the device is not on your account.
404 The device or route does not exist.
429 Rate limit reached; wait for Retry-After.
500 Something went wrong on our side; try again shortly.

Good practice

  • Give each integration its own labelled key so you can revoke one without affecting the others.
  • Rotate keys before they expire.
  • If a key may have been exposed, revoke it and generate a new one straight away.