alerts
Project history, activity across the account, pending deliveries, last firing, and the account spend alert.
An alert is an event that already fired — a budget rule, threshold, or the account spend alert crossed its condition, and Solwyn tried to deliver it. alerts list, show, and export read that history, each event carrying a delivery receipt per channel leg. Rules themselves are configured elsewhere: project rules under budget rule, and the single account-wide spend threshold under alerts account, documented on this page.
Project history accepts either credential. Anything account-scoped — --account history and every alerts account subcommand — requires a user login; a project key exits 3 before any request with jwt_required.
alerts activity and pending
solwyn --json alerts activity --range 7d --event-type fired --all
solwyn alerts activity --cursor CURSOR
solwyn --json alerts pending --all --fail-if-openBoth require JWT at any account role and no selected project. activity reads all projects plus account scope, unlike alerts list --account, which reads account-scope history only. It accepts --range 7d|30d|90d (default 30d), --event-type fired|snoozed|unsnoozed|paused|resumed, --cursor, and --all; it does not accept paired custom-window flags.
pending lists operationally open pending/retrying deliveries, regardless of normal event retention, with per-channel attempts and next_attempt_at. It accepts --cursor, --all, and --fail-if-open; it has no range filter. Default listing exits 0. With --fail-if-open, data prints first, then nonempty listed open deliveries produce open_alert_deliveries and exit 1. Use --all for a complete health check.
Both use 25-event cursor pages. Outputs are solwyn.alerts.activity.v1 and solwyn.alerts.pending.v1; exits are 0 success, 1 API/invalid response (also open-delivery gate), 2 usage, 3 auth. CLI all-page aggregation fails without partial success stdout if a later page fails. MCP list_alert_activity and list_open_alert_deliveries retain bounded pagination and first unread cursors on errors.
Choosing a window
list, show, and export share one set of window flags. All validation happens locally, before a credential is resolved or a request is sent; a bad value exits 2 with invalid_alert_query.
| Option | Type | Default | Purpose |
|---|---|---|---|
--account | boolean | false | Read account-scope history instead of the project's. Requires JWT. |
--range | 7d | 30d | 90d | 30d | Look-back window. |
--from, --to | ISO 8601, timezone-aware | none | An explicit window. Both must be supplied together, and --to must be later than --from. Replaces --range. |
--rule-type | string | none | Filter by rule type, for example scoped_budget or budget_threshold. Not on export. |
--scope | string | none | Filter by the rule's scope in metadata, for example tag. Not on export. |
Retention is tier-bound. When the API narrows the window you asked for, the CLI says so on stderr — Retention clamped window: … (requested …) — and the JSON window object reports both the requested and effective bounds with retention_clamped: true.
alerts list
solwyn --project <project_id> alerts list [window flags] [--failed-only] [--cursor <c>] [--all]| Option | Type | Default | Purpose |
|---|---|---|---|
--failed-only | boolean | false | Keep only events whose delivery rollup is partial or failed. Applied locally after fetching. |
--cursor | string | none | Start from a page cursor printed by a previous run. |
--all | boolean | false | Walk every page. The API returns at most 25 events per page. |
| Contract | |
|---|---|
| Auth | any; --account requires JWT |
| Exit codes | 0 success · 1 generic/API · 2 usage · 3 auth · 5 not found |
| JSON schema | solwyn.alerts.v1 |
$ solwyn --project proj_0123456789abcdef01234567 alerts list --range 7d
id emitted at rule type event delivery
evt_9c1e 2026-09-01T00:00:00+00:00 scoped_budget triggered partialThe delivery column is the worst leg across every channel the event was routed to: pending, retrying, processed, delivered, partial, or failed. Without --all, one page is fetched; when more remain, the table view prints the next cursor to stderr so you can continue with --cursor.
The JSON payload carries every leg:
{
"schema": "solwyn.alerts.v1",
"events": [
{
"id": "evt_9c1e",
"project_id": "proj_0123456789abcdef01234567",
"scope": "project",
"rule_key": "rule-one",
"emitted_at": "2026-09-01T00:00:00Z",
"event_type": "triggered",
"rule_type": "scoped_budget",
"value_at_event": 12.5,
"threshold_at_event": 10.0,
"period_key": null,
"metadata_json": {"scope": "tag"},
"delivery": {
"status": "partial",
"attempt_count": 3,
"legs": [
{"leg_key": "slack:one", "channel_type": "slack", "channel_name": "Operations",
"status": "failed", "attempt_count": 3, "delivered_at": null, "error": "Channel unavailable"}
]
}
}
],
"next_cursor": null,
"window": {"requested_from": "…", "requested_to": "…", "effective_from": "…", "effective_to": "…", "retention_clamped": false}
}Pretty-printed and abridged here; the CLI emits one line. value_at_event and threshold_at_event are the quantity the rule measured and the limit it crossed — dollars for a budget rule, never content.
alerts show
Find one event by id within the window and list its delivery legs.
solwyn --project <project_id> alerts show <event_id> [window flags]| Contract | |
|---|---|
| Auth | any; --account requires JWT |
| Exit codes | 0 success · 1 generic/API · 2 usage · 3 auth · 5 not found in window |
| JSON schema | solwyn.alerts.v1 |
$ solwyn --project proj_0123456789abcdef01234567 alerts show evt_9c1e
channel name status attempts delivered at error
slack Operations failed 3 — Channel unavailableThe table has one row per leg, not per event, and a summary line — Event evt_9c1e; delivery: partial. — goes to stderr. The CLI walks list pages inside the window and matches the id locally, so an event outside the window exits 5 with the hint to widen --range or check --account. The JSON payload is the single event object.
alerts export
Stream history as CSV or newline-delimited JSON to stdout. Production and above.
solwyn --project <project_id> alerts export [--format csv|json] [--account] [--range …] [--from … --to …]| Option | Type | Default | Purpose |
|---|---|---|---|
--format | csv | json | csv | json is NDJSON, one event per line. Anything else is a usage error. |
| Contract | |
|---|---|
| Auth | any; --account requires JWT |
| Exit codes | 0 success · 1 generic/API · 2 usage · 3 auth · 5 not found |
| JSON schema | stream (CSV or NDJSON), not an envelope |
$ solwyn --project proj_0123456789abcdef01234567 alerts export --range 90d > alerts.csv
Alert exports exclude delivery receipts.The stream is copied byte-for-byte to stdout — redirect it to a file. Window headers the API returns (X-Solwyn-Effective-From, X-Solwyn-Retention-Clamped, X-Solwyn-Truncated, and their siblings) are echoed on stderr. --rule-type and --scope do not apply to export.
alerts account
The account spend alert is one account-wide dollar threshold, at most one per account, that fires an alert when the account's combined spend crosses it. It is a notification, not a cap: it never blocks a call. Production and above; set, delete, snooze, and unsnooze require the account owner, while show and preview are open to any member.
| Contract | |
|---|---|
| Auth | JWT; owner for mutations |
| Exit codes | 0 success · 1 generic/API · 2 usage · 3 auth · 5 not found |
| JSON schema | solwyn.alerts.account.v1 |
| Subcommand | Purpose |
|---|---|
alerts account show | Show the configured alert. Exits 5 when none is configured. |
alerts account set --spend <usd> [--channel <id>]... [--enabled|--disabled] | Create or update it. --spend must be a positive amount. Repeating --channel replaces the channel list; omitting it preserves the existing one. |
alerts account delete | Delete it. Succeeds when already absent. No confirmation prompt. |
alerts account snooze --until <when> | Silence it until an absolute timezone-aware timestamp, or a relative +30m, +2h, +7d. |
alerts account unsnooze | Clear the snooze. |
alerts account preview [--channel <id>]... | Dry-run the routing for a channel list without saving anything. |
$ solwyn alerts account set --spend 500 --channel ch_one
field value
account_id acct_one
spend_threshold_usd 500.0
enabled True
channel_ids ["ch_one"]
snoozed_until —
routing {"will_send": true, "email": "ops@example.com", "channels": [{"id": "ch_one", "name": "Ops"}], "source": "override", "muted": null}
created_at 2026-09-01T00:00:00Z
updated_at 2026-09-01T00:00:00ZThe routing object answers "will this actually reach anyone?": will_send, the resolved email, the resolved channels, where the routing came from (override, project_default, or account_default), and — when it would be silenced — muted.reason of severity_floor, event_filter, or email_off. preview returns that object alone, which makes it the first thing to run when an alert never arrived. An unknown channel id in set exits 2 and names the offending ids.
A naive timestamp in --until is a usage error; +2h-style durations are always safe.
Last fired on account alerts
solwyn --json alerts account show --with-last-firedJWT reads can opt into --with-last-fired. The read-only latest-events POST returns the last firing and latest lifecycle event, merging current-account-ID and legacy account-spend history by timestamp and event ID. Core's default 30-day window and plan retention apply; null means no matching retained history. Without the flag, no extra request is made. MCP get_account_alert(with_last_fired=true) exposes the same read in both profiles; project rules support the same option.
Related
- Alerts & notifications — the six rule types and the dashboard's alert feed
budget rule— create, pause, and snooze the project rules that produce these eventsnotifications— the channels and per-project routing events are delivered throughaccount alert-email— where alert email goes