MachineQ Developer Documentation logo DOCS

Gateway & Network Provisioning

Gateways are the foundation of every LoRaWAN® deployment. Before any device can join the network, at least one gateway must be online, registered, and within Radio Frequency (RF) reach of that device.

Choosing a Gateway

MachineQ supports a range of indoor and outdoor LoRaWAN gateways. The right choice depends on:

  • Coverage area: Indoor vs. Outdoor
  • Backhaul: Ethernet vs. cellular

Contact MachineQ Support for hardware recommendations specific to your deployment.

Registering a Gateway

Step 1: Look Up the Gateway Profile ID

Gateway creation requires a Gateway Profile ID (the model/hardware type). Fetch available profiles for your account:

List the gateway profiles
curl -sS -H "Authorization: Bearer $MQ_TOKEN" \
  "https://api.machineq.net/v1/gatewayprofiles" | jq

Save the Id for the profile matching your hardware; pass it as GatewayProfile in the next step.

Step 2: Create the Gateway

You need the gateway's Node ID (the 16-digit hex Gateway EUI, printed on the device or available via its onboarding QR code) and its MAC address.

Create the gateway
curl -sS -X POST https://api.machineq.net/v1/gateways \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "NodeId": "<node_id>",
    "MacAddress": "<mac_address>",
    "Name": "warehouse-roof-01",
    "GatewayProfile": "<gateway_profile_id>",
    "AntennaGain": "3",
    "LocationType": "OUTDOOR",
    "Coordinates": {
      "X": "39.9526",
      "Y": "-75.1652",
      "Z": "12"
    }
  }'
API reference:

Field notes:

  • Coordinates.X = Latitude, Y = Longitude, Z = Height in meters, all as string values. Set to 0 if location is unknown.
  • LocationType accepts INDOOR or OUTDOOR.
  • GPSEnabled: true can be set for GPS-equipped gateways; the gateway will self-report its position, so Coordinates can be omitted.
  • CellularEnabled: true unlocks optional IMEI and ICCID fields for cellular backhaul.

The response returns an Id for the newly created gateway. Export it for use in subsequent API calls:

Export the gateway ID
export MQ_GATEWAY_ID="<Id_from_response>"

Once registered, power on the gateway and connect it to your network. The gateway reaches out to the MachineQ network server within a few minutes.

Monitoring Gateway Health

Every gateway reports telemetry, which the platform aggregates into a health view. Pull current statistics for a single gateway:

Fetch the gateway statistics
curl -sS -H "Authorization: Bearer $MQ_TOKEN" \
  "https://api.machineq.net/v1/gateways/$MQ_GATEWAY_ID/statistics" | jq

The key fields in the response:

Field Description
LrrCNX Boolean. true = gateway can reach the network server (online); false = cannot (offline).
ConnectionState CNX (connected), DISC (disconnected), NEVERCNX (never connected).
HealthState ACTIVE, BACKHAUL_CNX_ERROR, RF_ERROR, INIT, or HEALTH_UNKNOWN.
LastReportingTime When the platform last received any traffic. A gap of 15+ minutes warrants an alert.
LastUplinkTime Timestamp of the most recent uplink forwarded.
SoftwareVersion Packet forwarder version. Outdated forwarders are the most common cause of subtle protocol bugs.
UplinkPacketPerHour Uplink throughput rate. Sudden drops correlate with backhaul or RF problems.
DownlinkPacketPerHour Downlink throughput rate.

LrrCNX is also embedded in the Statistics object returned by GET /v1/gateways, making it easy to check connectivity across your entire fleet in one call.

To see all gateways grouped by connection or health state:

List the gateways by state
# Grouped by connection state
curl -sS -H "Authorization: Bearer $MQ_TOKEN" \
  "https://api.machineq.net/v1/gateways/connection" | jq

# Grouped by health state
curl -sS -H "Authorization: Bearer $MQ_TOKEN" \
  "https://api.machineq.net/v1/gateways/health" | jq

To retrieve historical gateway events (connection changes, packet forwarder reconnects, RF config pushes) for a specific time window:

Fetch the gateway events
curl -sS -H "Authorization: Bearer $MQ_TOKEN" \
  "https://api.machineq.net/v1/gateways/$MQ_GATEWAY_ID/events" \
  | jq

Each event includes a Field indicating what changed (BACKHAUL_CONNECTED, BACKHAUL_DISCONNECTED, PACKET_FORWARDER_CONNECTED, PACKET_FORWARDER_DISCONNECTED, ONLINE_STATUS, etc.) along with OldValue, NewValue, and a Time timestamp.

Gateway Connectivity Notifications

There are two approaches to detecting and acting on gateway online/offline changes:

  1. push notifications via the Output Alert Service, or
  2. polling LrrCNX on a schedule.

Option 1: Push Notifications (Output Alert Service)

The Output Alert Service delivers a JSON event payload to your endpoint whenever a gateway's connectivity status changes. Setup takes three steps.

Note: The Output Alert Service uses the v2 API at https://api.machineq.net/v2; all calls in this section use that base URL, not the v1 base URL used elsewhere in this guide. For the full v2 API reference, check out: https://docs.machineq.net/machineq-api-v2.html.

Step 1: Create Output Credentials

Credentials define how MQcentral authenticates delivery to your endpoint. Create them first; the id returned is required when creating a destination.

Create the output credentials
curl -sS -X POST https://api.machineq.net/v2/output/credentials \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Gateway Monitor Auth",
    "type": "basic_auth",
    "data": {
      "username": "gateway_monitor",
      "password": "<your-password>"
    }
  }' | jq

A successful 201 Created response returns:

Inspect the credentials response
{
  "id": "Xrzm28a0",
  "name": "My Gateway Monitor Auth",
  "type": "basic_auth"
}

The credential type depends on your destination:

Destination type Credential type
webhook basic_auth or client_credentials
mqtt basic_auth
aws_iot_core x509_certificate
azure_iot_hub azure_shared_access_policy
Export the credential ID
export MQ_CREDENTIAL_ID="<credential_id>"

Step 2: Create an Output Destination

A destination defines where event payloads are delivered.

Create the output destination
curl -sS -X POST https://api.machineq.net/v2/output/destinations \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"My Gateway Monitor Webhook\",
    \"type\": \"webhook\",
    \"enabled\": true,
    \"credentials_id\": \"$MQ_CREDENTIAL_ID\",
    \"data\": {
      \"url\": \"https://your-endpoint.example.com/gateway-alerts\",
      \"headers\": [
        { \"header\": \"accept\", \"value\": \"application/json\" }
      ]
    }
  }" | jq

The 201 Created response returns a destination id; use it in Step 3.

Export the destination ID
export MQ_DESTINATION_ID="<destination_id>"

Step 3: Create an Output Alert

An alert ties one or more gateway Node IDs to one or more destinations. When any monitored gateway goes online or offline, all listed destinations are notified.

Create the output alert
curl -sS -X POST https://api.machineq.net/v2/output/alerts \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"My Gateway Connectivity Alert\",
    \"type\": \"gateway_connectivity\",
    \"data\": {
      \"node_ids\": [
        \"$MQ_GATEWAY_ID\"
      ]
    },
    \"destination_ids\": [
      \"$MQ_DESTINATION_ID\"
    ]
  }" | jq
Field Description
name Human-readable label for the alert.
type Always gateway_connectivity for gateway online/offline alerts.
data.node_ids One or more gateway Node IDs to monitor.
destination_ids One or more Output Destination IDs to notify when the alert fires.
Export the alert ID
export MQ_ALERT_ID="<alert_id>"

Managing Gateways on an Existing Alert

Add or remove gateways from an alert without recreating it:

Manage the alert gateways
# Add a single gateway
curl -sS -X POST "https://api.machineq.net/v2/output/alerts/$MQ_ALERT_ID/gateways:add" \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "node_id": "<node_id>" }' | jq

# Add multiple gateways
curl -sS -X POST "https://api.machineq.net/v2/output/alerts/$MQ_ALERT_ID/gateways:batch_add" \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "node_ids": ["FFFF00800001069F", "2CC4070000002E86"] }' \
  | jq

# Remove a single gateway
curl -sS -X POST 'https://api.machineq.net/v2/output/alerts/$MQ_ALERT_ID/gateways:remove' \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "node_id": "FFFF00800001069F" }' | jq

# Remove multiple gateways
curl -sS -X POST "https://api.machineq.net/v2/output/alerts/$MQ_ALERT_ID/gateways:batch_remove" \
  -H "Authorization: Bearer $MQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "node_ids": ["FFFF00800001069F", "2CC4070000002E86"] }' \
  | jq

Note: batch_add and batch_remove are all-or-nothing. If any gateway's node_id is already present when adding, or missing when removing, the entire request fails.

Output Event Payload

When a gateway's connectivity changes, MQcentral delivers a JSON payload to all configured destinations:

Inspect the event payload
{
  "timestamp": "2022-09-12T14:49:01.964Z",
  "type": "gateway_connectivity",
  "data": {
    "timestamp": "2022-09-12T14:49:01.919Z",
    "node_id": "2CC4070000001234",
    "status": "online"
  }
}
API reference:

data.status is either "online" or "offline". The top-level timestamp is when MQcentral generated the event; data.timestamp is when the gateway state actually changed, and these may differ slightly.

Gateway connectivity alerts have a built-in 15-minute debounce; a status change is only delivered after it persists for 15 minutes, filtering out transient connectivity blips.

Option 2: Polling LrrCNX

If you prefer polling over push notifications, call GET /v1/gateways/{Id}/statistics and check the LrrCNX boolean:

  • true: gateway is connected to the network server (online)
  • false: gateway cannot reach the network server (offline)

Polling guidance: LrrCNX can briefly flip to false during transient network blips. Confirm the state across two consecutive polling cycles (e.g., two 15-minute intervals) before triggering an alert.

What's Next?