Meraki Dashboard API

Meraki Dashboard API for managing organizations, networks, devices, and configuration templates.

Authentication & Rate Limiting

Meraki Dashboard API uses a single API key in the header. No token exchange.

Set API key variable β€” all calls use this header
MERAKI_API_KEY="<your-api-key>"
MERAKI_BASE="https://api.meraki.com/api/v1"
Test authentication β€” list organizations you have access to
curl -s \
  "${MERAKI_BASE}/organizations" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {id, name, url}'
Output
{
  "id": "123456",
  "name": "Domus Digitalis Lab",
  "url": "https://n123.meraki.com/o/abcdef/manage/organization/overview"
}

Rate limiting rules:

Limit: 5 API calls per second per organization
Burst: 5 calls (then 429 responses)
Header: X-RateLimit-Remaining shows calls left
Retry: Wait for Retry-After header value (seconds)
Dashboard API calls: 5/sec org-wide, not per-key
Action Batches: Use for bulk operations (up to 20K actions)
The 5 calls/sec limit is per organization, not per API key. Multiple scripts hitting the same org will share this limit. Use action batches for bulk operations.

Organizations & Networks

Store org ID for subsequent calls
ORG_ID="123456"
List all networks in an organization
curl -s \
  "${MERAKI_BASE}/organizations/${ORG_ID}/networks" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {id, name, productTypes, timeZone}'
Output
{
  "id": "L_123456789",
  "name": "HQ-Network",
  "productTypes": ["appliance", "switch", "wireless"],
  "timeZone": "America/Los_Angeles"
}
Create a new network
curl -s -X POST \
  "${MERAKI_BASE}/organizations/${ORG_ID}/networks" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Branch-Office-01",
    "productTypes": ["appliance", "switch", "wireless"],
    "timeZone": "America/Los_Angeles",
    "tags": ["branch", "west-coast"]
  }' | jq

Device Inventory

List all devices in a network
NETWORK_ID="L_123456789"
curl -s \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/devices" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {name, serial, model, lanIp, firmware}'
Output
{
  "name": "HQ-AP-01",
  "serial": "Q2AB-CD12-EF34",
  "model": "MR46",
  "lanIp": "10.50.1.30",
  "firmware": "wireless-29-7"
}
Get all devices across the entire organization
curl -s \
  "${MERAKI_BASE}/organizations/${ORG_ID}/devices?perPage=1000" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {name, serial, model, networkId}'
Get device uplink status β€” WAN1/WAN2 for MX appliances
curl -s \
  "${MERAKI_BASE}/organizations/${ORG_ID}/appliance/uplink/statuses" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {networkName: .networkId, uplinks: [.uplinks[] | {interface, status, ip, publicIp}]}'

Clients

List clients on a network β€” last 24 hours
curl -s \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/clients?timespan=86400&perPage=100" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {description, mac, ip, vlan, usage: {sent: .usage.sent, recv: .usage.recv}}'
Get specific client by MAC β€” track a device across the network
CLIENT_MAC="aa:bb:cc:dd:ee:ff"
curl -s \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/clients/${CLIENT_MAC}" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '{description, ip, vlan, switchport, ssid, status}'

Wireless β€” SSID Configuration

List all SSIDs on a network (0-14)
curl -s \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/wireless/ssids" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | select(.enabled == true) | {number, name, authMode, encryptionMode}'
Update SSID settings β€” change name, auth mode, PSK
SSID_NUMBER=0
curl -s -X PUT \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/wireless/ssids/${SSID_NUMBER}" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Corp-Wireless",
    "enabled": true,
    "authMode": "8021x-radius",
    "radiusServers": [
      {"host": "10.50.1.20", "port": 1812, "secret": "<REDACTED>"}
    ],
    "encryptionMode": "wpa-eap",
    "wpaEncryptionMode": "WPA2 only"
  }' | jq '{name, enabled, authMode}'

Switch Ports

Get all switch port configurations
SERIAL="Q2AB-CD12-EF34"
curl -s \
  "${MERAKI_BASE}/devices/${SERIAL}/switch/ports" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {portId, name, type, vlan, voiceVlan, enabled}'
Update a switch port β€” set access VLAN and name
PORT_ID="1"
curl -s -X PUT \
  "${MERAKI_BASE}/devices/${SERIAL}/switch/ports/${PORT_ID}" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "User-Port-01",
    "type": "access",
    "vlan": 10,
    "voiceVlan": 20,
    "poeEnabled": true,
    "enabled": true
  }' | jq '{portId, name, type, vlan, voiceVlan}'

Pagination

Meraki uses Link headers for pagination, not offset/limit in the response body.

Handle pagination β€” follow Link headers
# First page
RESPONSE=$(curl -s -D /tmp/meraki-headers \
  "${MERAKI_BASE}/organizations/${ORG_ID}/networks?perPage=10" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}")
echo "${RESPONSE}" | jq '.[].name'

# Check for next page
awk '/^Link:/ {print}' /tmp/meraki-headers
# Output: Link: <https://api.meraki.com/api/v1/...?perPage=10&startingAfter=N_12345>; rel=next

# Follow next page URL from Link header
NEXT_URL=$(awk -F'[<>]' '/^Link:.*rel=next/ {print $2}' /tmp/meraki-headers)
[[ -n "${NEXT_URL}" ]] && curl -s "${NEXT_URL}" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[].name'
Always check the Link header. If rel=next exists, there are more pages. Maximum perPage varies by endpoint (typically 1000). Omitting pagination risks silent data truncation.

Webhook Alerts

List configured webhook receivers
curl -s \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/webhooks/httpServers" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" | jq '.[] | {id, name, url}'
Create a webhook receiver
curl -s -X POST \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/webhooks/httpServers" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "SIEM-Webhook",
    "url": "https://siem.example.com/api/v1/meraki-events",
    "sharedSecret": "<REDACTED>"
  }' | jq
Test a webhook β€” sends a sample payload
WEBHOOK_ID="aHR0cHM6Ly93ZW..."
curl -s -X POST \
  "${MERAKI_BASE}/networks/${NETWORK_ID}/webhooks/webhookTests" \
  -H "X-Cisco-Meraki-API-Key: ${MERAKI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d "{\"url\": \"https://siem.example.com/api/v1/meraki-events\"}" | jq