API reference
CPEs
Customer radios: plan, signal, shaping and live health
- List CPEs
GET /v1/cpes - Get a CPE
GET /v1/cpes/{cpeid} - Get a CPE's health
GET /v1/cpes/{cpeid}/health - Get a CPE's history
GET /v1/cpes/{cpeid}/history/{series}
List CPEs
Your customers' radios (CPEs). Filter by access point, site or region (through the access point), plan, disconnected accounts, or account_number (the number on the customer's invoices), or search with q, which matches MAC and IP addresses, and names too with the pii scope. Each one comes with its billing plan's rates and effective_rate_mbps: what the shaper is applying right now, which is the plan, lowered when the network is congested or the customer is over a usage cap. Subscriber names need the pii scope; without it, CPEs are named by MAC address and account number.
Parameters
-
ispstring queryISP code from GET /isps. Optional when the key reaches exactly one ISP.
-
apinteger queryRestrict to CPEs associated to this access point (its infid)
-
siteinteger or string queryRestrict to CPEs whose access point is at this site: site_id or site code
-
regioninteger queryRestrict to CPEs whose access point is in this region: region_id from
list_regions -
planinteger queryRestrict to one billing plan: a plan_id from a CPE's plan
-
disconnectedboolean querytrue: only CPEs on disconnected accounts; false: only connected ones
-
account_numberstring queryExact customer account number (as shown on invoices)
-
qstring querySubstring match: MAC/IP always; account+device names only with pii scope
-
limitinteger queryMax rows (default 200, max 500)
-
cursorstring querynext_cursor from the previous page
Response
Also available as CSV: add format=csv. Columns follow the field order below, with nested fields as dotted columns
(ap.name).
Paged: pass next_cursor back as cursor for the next page.
-
countinteger -
next_cursorstring nullablePass as cursor to get the next page; null on the last page
-
cpesarray of objectsEach item: 16 fields
-
cpeidinteger -
macstring -
ipstring nullable -
apobject nullableThe access point it's associated to
2 fields
-
infidinteger -
namestring
-
-
siteobject nullableThe access point's site
3 fields
-
site_idinteger -
codestringThe ISP's short site code
-
namestring
-
-
account_numberstring nullableThe customer-visible account number, as on invoices
-
account_disconnectedboolean nullable -
signal_dbmnumber nullable -
planobject nullableThe billing plan and its configured rates
4 fields
-
plan_idinteger nullablePass as plan to
list_cpes -
namestring nullable -
down_mbpsnumber nullable -
up_mbpsnumber nullable
-
-
effective_rate_mbpsobject nullableWhat the shaper applies right now: the plan reduced by congestion multipliers or usage caps
2 fields
-
downnumber nullable -
upnumber nullable
-
-
monitoredboolean -
last_assocdate-time nullable -
namestringThe subscriber's name with the pii scope; otherwise 'CPE <mac> (account <number>)'
-
account_namestring nullable optionalpii scope only
-
descriptionstring nullable optionalpii scope only
-
discovered_namestring nullable optionalpii scope only: the name the radio reports
-
Example
curl -H "Authorization: Bearer $SWIFTFOX_KEY" \
"https://api.swiftfox.net/v1/cpes?isp=yourisp" Response (example data):
{
"count": 1,
"next_cursor": "eyJ2IjoxLCJvIjoyMDB9",
"cpes": [
{
"cpeid": 5012,
"mac": "00:00:5E:00:53:1A",
"ip": "10.50.7.112",
"ap": {
"infid": 230,
"name": "Hilltop Sector 1"
},
"site": {
"site_id": 7,
"code": "HT",
"name": "Hilltop Tower"
},
"account_number": "10442",
"account_disconnected": false,
"signal_dbm": -61,
"plan": {
"plan_id": 4,
"name": "Residential 50",
"down_mbps": 50,
"up_mbps": 10
},
"effective_rate_mbps": {
"down": 50,
"up": 10
},
"monitored": true,
"last_assoc": "2026-10-08T22:01:37Z",
"name": "CPE 00:00:5E:00:53:1A (account 10442)"
}
]
} Get a CPE
One customer radio: who it belongs to, its access point, billing plan, what the shaper is applying right now, its signal and last association, and its live health. History: get_cpe_history with series pings, traffic, plan, quality or signal. Subscriber names need the pii scope; without it, CPEs are named by MAC address and account number. An issue's status is active (alerting now), pending (alerting, but still inside its grace period, so not alert-worthy yet) or recovering (back to good, but held open a while in case it comes back: recovered_at is when it went good, and resolves_at is when it clears if it stays good).
Parameters
-
cpeidinteger path requiredCPE id from
list_cpes/ip_lookup/list_issue_events -
ispstring queryISP code from GET /isps. Optional when the key reaches exactly one ISP.
Response
-
cpeidinteger -
macstring -
ipstring nullable -
apobject nullableThe access point it's associated to
2 fields
-
infidinteger -
namestring
-
-
siteobject nullableThe access point's site
3 fields
-
site_idinteger -
codestringThe ISP's short site code
-
namestring
-
-
account_numberstring nullableThe customer-visible account number, as on invoices
-
account_disconnectedboolean nullable -
signal_dbmnumber nullable -
planobject nullableThe billing plan and its configured rates
4 fields
-
plan_idinteger nullablePass as plan to
list_cpes -
namestring nullable -
down_mbpsnumber nullable -
up_mbpsnumber nullable
-
-
effective_rate_mbpsobject nullableWhat the shaper applies right now: the plan reduced by congestion multipliers or usage caps
2 fields
-
downnumber nullable -
upnumber nullable
-
-
monitoredboolean -
last_assocdate-time nullable -
namestringThe subscriber's name with the pii scope; otherwise 'CPE <mac> (account <number>)'
-
account_namestring nullable optionalpii scope only
-
descriptionstring nullable optionalpii scope only
-
discovered_namestring nullable optionalpii scope only: the name the radio reports
-
healtharray of objectsEach item: 10 fields
-
metricstring -
substring optionalWhich value of a metric with several on one entity (a radio chain, a vulnerability)
-
descriptionstring optional -
valuenumber nullableLatest collected value
-
unitstring optional -
statestringThreshold state name for the value, e.g. Good, Warning, Down; Inactive = the metric has no thresholds set
-
severityone of: "ok", "info", "warning", "outage", "critical" nullableok, info, warning, outage or critical for the state's level; null when the metric has no thresholds
-
value_ttl_secondsinteger nullableSeconds until the value is considered stale; -1 = no expiry set
-
issueobject nullable6 fields
-
detailsstring -
severityone of: "ok", "info", "warning", "outage", "critical"ok while recovering, otherwise info, warning, outage or critical
-
sincedate-time nullableWhen the issue started
-
statusone of: "active", "pending", "recovering" -
recovered_atdate-time nullablerecovering only: when the metric went back to good
-
resolves_atdate-time nullablerecovering only: when the issue clears if it stays good
-
-
has_historyboolean optionalDevices: true when the metric's history is available (REST: /devices/{infid}/history/{metric})
-
Example
curl -H "Authorization: Bearer $SWIFTFOX_KEY" \
"https://api.swiftfox.net/v1/cpes/5678?isp=yourisp" Response (example data):
{
"cpeid": 5012,
"mac": "00:00:5E:00:53:1A",
"ip": "10.50.7.112",
"ap": {
"infid": 230,
"name": "Hilltop Sector 1"
},
"site": {
"site_id": 7,
"code": "HT",
"name": "Hilltop Tower"
},
"account_number": "10442",
"account_disconnected": false,
"signal_dbm": -61,
"plan": {
"plan_id": 4,
"name": "Residential 50",
"down_mbps": 50,
"up_mbps": 10
},
"effective_rate_mbps": {
"down": 50,
"up": 10
},
"monitored": true,
"last_assoc": "2026-10-08T22:01:37Z",
"name": "CPE 00:00:5E:00:53:1A (account 10442)",
"health": [
{
"metric": "Ping:Quality",
"description": "A weighted quality rating based on packet loss and latency.",
"value": 5,
"unit": "",
"state": "Good",
"severity": "ok",
"value_ttl_seconds": 604780,
"issue": null
},
{
"metric": "Wireless:Signal",
"sub": "Chain 0",
"description": "Receive Signal Strength (RSSI) in dBm",
"value": -61,
"unit": "dBm",
"state": "Good",
"severity": "ok",
"value_ttl_seconds": 604780,
"issue": null
}
]
} Get a CPE's health
The live monitored metrics for one device, backhaul or CPE: each metric's latest value and unit, its threshold state and severity, and any open issue. It's the same list as get_device's health, for backhauls and CPEs too. For devices, entries with has_history have history in get_device_history (series = the metric name). An issue's status is active (alerting now), pending (alerting, but still inside its grace period, so not alert-worthy yet) or recovering (back to good, but held open a while in case it comes back: recovered_at is when it went good, and resolves_at is when it clears if it stays good).
Parameters
-
cpeidinteger path requiredinfid / bhid / cpeid
-
ispstring queryISP code from GET /isps. Optional when the key reaches exactly one ISP.
Response
Also available as CSV: add format=csv. Columns follow the field order below, with nested fields as dotted columns
(ap.name).
-
typestringdevice, backhaul or cpe; more types may be added
-
idinteger -
metricsarray of objectsEach item: 10 fields
-
metricstring -
substring optionalWhich value of a metric with several on one entity (a radio chain, a vulnerability)
-
descriptionstring optional -
valuenumber nullableLatest collected value
-
unitstring optional -
statestringThreshold state name for the value, e.g. Good, Warning, Down; Inactive = the metric has no thresholds set
-
severityone of: "ok", "info", "warning", "outage", "critical" nullableok, info, warning, outage or critical for the state's level; null when the metric has no thresholds
-
value_ttl_secondsinteger nullableSeconds until the value is considered stale; -1 = no expiry set
-
issueobject nullable6 fields
-
detailsstring -
severityone of: "ok", "info", "warning", "outage", "critical"ok while recovering, otherwise info, warning, outage or critical
-
sincedate-time nullableWhen the issue started
-
statusone of: "active", "pending", "recovering" -
recovered_atdate-time nullablerecovering only: when the metric went back to good
-
resolves_atdate-time nullablerecovering only: when the issue clears if it stays good
-
-
has_historyboolean optionalDevices: true when the metric's history is available (REST: /devices/{infid}/history/{metric})
-
Example
curl -H "Authorization: Bearer $SWIFTFOX_KEY" \
"https://api.swiftfox.net/v1/cpes/5678/health?isp=yourisp" Response (example data):
{
"type": "cpe",
"id": 5012,
"metrics": [
{
"metric": "Ping:Quality",
"description": "A weighted quality rating based on packet loss and latency.",
"value": 5,
"unit": "",
"state": "Good",
"severity": "ok",
"value_ttl_seconds": 604780,
"issue": null
},
{
"metric": "Wireless:Signal",
"sub": "Chain 0",
"description": "Receive Signal Strength (RSSI) in dBm",
"value": -61,
"unit": "dBm",
"state": "Good",
"severity": "ok",
"value_ttl_seconds": 604780,
"issue": null
}
]
} Get a CPE's history
History for one device, backhaul or CPE, rolled up into time buckets (up to 200, or max_points up to 500), so long ranges stay small. Series: devices have pings, quality, signal, traffic (with interface), or a health metric name from get_device whose has_history is true; backhauls have pings, quality, traffic or capacity; CPEs have pings, traffic, plan, quality or signal. Each point has its bucket's start time (at), the values for the series and how many readings went into it (samples). pings: loss_avg_pct, loss_max_pct, latency_avg_ms, latency_min_ms, latency_max_ms. traffic, capacity and plan: avg and max Mbps per direction (an interface's in/out, a backhaul's ap_to_su/su_to_ap, a CPE's down/up). quality: quality_avg, quality_min (0 down to 6 perfect). signal: one point per radio chain per bucket. Health metrics: value_avg, value_min, value_max in unit. A missing bucket means nothing was recorded then.
Parameters
-
cpeidinteger path requiredThe infid, bhid or cpeid
-
seriesstring path requiredWhich history; see the operation's description
-
ispstring queryISP code from GET /isps. Optional when the key reaches exactly one ISP.
-
periodone of: "1hour", "4hours", "day", "week", "month", "year" queryLookback from now (default day). Use from/to instead for a past window
-
frominteger or string queryRange start: unix seconds or 'YYYY-MM-DD HH:MM:SS' UTC
-
tointeger or string queryRange end (default: now)
-
max_pointsinteger queryPoint budget (default 200, max 500); buckets are sized to stay under it
Response
Also available as CSV: add format=csv. Columns follow the field order below, with nested fields as dotted columns
(ap.name).
-
typestringdevice, backhaul or cpe; more types may be added
-
idinteger -
seriesstring -
interfacestring optionalDevice traffic: the interface
-
sourcestring optionalBackhaul capacity: the measurement shown
-
unitstring nullableHealth metrics: the value's unit. Other series carry the unit in their field names
-
fromdate-time -
todate-time -
bucket_secondsinteger -
point_countinteger -
pointsarray of objectsEach item: 2 fields
-
atdate-timeBucket start
-
chainstring optionalsignal only: the radio chain
-
Example
curl -H "Authorization: Bearer $SWIFTFOX_KEY" \
"https://api.swiftfox.net/v1/cpes/5678/history/series?isp=yourisp" Response (example data):
{
"type": "cpe",
"id": 5012,
"series": "traffic",
"unit": null,
"from": "2026-10-08T21:00:00Z",
"to": "2026-10-08T22:00:00Z",
"bucket_seconds": 1800,
"point_count": 2,
"points": [
{
"at": "2026-10-08T21:00:00Z",
"down_avg_mbps": 12.4,
"down_max_mbps": 41.7,
"up_avg_mbps": 1.1,
"up_max_mbps": 3.9,
"samples": 30
},
{
"at": "2026-10-08T21:30:00Z",
"down_avg_mbps": 18.9,
"down_max_mbps": 47.2,
"up_avg_mbps": 1.6,
"up_max_mbps": 4.4,
"samples": 30
}
]
}