Notifications
Manage your in-app notification feed and configure delivery preferences per event category.
List Notifications
Returns a paginated list of notifications for the authenticated tenant, ordered by most recent first.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit | integer | No | 50 | Max records to return |
offset | integer | No | 0 | Records to skip |
unread_only | boolean | No | false | When true, returns only unread notifications |
Example Request
curl "https://api.rymi.live/v1/notifications?limit=20&unread_only=true" \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"data": [
{
"id": "notif_abc123",
"tenant_id": "550e8400-...",
"event_category": "billing.low_balance",
"title": "Your balance is getting low",
"message": "Your account has about $8.50 in credits left. Add credits now to keep your agents online.",
"is_read": false,
"metadata": { "remaining_credits": 850, "amount_display": "$8.50" },
"created_at": "2026-04-01T14:30:00Z"
}
],
"total": 1,
"offset": 0,
"limit": 20
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
Mark All as Read
Marks all unread notifications as read for the authenticated tenant. No request body required.
Example Request
curl -X PUT https://api.rymi.live/v1/notifications/read-all \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"success": true
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
Mark Notification as Read
Marks a single notification as read. Idempotent: marking an already-read or unknown ID still returns 200.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Notification ID |
Example Request
curl -X PUT https://api.rymi.live/v1/notifications/notif_abc123/read \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"success": true
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
Delete Notifications
Removes a single notification from your in-app feed. Deletion is tenant-scoped and idempotent: an ID that doesn't exist (or belongs to another tenant) is a no-op that still returns 200.
Clears all read notifications from your in-app feed. The unread set is left untouched.
Response 200
{ "success": true }Delivery History
Lists per-channel delivery attempts joined to the source notification. Use it to debug why a notification didn't fire: each row shows the channel, status (queued / sent / failed), and the parent notification metadata.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max records |
offset | integer | 0 | Records to skip |
channel | string | — | Filter to in_app, email, sms, or webhook |
status | string | — | Filter by delivery status |
event_category | string | — | Filter by source event category |
Response 200
{
"data": [
{
"id": "del_...",
"notification_id": "notif_...",
"channel": "email",
"status": "sent",
"attempt_count": 1,
"last_error": null,
"notification": {
"id": "notif_...",
"event_category": "billing.low_balance",
"title": "Low Balance Warning",
"created_at": "..."
}
}
],
"total": 1,
"offset": 0,
"limit": 50
}Runtime Status
Returns the notification dispatcher's runtime state, which powers the dashboard's "notifications healthy?" indicator. Reports whether the delivery queue is enabled (queue_enabled) and a flat per-channel enabled boolean for each channel, plus any configuration warnings.
email readiness is gated on RESEND_API_KEY, sms on the Plivo env (PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, PLIVO_FROM_NUMBER), and queue_enabled / webhook on REDIS_URL. in_app is always enabled.
Response 200
{
"queue_enabled": true,
"channels": {
"in_app": true,
"email": true,
"sms": false,
"webhook": true
},
"preference_scope": "tenant_and_user",
"warnings": [
"PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, or PLIVO_FROM_NUMBER missing: SMS notifications are unavailable."
]
}Get Notification Preferences
Returns delivery preferences for each event category. Preferences control which channels (email, SMS, in-app, webhook) receive notifications.
Event Categories
Notification event categories are distinct from webhook events:
| Group | Categories |
|---|---|
| Billing | billing.low_balance, billing.balance_depleted, billing.payment_failed, billing.topup_confirmed, billing.invoice_ready |
| Calls | call.first_call, call.daily_summary, call.monthly_summary, call.volume_spike |
| Agents | agent.published, agent.failed, agent.degraded, agent.number_assigned |
| System | system.api_key_created, system.api_key_revoked, system.login_new_device, system.maintenance |
| Team | team.member_invited, team.member_joined |
| Other | auth.welcome, number.porting_complete |
Emails for billing.low_balance, billing.balance_depleted, agent.failed, and agent.degraded are rate-limited to one per category per 24 hours so a flapping condition can't flood an inbox.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
scope | enum | tenant | tenant returns the tenant-wide config; all returns tenant + per-user overrides merged |
Example Request
curl https://api.rymi.live/v1/notifications/preferences \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"data": [
{
"event_category": "billing.low_balance",
"email_enabled": true,
"sms_enabled": false,
"in_app_enabled": true,
"webhook_enabled": false
},
{
"event_category": "agent.failed",
"email_enabled": true,
"sms_enabled": false,
"in_app_enabled": true,
"webhook_enabled": true
}
],
"scope": "tenant"
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
Update Notification Preference
Update tenant-wide delivery channels for a specific event category. Creates the preference if it doesn't exist. Only tenant owners and admins can update tenant-wide preferences. Other members get a 403, but can still set personal overrides.
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
event_category | string | Yes | — | Event category to configure (e.g., billing.low_balance, agent.failed) |
email_enabled | boolean | No | Unchanged | Enable or disable email delivery |
sms_enabled | boolean | No | Unchanged | Enable or disable SMS delivery |
in_app_enabled | boolean | No | Unchanged | Enable or disable in-app notification |
webhook_enabled | boolean | No | Unchanged | Enable or disable webhook delivery |
Example Request
curl -X PUT https://api.rymi.live/v1/notifications/preferences \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_category": "billing.low_balance",
"email_enabled": true,
"sms_enabled": true,
"in_app_enabled": true,
"webhook_enabled": false
}'Response 200
{
"data": {
"event_category": "billing.low_balance",
"email_enabled": true,
"sms_enabled": true,
"in_app_enabled": true,
"webhook_enabled": false
}
}Errors
| Status | Meaning |
|---|---|
400 | Missing event_category |
401 | Missing or invalid API key |
403 | Caller is not a tenant owner or admin |
Personal Preferences
Per-user overrides on top of the tenant-wide preferences. Useful when one user wants email alerts while the rest of the team prefers in-app only. The body shape mirrors the tenant-scoped endpoint above.
GET Response 200
{
"data": [
{
"event_category": "billing.low_balance",
"email_enabled": true,
"sms_enabled": false,
"in_app_enabled": true,
"webhook_enabled": false
}
],
"scope": "user"
}Send Test Notification
Sends a test notification through your delivery pipeline so you can confirm each preference channel works. The body is optional; with no body, you get a simulated billing.low_balance notification routed through your normal preferences.
Request Body (optional)
| Field | Type | Description |
|---|---|---|
event_category | string | Category to simulate (default billing.low_balance) |
title | string | Override the notification title |
message | string | Override the notification message |
requested_channels | string[] | Restrict delivery to these channels (in_app, email, sms, webhook); preferences still apply |
force_channels | string[] | Deliver to these channels even if preferences disable them. Use it to test a channel before enabling it |
Example Request
curl -X POST https://api.rymi.live/v1/notifications/test \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "force_channels": ["email"] }'Response 200
{
"success": true,
"jobId": "job_notif_123"
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
500 | Notification service not configured |

