Notifications
Channel + subscription model for delivering ZopNight events to Slack, Teams, Google Chat, and email, with cost-anomaly, budget, and resource-event subscriptions.
The notification system lets you receive alerts when resources are started, stopped, actions fail, overrides fire, retries are exhausted, or budget thresholds are crossed. Notifications can be delivered to Slack, Microsoft Teams, Google Chat, or email.
The system is built around two concepts: channels define where notifications go (a Slack channel, a Teams or Google Chat webhook, or a generic webhook), and subscriptions define which events trigger a notification on a given channel, optionally scoped to a specific resource, resource group, or cloud account.
Supported Channels
| Channel | platform | Configuration fields |
|---|---|---|
| Slack | slack | slackBotToken, slackChannelId, slackSigningSecret |
| Microsoft Teams | teams | webhookUrl (incoming webhook URL) |
| Google Chat | gchat | webhookUrl (incoming webhook URL) |
| Webhook | webhook | webhookUrl (any HTTPS endpoint that accepts a POST) |
Email is not a channel type. Transactional emails are controlled with Email Preferences.
Legacy Notifications (Deprecated)
List Legacy Notifications
/notifications List all legacy notification configurations.
Create Legacy Notification
/notifications Create a legacy notification configuration.
curl -X POST https://api.zop.dev/notifications \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "channel": "slack", "webhookUrl": "https://hooks.slack.com/services/T00/B00/xxxx", "notifyOnStart": true, "notifyOnStop": true, "notifyOnFailure": true, "notifyOnOverride": false }'{ "data": { "id": "ntf_abc123", "channel": "slack", "webhookUrl": "https://hooks.slack.com/services/T00/B00/xxxx", "notifyOnStart": true, "notifyOnStop": true, "notifyOnFailure": true, "notifyOnOverride": false, "createdAt": "2025-01-15T10:30:00Z", "updatedAt": "2025-01-15T10:30:00Z" }}Update Legacy Notification
/notifications/{notificationID} Update a legacy notification configuration.
curl -X PUT https://api.zop.dev/notifications/ntf_abc123 \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "notifyOnOverride": true }'Delete Legacy Notification
/notifications/{notificationID} Remove a legacy notification configuration.
Notification Channels
Channels represent a delivery destination such as a Slack channel, a Teams channel, or a webhook. Create a channel first, then attach subscriptions to it.
List Channels
/notifications/channels List all notification channels for the organization.
curl https://api.zop.dev/notifications/channels \ -H "Authorization: Bearer <token>"Returns {"data": [...]} with one entry per channel. Each entry carries the channel’s id,
which you pass as channelId when creating subscriptions.
Create Channel
/notifications/channels Create a new notification channel.
curl -X POST https://api.zop.dev/notifications/channels \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "name": "Engineering Alerts", "platform": "slack", "slackBotToken": "xoxb-...", "slackChannelId": "C0123456789", "slackSigningSecret": "..." }'curl -X POST https://api.zop.dev/notifications/channels \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "name": "Infra Alerts", "platform": "teams", "webhookUrl": "https://example.webhook.office.com/webhookb2/..." }'Update Channel
/notifications/channels/{channelID} Update an existing notification channel. Takes the same fields as create.
curl -X PUT https://api.zop.dev/notifications/channels/<channelId> \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "name": "Infra Alerts", "platform": "teams", "webhookUrl": "https://example.webhook.office.com/webhookb2/new..." }'Delete Channel
/notifications/channels/{channelID} Delete a notification channel and all its subscriptions.
curl -X DELETE https://api.zop.dev/notifications/channels/<channelId> \ -H "Authorization: Bearer <token>"Notification Subscriptions
Subscriptions bind a channel to one or more event types. You can scope a subscription to the entire organization, a specific cloud account, a resource group, or an individual resource.
Event Types
The table below lists common event keys. It is not the complete catalogue: more keys exist (for
example remediation approvals, billing sync, and override expiry). GET /notifications/event-types
returns the authoritative list.
| Event Key | Display Name | Triggered When |
|---|---|---|
resource.started | Resource Started | A resource is successfully started by the executor |
resource.stopped | Resource Stopped | A resource is successfully stopped by the executor |
resource.failed | Action Failed | A start or stop action fails during execution |
resource.override | Override Triggered | An override is created for a resource or group |
resource.retry_exhausted | Retry Exhausted | All retry attempts for an action have been exhausted |
budget.warning | Budget Warning | Spending approaches a configured budget threshold |
budget.exceeded | Budget Exceeded | Spending exceeds a configured budget threshold |
cost.anomaly.warning | Cost Anomaly (Warning) | Org-level cost exceeds 7-day baseline by 30% |
cost.anomaly.critical | Cost Anomaly (Critical) | Org-level cost exceeds 7-day baseline by 100% |
cost.anomaly.emergency | Cost Anomaly (Emergency) | Org-level cost exceeds 7-day baseline by 500% |
cost.anomaly.cloud_account.* | Cloud Account Anomaly | A cloud account’s cost spikes beyond baseline, each * expands to warning, critical, emergency |
cost.anomaly.resource_group.* | Resource Group Anomaly | A resource group’s cost spikes beyond baseline, each * expands to warning, critical, emergency |
cost.anomaly.resource.* | Resource Anomaly | A single resource’s cost spikes beyond baseline, each * expands to warning, critical, emergency |
cost.anomaly.team.* | Team Anomaly | A team’s attributed cost spikes beyond baseline, each * expands to warning, critical, emergency |
Scope Types
| Scope Type | Scope ID | Description |
|---|---|---|
org | (none) | Matches all events across the organization |
cloud_account | Cloud account ID | Matches events for resources in a specific cloud account |
resource_group | Resource group ID | Matches events for resources in a specific group |
resource | Resource UID | Matches events for a single resource |
team | Team ID | Matches events for resources attributed to a specific team |
List Subscriptions
/notifications/subscriptions List all notification subscriptions.
curl https://api.zop.dev/notifications/subscriptions \ -H "Authorization: Bearer <token>"{ "data": [ { "id": "sub_x1y2z3", "channelId": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a", "eventType": "resource.stopped", "scopeType": "org", "scopeId": "", "enabled": true, "createdAt": "2025-06-01T09:15:00Z", "updatedAt": "2025-06-01T09:15:00Z" } ]}Create Subscription
/notifications/subscriptions Subscribe a channel to an event type.
curl -X POST https://api.zop.dev/notifications/subscriptions \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "channelId": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a", "eventType": "resource.failed", "scopeType": "cloud_account", "scopeId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "enabled": true }'{ "data": { "id": "sub_f4g5h6", "channelId": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a", "eventType": "resource.failed", "scopeType": "cloud_account", "scopeId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "enabled": true, "createdAt": "2025-06-02T11:00:00Z", "updatedAt": "2025-06-02T11:00:00Z" }}Update Subscription
/notifications/subscriptions/{subID} Update an existing subscription.
curl -X PUT https://api.zop.dev/notifications/subscriptions/sub_f4g5h6 \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "enabled": false }'Delete Subscription
/notifications/subscriptions/{subID} Delete a notification subscription.
curl -X DELETE https://api.zop.dev/notifications/subscriptions/sub_f4g5h6 \ -H "Authorization: Bearer <token>"Bulk Create / Update Subscriptions
/notifications/subscriptions/bulk Create or update multiple subscriptions in a single request. Existing subscriptions matched by channelId + eventType + scope are updated; otherwise new ones are created.
curl -X POST https://api.zop.dev/notifications/subscriptions/bulk \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "subscriptions": [ { "channelId": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a", "eventType": "resource.started", "scopeType": "org", "scopeId": "", "enabled": true }, { "channelId": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a", "eventType": "resource.stopped", "scopeType": "org", "scopeId": "", "enabled": true }, { "channelId": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a", "eventType": "budget.exceeded", "scopeType": "cloud_account", "scopeId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "enabled": true } ] }'{ "data": { "status": "ok" }}Event Types
/notifications/event-types List all available event types that can be used in subscriptions. This is the authoritative catalogue.
curl https://api.zop.dev/notifications/event-types \ -H "Authorization: Bearer <token>"{ "data": [ { "key": "resource.started", "label": "Resource Started", "category": "resource" }, { "key": "resource.failed", "label": "Action Failed", "category": "resource" }, { "key": "budget.exceeded", "label": "Budget Exceeded", "category": "budget" }, { "key": "cost.anomaly.critical", "label": "Cost Anomaly (Critical)", "category": "cost_anomaly" } ]}Email Preferences
Email preferences are organization-level opt-outs for ZopNight’s transactional emails, one per event key. They are independent of channel subscriptions.
List Email Preferences
/notifications/email-preferences List the email preferences for every event key.
curl https://api.zop.dev/notifications/email-preferences \ -H "Authorization: Bearer <token>"Update Email Preference
/notifications/email-preferences/{eventKey} Enable or disable emails for a specific event key.
curl -X PUT https://api.zop.dev/notifications/email-preferences/resource.failed \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "enabled": false }'{ "data": { "orgId": "3f6c2a9e-8b1d-4c7e-9f2a-1d5e6b7c8a90", "eventKey": "resource.failed", "enabled": false }}Share Recommendation
Send a cost-saving recommendation to one or more notification channels so that team members who may not use the dashboard directly can act on it.
/notifications/share/recommendation/{recID} Share a recommendation by email or through a notification channel.
curl -X POST https://api.zop.dev/notifications/share/recommendation/<recId> \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "channel": "slack", "targets": ["6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"], "message": "This EC2 instance has been idle for 14 days. Consider stopping or downsizing." }'channel is email, slack, teams, gchat or webhook. targets holds email addresses for
email, or channel IDs otherwise. message is optional.