Licence
Licence
The complete MQTT platform in one small binary: broker, SQL rules, data connectors and multi-tenancy in a single process.
Request, install and read the licence. Use it to unlock clustering. You get identity, expiry and entitlements.
flowchart LR Op["operator"] -- "GET /api/v1/licence/status" --> API["management API"] API -- "read" --> L["licence"]Before you start
- Start the broker from First start.
- Set
INDRA_API_KEYto an operator key. The examples read it.
Note: Calls except
/healthzneed an operator API key. Pass it asAuthorization: Bearer $INDRA_API_KEY.
Commercial licence request, install and status
POST /api/v1/licence/install
Install a licence token
Operation id: installLicence.
Parameters:
No parameters.
Request body:
Media type application/json:
Required: token.
| Field | Type | Description |
|---|---|---|
token | string |
Responses:
| Status | Description |
|---|---|
| 200 | Installed licence payload |
| 400 | Token rejected |
| 409 | Token names another installation |
Response 200 body:
Media type application/json:
{ "type": "object", "properties": { "customer": { "type": "string" }, "expires_at": { "type": "integer" }, "max_nodes": { "type": "integer" }, "kid": { "type": "string" } }}Notes:
-
Send
token. An empty required string fails with 400. -
A token for another installation fails with 409.
-
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X POST 'http://127.0.0.1:18083/api/v1/licence/install' \ -H "Authorization: Bearer $INDRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "token": "INDRA-ENT-V2.doc-payload.doc-signature"}'GET /api/v1/licence/request
Show the installation licence request
Operation id: getLicenceRequest.
Parameters:
No parameters.
Request body:
No request body.
Responses:
| Status | Description |
|---|---|
| 200 | Licence request safe to send |
| 503 | Request cannot be generated |
Response 200 body:
Media type application/json:
{ "type": "object"}Notes:
- Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X GET 'http://127.0.0.1:18083/api/v1/licence/request' \ -H "Authorization: Bearer $INDRA_API_KEY"GET /api/v1/licence/status
Show licence status
Operation id: getLicenceStatus.
Parameters:
No parameters.
Request body:
No request body.
Responses:
| Status | Description |
|---|---|
| 200 | Identity, customer, expiry and entitlements |
Response 200 body:
Media type application/json:
{ "type": "object"}Notes:
- Related calls sit on the same tag page.
Verified: the example flow below runs this call.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X GET 'http://127.0.0.1:18083/api/v1/licence/status' \ -H "Authorization: Bearer $INDRA_API_KEY"Example flow
Read real rows through the management API, then read them back. The docs harness runs this flow against a started broker.
python3 - <<'PY'import json, os, urllib.requestport = os.environ.get("API_PORT", "18083")key = os.environ.get("API_KEY", "")base = f"http://127.0.0.1:{port}"req = urllib.request.Request(base + "/api/v1/licence/status", method="GET")req.add_header("Authorization", f"Bearer {key}")with urllib.request.urlopen(req, timeout=5) as r: body = r.read().decode() assert r.status == 200, bodyparsed = json.loads(body)assert isinstance(parsed, dict), bodyreq2 = urllib.request.Request(base + "/api/v1/licence/status", method="GET")req2.add_header("Authorization", f"Bearer {key}")with urllib.request.urlopen(req2, timeout=5) as r2: body2 = r2.read().decode() assert r2.status == 200, body2assert body == body2, "read back the same status"print("OK")PYOKCheck that it works
Start the broker with this file. The health endpoint returns OK.
[node]id = "doc-ref"
[listeners.tcp]bind = "0.0.0.0:1883"
[listeners.tls]bind = "0.0.0.0:8883"
[listeners.ws]bind = "0.0.0.0:8083"
[listeners.wss]bind = "0.0.0.0:8084"
[listeners.api]bind = "0.0.0.0:18083"
[logging]level = "warn"python3 - <<'PY'import os, socketport = int(os.environ.get("API_PORT", "18083"))sock = socket.create_connection(("127.0.0.1", port), timeout=5)sock.sendall(b"GET /healthz HTTP/1.0\r\nHost: docs\r\n\r\n")print(sock.makefile().read().strip().splitlines()[-1])PYOKCheck one documented call. GET /api/v1/licence/status answers 200 with its rows. It prints OK.
python3 - <<'PY'import os, urllib.requestport = os.environ.get("API_PORT", "18083")key = os.environ.get("API_KEY", "")base = f"http://127.0.0.1:{port}"req = urllib.request.Request(base + "/api/v1/licence/status", method="GET")req.add_header("Authorization", f"Bearer {key}")with urllib.request.urlopen(req, timeout=5) as r: body = r.read().decode() assert r.status == 200, bodyassert len(body.strip()) > 0, bodyprint("OK")PYOKNext steps
- API reference: the other tags.
- Configuration reference: the settings behind the rows.
- Metrics reference: the counter names.