API reference

CPEs

Customer radios: plan, signal, shaping and live health

List CPEs

GET /v1/cpes Try it

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

  • isp string query

    ISP code from GET /isps. Optional when the key reaches exactly one ISP.

  • ap integer query

    Restrict to CPEs associated to this access point (its infid)

  • site integer or string query

    Restrict to CPEs whose access point is at this site: site_id or site code

  • region integer query

    Restrict to CPEs whose access point is in this region: region_id from list_regions

  • plan integer query

    Restrict to one billing plan: a plan_id from a CPE's plan

  • disconnected boolean query

    true: only CPEs on disconnected accounts; false: only connected ones

  • account_number string query

    Exact customer account number (as shown on invoices)

  • q string query

    Substring match: MAC/IP always; account+device names only with pii scope

  • limit integer query

    Max rows (default 200, max 500)

  • cursor string query

    next_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.

  • count integer
  • next_cursor string nullable

    Pass as cursor to get the next page; null on the last page

  • cpes array of objects
    Each item: 16 fields
    • cpeid integer
    • mac string
    • ip string nullable
    • ap object nullable

      The access point it's associated to

      2 fields
      • infid integer
      • name string
    • site object nullable

      The access point's site

      3 fields
      • site_id integer
      • code string

        The ISP's short site code

      • name string
    • account_number string nullable

      The customer-visible account number, as on invoices

    • account_disconnected boolean nullable
    • signal_dbm number nullable
    • plan object nullable

      The billing plan and its configured rates

      4 fields
      • plan_id integer nullable

        Pass as plan to list_cpes

      • name string nullable
      • down_mbps number nullable
      • up_mbps number nullable
    • effective_rate_mbps object nullable

      What the shaper applies right now: the plan reduced by congestion multipliers or usage caps

      2 fields
      • down number nullable
      • up number nullable
    • monitored boolean
    • last_assoc date-time nullable
    • name string

      The subscriber's name with the pii scope; otherwise 'CPE <mac> (account <number>)'

    • account_name string nullable optional

      pii scope only

    • description string nullable optional

      pii scope only

    • discovered_name string nullable optional

      pii 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

GET /v1/cpes/{cpeid} Try it

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

Response

  • cpeid integer
  • mac string
  • ip string nullable
  • ap object nullable

    The access point it's associated to

    2 fields
    • infid integer
    • name string
  • site object nullable

    The access point's site

    3 fields
    • site_id integer
    • code string

      The ISP's short site code

    • name string
  • account_number string nullable

    The customer-visible account number, as on invoices

  • account_disconnected boolean nullable
  • signal_dbm number nullable
  • plan object nullable

    The billing plan and its configured rates

    4 fields
    • plan_id integer nullable

      Pass as plan to list_cpes

    • name string nullable
    • down_mbps number nullable
    • up_mbps number nullable
  • effective_rate_mbps object nullable

    What the shaper applies right now: the plan reduced by congestion multipliers or usage caps

    2 fields
    • down number nullable
    • up number nullable
  • monitored boolean
  • last_assoc date-time nullable
  • name string

    The subscriber's name with the pii scope; otherwise 'CPE <mac> (account <number>)'

  • account_name string nullable optional

    pii scope only

  • description string nullable optional

    pii scope only

  • discovered_name string nullable optional

    pii scope only: the name the radio reports

  • health array of objects
    Each item: 10 fields
    • metric string
    • sub string optional

      Which value of a metric with several on one entity (a radio chain, a vulnerability)

    • description string optional
    • value number nullable

      Latest collected value

    • unit string optional
    • state string

      Threshold state name for the value, e.g. Good, Warning, Down; Inactive = the metric has no thresholds set

    • severity one of: "ok", "info", "warning", "outage", "critical" nullable

      ok, info, warning, outage or critical for the state's level; null when the metric has no thresholds

    • value_ttl_seconds integer nullable

      Seconds until the value is considered stale; -1 = no expiry set

    • issue object nullable
      6 fields
      • details string
      • severity one of: "ok", "info", "warning", "outage", "critical"

        ok while recovering, otherwise info, warning, outage or critical

      • since date-time nullable

        When the issue started

      • status one of: "active", "pending", "recovering"
      • recovered_at date-time nullable

        recovering only: when the metric went back to good

      • resolves_at date-time nullable

        recovering only: when the issue clears if it stays good

    • has_history boolean optional

      Devices: 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

GET /v1/cpes/{cpeid}/health Try it

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

  • cpeid integer path required

    infid / bhid / cpeid

  • isp string query

    ISP 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).

  • type string

    device, backhaul or cpe; more types may be added

  • id integer
  • metrics array of objects
    Each item: 10 fields
    • metric string
    • sub string optional

      Which value of a metric with several on one entity (a radio chain, a vulnerability)

    • description string optional
    • value number nullable

      Latest collected value

    • unit string optional
    • state string

      Threshold state name for the value, e.g. Good, Warning, Down; Inactive = the metric has no thresholds set

    • severity one of: "ok", "info", "warning", "outage", "critical" nullable

      ok, info, warning, outage or critical for the state's level; null when the metric has no thresholds

    • value_ttl_seconds integer nullable

      Seconds until the value is considered stale; -1 = no expiry set

    • issue object nullable
      6 fields
      • details string
      • severity one of: "ok", "info", "warning", "outage", "critical"

        ok while recovering, otherwise info, warning, outage or critical

      • since date-time nullable

        When the issue started

      • status one of: "active", "pending", "recovering"
      • recovered_at date-time nullable

        recovering only: when the metric went back to good

      • resolves_at date-time nullable

        recovering only: when the issue clears if it stays good

    • has_history boolean optional

      Devices: 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

GET /v1/cpes/{cpeid}/history/{series} Try it

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

  • cpeid integer path required

    The infid, bhid or cpeid

  • series string path required

    Which history; see the operation's description

  • isp string query

    ISP code from GET /isps. Optional when the key reaches exactly one ISP.

  • period one of: "1hour", "4hours", "day", "week", "month", "year" query

    Lookback from now (default day). Use from/to instead for a past window

  • from integer or string query

    Range start: unix seconds or 'YYYY-MM-DD HH:MM:SS' UTC

  • to integer or string query

    Range end (default: now)

  • max_points integer query

    Point 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).

  • type string

    device, backhaul or cpe; more types may be added

  • id integer
  • series string
  • interface string optional

    Device traffic: the interface

  • source string optional

    Backhaul capacity: the measurement shown

  • unit string nullable

    Health metrics: the value's unit. Other series carry the unit in their field names

  • from date-time
  • to date-time
  • bucket_seconds integer
  • point_count integer
  • points array of objects
    Each item: 2 fields
    • at date-time

      Bucket start

    • chain string optional

      signal 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
    }
  ]
}