Authentication
Every request to EdgeMQ requires authentication. This guide explains how to create API keys, choose the right permissions, and authenticate your HTTP and MQTT requests.
Overview
EdgeMQ uses API keys for authentication across both protocols. You create a key in the Console, then use it in one of three ways:
- HTTP header — pass the key in the
X-API-Keyheader (simplest for HTTP ingest) - MQTT CONNECT — pass the key in the MQTT
passwordfield (for IoT devices) - Token exchange — exchange the key for a short-lived JWT access token (for managing resources via API)
The same API key works for both HTTP and MQTT. You do not need separate keys per protocol.
Step 1: Create an API key
- Log in to the EdgeMQ Console
- Navigate to API Keys in the sidebar
- Click Create API Key
- Give it a descriptive name (e.g.,
production-ingest,ci-deploy,monitoring) - Select the permissions you need (see below)
- Click Create Key
The key is shown once — copy it immediately and store it securely. It looks like this:
ing_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345Step 2: Choose permissions
When creating a key, you select one or more permission scopes:
| Scope | What it does | Use case |
|---|---|---|
| Ingest | Send data to your endpoints (HTTP and MQTT) | Application backends, IoT devices, webhooks |
| Admin | Manage endpoints, destinations, views, and keys | CI/CD pipelines, infrastructure-as-code, agents |
| Metrics | Read data quality metrics, DLQ files, and delivery status | Monitoring dashboards, alerting |
You can combine scopes. For example, a key with Ingest + Metrics can send data and read delivery status.
Principle of least privilege — create separate keys for separate purposes. Your production ingest pipeline should use an ingest-only key. Your CI/CD system should use an admin key. Your monitoring should use a metrics-only key.
Step 3: Authenticate requests
Option A: HTTP header (for HTTP ingest)
Pass your key in the X-API-Key header:
curl -X POST https://your-endpoint.ingest.edge.mq/v1/ingest \ -H "X-API-Key: ing_live_aBcDeFgH..." \ -H "Content-Type: application/x-ndjson" \ -d '{"user_id": "123", "event": "signup", "timestamp": "2026-01-15T10:30:00Z"}'
The ingest node verifies your key and caches the result for fast subsequent requests. No token exchange needed.
Best for: Application backends, webhooks, batch uploads — any HTTP-based producer.
Option B: MQTT CONNECT (for IoT devices)
Pass your key in the MQTT CONNECT packet's password field. The same API key used for HTTP works here — no separate credential needed.
Python (paho-mqtt):
import paho.mqtt.client as mqtt client = mqtt.Client(transport=class="t-string">"websockets") client.ws_set_options(path=class="t-string">"/mqtt") client.username_pw_set(class="t-string">"my-device", class="t-string">"ing_live_aBcDeFgH...") client.tls_set() client.connect(class="t-string">"your-endpoint.ingest.edge.mq", class="t-number">443) client.publish(class="t-string">"sensors/temperature", class="t-string">'{"temp": class="t-number">22.5}')
Node.js (mqtt.js):
import mqtt from class="t-string">'mqtt' const client = mqtt.connect(class="t-string">'wss:class="t-comment">//your-endpoint.ingest.edge.mq/mqtt', { username: class="t-string">'my-device', password: class="t-string">'ing_live_aBcDeFgH...' })
| MQTT field | Value | Purpose |
|---|---|---|
password | Your API key | Authentication (required) |
username | Any string | Display name in metrics (not used for auth) |
clientId | Device identifier | Connection tracking; should be unique per device |
Authentication happens once at CONNECT time. Subsequent PUBLISH messages on the same connection do not require re-authentication.
Best for: IoT devices, sensors, gateways publishing telemetry via MQTT. See the MQTT guide for full connection setup and additional client library examples.
Option C: Token exchange (for managing resources)
If you need to manage endpoints, destinations, or views via the API, exchange your key for a short-lived JWT:
# Step 1: Exchange your API key for an access token curl -X POST https://api.edge.mq/v1/token/exchange \ -H "Content-Type: application/json" \ -d '{ "api_key": "ing_live_aBcDeFgH...", "scope": "admin" }'
Response:
{ "access_token":: "eyJhbGciOiJSUzI1NiI...", "token_type":: "Bearer", "expires_in":: 900 }
# Step 2: Use the token for API calls curl https://api.edge.mq/v1/endpoints \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiI..."
The token expires after 15 minutes. Exchange a new one when it expires.
Best for: Managing resources (endpoints, destinations, views), CI/CD automation, agent workflows.
Which method should I use?
| Scenario | Method | Scope |
|---|---|---|
| Send events from my app (HTTP) | Direct API key | Ingest |
| Send telemetry from IoT devices (MQTT) | MQTT CONNECT | Ingest |
| Send events at high volume (HTTP) | Token exchange | Ingest |
| Create/update endpoints in CI/CD | Token exchange | Admin |
| List my endpoints and destinations | Token exchange | Admin |
| Create and publish schema views | Token exchange | Admin |
| Monitor delivery status | Token exchange | Metrics |
| Check DLQ files for failed records | Token exchange | Metrics |
| AI agent managing my infrastructure | Token exchange | Admin |
Token exchange details
Scope selection
When exchanging a key, you specify which scope to use for the token. The key must have that scope — if you request admin but the key only has ingest, the exchange returns 403 Forbidden.
{ "api_key":: "ing_live_...", "scope":: "admin", "ttl":: "15m" }
The scope parameter accepts: ingest, admin, or metrics. Default is ingest.
The optional ttl parameter controls token lifetime (default 15m). Shorter tokens are more secure.
Token refresh
Tokens are short-lived by design. When your token expires, exchange your API key for a new one. There is no refresh token mechanism — the API key itself is the long-lived credential.
# Your token expired? Just exchange again. TOKEN=$(curl -s -X POST https://api.edge.mq/v1/token/exchange \ -H "Content-Type: application/json" \ -d '{"api_key": "ing_live_...", "scope": "admin"}' \ | jq -r '.access_token')
Error handling
| Status | Meaning | Action |
|---|---|---|
401 | Invalid or revoked API key | Check the key is correct and not revoked |
403 | Key doesn't have the requested scope | Create a new key with the right permissions |
429 | Rate limited | Wait and retry with exponential backoff |
For MQTT, authentication errors are returned as CONNACK return codes:
| CONNACK code | Meaning | Equivalent HTTP status |
|---|---|---|
0x00 | Connection accepted | 200 |
0x04 | Bad username or password (invalid API key) | 401 |
0x05 | Not authorized (key lacks Ingest scope) | 403 |
0x03 | Server unavailable (backpressure or capacity) | 503 |
All HTTP error responses follow RFC 7807 format with a retry field indicating whether the request can be retried.
Key management
Revoking keys
Revoke a key immediately from the Console. Revocation propagates to all ingest nodes within 30 seconds. Any tokens previously issued from that key continue to work until they expire (max 15 minutes). Active MQTT connections authenticated with the revoked key remain connected until their next re-authentication (e.g., reconnect).
Key rotation
To rotate a key:
- Create a new key with the same permissions
- Update your applications and devices to use the new key
- Revoke the old key once all instances are updated
For MQTT devices, coordinate the key update with device firmware or configuration management before revoking the old key.
Security best practices
- Store keys in environment variables or a secrets manager — never in source code or device firmware images
- Use separate keys for separate environments (dev, staging, production)
- Use separate keys for HTTP and MQTT if you want independent revocation control
- Use the minimum scope needed for each key
- Rotate keys periodically (every 90 days recommended)
- Revoke keys immediately when team members leave or keys are compromised