Skip to content
Anlyon
Esc
↑↓navigate↵open⌘Jpreview
On this page

Notifications

Where Anlyon sends alerts about approvals, usage, billing and API keys, and how to configure the channels.

Anlyon sends alerts about approvals waiting for a decision, usage against your allowances, billing and API keys.

Channels

  • In-app. Shown in the console.
  • Email. Sent to the recipients you list. Early Beta Access includes it, up to 500 emails per workspace per UTC month. The standard Free plan that follows the beta sends no email alerts.
  • Webhook. A POST to an endpoint you configure.
  • Slack and Discord. Sent to a channel once you connect one.

Configure channels and recipients in the console under Settings → Notifications.

Notification types

Type Sent when
approval_requested An approval is waiting for a decision
quota_warning Usage of a monthly allowance crossed one of your alert thresholds
quota_exceeded A monthly allowance with a hard limit reached 100%
budget_alert Projected overage reached your alert target. The alert does not stop usage
payment_failed A payment did not go through
plan_upgraded, plan_downgraded The workspace plan changed
feature_enabled A feature was turned on for the workspace
api_key_expiring An API key is close to its expiry date
security_alert A security event needs attention
system_alert A system event needs attention
delivery_failure_spike Message deliveries are failing at an unusual rate

Usage alerts cover action executions and delivery messages. Each threshold alerts at most once per month for each of the two. When usage crosses several thresholds at once, only the highest one alerts.

Managing notifications

Listing and counting need notifications:read. Marking read and dismissing need notifications:write. Both scopes are in the default set. Read state belongs to the workspace, so a dismissed notification is gone for everyone.

# List. Add ?unreadOnly=true or ?limit=50 (1 to 100).
curl https://api.anlyon.com/api/v2/notifications \
  -H "Authorization: Bearer $ANLYON_API_KEY"

# Count the unread ones
curl https://api.anlyon.com/api/v2/notifications/unread-count \
  -H "Authorization: Bearer $ANLYON_API_KEY"

# Mark one as read
curl -X PATCH https://api.anlyon.com/api/v2/notifications/$NOTIFICATION_ID/read \
  -H "Authorization: Bearer $ANLYON_API_KEY"

# Mark all as read
curl -X PATCH https://api.anlyon.com/api/v2/notifications/read-all \
  -H "Authorization: Bearer $ANLYON_API_KEY"

# Delete one
curl -X DELETE https://api.anlyon.com/api/v2/notifications/$NOTIFICATION_ID \
  -H "Authorization: Bearer $ANLYON_API_KEY"

Your own preferences

Every member has their own preferences in each workspace. They hold the notification types you muted. A muted type is left out of your own list and unread count. It is still raised, still sent to email, Slack, Discord and the webhook, and still shown to every other member.

Reading them needs notifications:read. Changing them needs notifications:write. No role is needed. Both calls need a user, so they work from the console and from an OAuth connection. An API key has no user and gets 403 with the code USER_IDENTITY_REQUIRED.

# Read
curl https://api.anlyon.com/api/v2/notifications/preferences/me \
  -H "Authorization: Bearer $OAUTH_ACCESS_TOKEN"

# Replace the muted types. Send [] to mute nothing.
curl -X PATCH https://api.anlyon.com/api/v2/notifications/preferences/me \
  -H "Authorization: Bearer $OAUTH_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "mutedTypes": ["quota_warning"] }'
{
  "success": true,
  "data": {
    "mutedTypes": ["quota_warning"],
    "updatedAt": "2026-10-03T12:00:00.000Z"
  }
}

mutedTypes takes up to 12 notification types. In the console this is Settings > Notifications > My notifications.

Workspace preferences

These decide where the workspace’s alerts are sent and which types are raised, for every member.

What you do Scope Role, for a console session or an OAuth connection
Read workspace preferences notifications:read Any member
Update workspace preferences notifications:manage Admin or owner
Send the test webhook notifications:manage Admin or owner

notifications:manage is a privileged scope. No key gets it by default. An OAuth connection gets it from the Notification channels group, which is off unless you turn it on. In the console, a member sees these settings and an admin changes them.

OAuth tokens issued before 2026-10-03 do not carry notifications:write or notifications:manage. An existing OAuth client must re-consent before it can mark notifications read, dismiss them, or change notification settings. API keys created before that date that changed notification settings with notifications:read need the new scope.

Read

curl https://api.anlyon.com/api/v2/notifications/preferences \
  -H "Authorization: Bearer $ANLYON_API_KEY"
{
  "success": true,
  "data": {
    "emailEnabled": true,
    "webhookEnabled": false,
    "inAppEnabled": true,
    "slackEnabled": false,
    "discordEnabled": false,
    "emailRecipients": ["owner@example.com"],
    "webhookUrl": null,
    "hasWebhookSecret": false,
    "quotaAlertThresholds": [50, 75, 90, 100],
    "enabledTypes": ["approval_requested", "quota_warning", "quota_exceeded"]
  }
}

The webhook secret is never returned. hasWebhookSecret says whether one is set.

Update

Send the fields you want to change.

curl -X PATCH https://api.anlyon.com/api/v2/notifications/preferences \
  -H "Authorization: Bearer $ANLYON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "emailEnabled": true,
    "emailRecipients": ["oncall@example.com"],
    "quotaAlertThresholds": [60, 80, 95, 100]
  }'
Field Meaning
emailEnabled, webhookEnabled, inAppEnabled, slackEnabled, discordEnabled Turn a channel on or off
emailRecipients Up to 50 email addresses
webhookUrl, webhookSecret The webhook endpoint and the secret that signs its payloads. null clears either one
quotaAlertThresholds Up to 20 whole percentages from 0 to 100. The default is 50, 75, 90 and 100
enabledTypes The notification types to send

Webhook notifications

Configure the endpoint

curl -X PATCH https://api.anlyon.com/api/v2/notifications/preferences \
  -H "Authorization: Bearer $ANLYON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookEnabled": true,
    "webhookUrl": "https://your-app.com/webhooks/anlyon",
    "webhookSecret": "a-long-random-string"
  }'

Send a test payload to an endpoint before you save it:

curl -X POST https://api.anlyon.com/api/v2/notifications/preferences/test-webhook \
  -H "Authorization: Bearer $ANLYON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "webhookUrl": "https://your-app.com/webhooks/anlyon", "webhookSecret": "a-long-random-string" }'

Payload

{
  "event": "notification.quota_warning",
  "timestamp": "2026-10-01T15:00:00.000Z",
  "workspaceId": "2f8a1f72-7cf9-4fef-95e8-df9de5f2f5d0",
  "data": {
    "notificationId": "...",
    "type": "quota_warning",
    "priority": "medium",
    "title": "Action executions: 75% of monthly allowance used",
    "message": "7,500 of 10,000 used. ...",
    "metadata": { "dimension": "actionInvokes", "month": "2026-10", "threshold": 75, "percent": 75 }
  }
}

The request carries X-Anlyon-Event and X-Anlyon-Timestamp headers.

Signature

When a webhook secret is set, the request also carries X-Anlyon-Signature: sha256=<hex>. The value is the HMAC-SHA256 of the raw request body, keyed with your webhook secret. With no secret set, the request is unsigned.

This is a different format from the Anlyon-Signature header on signed deliveries. The SDK’s Receiver class verifies Anlyon-Signature and does not verify this header. Verify it yourself:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verifyNotification(rawBody: string, header: string | undefined, secret: string): boolean {
  if (!header) return false;
  const expected = `sha256=${createHmac('sha256', secret).update(rawBody).digest('hex')}`;
  const a = Buffer.from(expected);
  const b = Buffer.from(header);
  return a.length === b.length && timingSafeEqual(a, b);
}

The signature covers the body and nothing else. It carries no timestamp and no environment, so it does not bound replay age.

How it behaves

  • An alert reports. A budget_alert reports projected overage, and usage continues.
  • A notification webhook is one POST. Make your handler safe to call more than once, and do not rely on its arrival for anything that must happen.
  • The notification signature is separate from the delivery signature. It covers the body and names no environment. See Webhook signature verification.

Next steps

Was this page helpful?