# Morning Fleet Digest

**Level:** 30 minutes · your first automation

**APIs used:** GET /api/v2/routers/, GET /api/v2/alerts/

---
Read https://cradlepoint.ericsson.com/llms.txt and the OpenAPI document at
https://cradlepoint.ericsson.com/developer/api/openapi.json so you know the
Ericsson NetCloud Manager (NCM) API.

Build me a Python script (standard library only) that produces a once-a-day
summary of my NCM fleet and posts it to a Slack incoming webhook.

The digest should contain:
- Total routers and the count in each state. Pull GET /api/v2/routers/ once
  with fields=id,name,state,state_updated_at and group the results client-side.
- Alerts from the last 24 hours, from GET /api/v2/alerts/ with
  created_at__gt=<ISO 8601 UTC timestamp, e.g. 2026-10-25T07:00:00Z>. Group
  them by `type`, sorted by count. On each type's line, show its count and up
  to 3 distinct `friendly_info` strings inline, each cut to 60 characters.
  (Don't send an epoch number; the API rejects it with 409.)
- Routers whose state changed in the last 24 hours: GET /api/v2/routers/ with
  state_updated_at__gt=<same ISO timestamp> and the same fields. List them
  newest first.

Requirements:
- Keep the Slack message under 20 lines: a bulleted summary, not JSON. Show at
  most the top 5 alert types and the 5 most recent state changes. Summarise
  the rest in one "+N more" line each; for alerts, give both the number of
  extra types and the number of extra alerts. If there were no alerts, say so
  in one line.
- Add a --dry-run flag that prints the message instead of posting it.
- v2 paths keep the trailing slash. Auth is four headers (X-CP-API-ID,
  X-CP-API-KEY, X-ECM-API-ID, X-ECM-API-KEY) read from the environment
  variables X_CP_API_ID, X_CP_API_KEY, X_ECM_API_ID and X_ECM_API_KEY. Read the
  webhook URL from SLACK_WEBHOOK_URL. Never hardcode any of them. Send a
  descriptive User-Agent header.
- Page every list call with limit=500 by following meta.next exactly as
  returned until it is null. Don't compute offsets yourself; alerts may page
  with a cursor rather than an offset. meta.next may point at a regional host
  such as www.us0.cradlepointecm.com. Send the same headers there, but only
  ever send credentials to https:// URLs on cradlepointecm.com or its
  subdomains.
- Don't follow redirects automatically; treat any 3xx response as an error (a
  301 usually means a missing trailing slash). HTTP clients re-send custom
  headers to wherever a redirect points, which would leak your keys.
- On HTTP 429, wait until X-RateLimit-Reset (a Unix epoch) if that header is
  present, otherwise back off exponentially (1s, 2s, 4s, 8s). Make at most
  5 attempts per request in total, and never wait more than 60s at a time.
  On any other HTTP error, stop with a clear message. Use a 30s request timeout.

Then give me a ready-to-use crontab line for 7am. Note that cron uses the
machine's local time zone, and that cron doesn't inherit my shell environment,
so source the variables from a file only I can read (chmod 600).
