Skip to main content

Overview

The Royalti.io notification system keeps users informed about important events across your workspace through multiple delivery channels. This guide covers how to retrieve, manage, and customize notification preferences for your users.

Why Use Notifications?

  • Stay Informed: Get real-time updates about critical events in your workspace
  • Multi-Channel Delivery: Receive notifications via in-app, email, and push notifications
  • Customizable: Control which events trigger notifications and through which channels
  • Centralized: All notifications are accessible through a unified API
  • Actionable: Notifications link directly to relevant resources for quick action

Notification Channels

Royalti.io supports three notification channels:
ChannelDescriptionUse Case
IN_APPIn-app notifications displayed in the Royalti dashboardReal-time updates while users are actively working
EMAILEmail notifications sent to user’s registered email addressImportant updates that require user attention
PUSHPush notifications sent to mobile devicesUrgent updates when users are away from the dashboard
Users can customize which channels they want to receive for each notification type through their preferences.

Notification Types

Royalti.io generates notifications for events across multiple categories:

Royalty File Processing

Event TypeDescriptionDefault Channels
ROYALTY_FILE_UPLOADEDRoyalty file uploaded successfullyIN_APP
ROYALTY_FILE_PROCESSEDRoyalty file processing completedIN_APP, EMAIL
ROYALTY_FILE_PROCESSING_FAILEDRoyalty file processing failedIN_APP, EMAIL
ROYALTY_FILE_DELETEDRoyalty file deletedIN_APP

User & Collaboration Events

Event TypeDescriptionDefault Channels
USER_CREATEDNew user added to workspaceIN_APP
USER_UPDATEDUser profile or permissions modifiedIN_APP
USER_DEACTIVATEDUser account deactivatedIN_APP
USER_DELETEDUser removed from workspaceIN_APP, EMAIL
USER_INVITATION_SENTUser invited to workspaceIN_APP, EMAIL
USER_ADDED_TO_SPLITUser added to revenue splitIN_APP, EMAIL
USER_REMOVED_FROM_SPLITUser removed from revenue splitIN_APP

Artist Management

Event TypeDescriptionDefault Channels
ARTIST_CREATEDNew artist profile createdIN_APP
ARTIST_UPDATEDArtist profile modifiedIN_APP
ARTIST_DEACTIVATEDArtist profile deactivatedIN_APP
ARTIST_DELETEDArtist profile removedIN_APP, EMAIL
ARTIST_AUTO_CREATEDArtist automatically created during processingIN_APP
ARTIST_RESOLUTION_FAILEDFailed to resolve artist informationIN_APP

Catalog Management (Tracks & Releases)

Event TypeDescriptionDefault Channels
ASSET_CREATEDNew asset (track) addedIN_APP
ASSET_UPDATEDAsset modifiedIN_APP
ASSET_DEACTIVATEDAsset deactivatedIN_APP
ASSET_DELETEDAsset removedIN_APP, EMAIL
PRODUCT_CREATEDNew product (album/release) createdIN_APP
PRODUCT_UPDATEDProduct modifiedIN_APP
PRODUCT_DEACTIVATEDProduct deactivatedIN_APP
PRODUCT_DELETEDProduct removedIN_APP, EMAIL

Financial & Payment Events

Event TypeDescriptionDefault Channels
PAYMENT_REQUEST_SENTPayment request createdIN_APP, EMAIL
PAYMENT_REQUEST_APPROVEDPayment request approvedIN_APP, EMAIL
PAYMENT_REQUEST_REJECTEDPayment request rejectedIN_APP, EMAIL
PAYMENT_MADE_PROCESSINGPayment being processedIN_APP
PAYMENT_MADE_COMPLETEDPayment successfully completedIN_APP, EMAIL
PAYMENT_MADE_FAILEDPayment failedIN_APP, EMAIL
PAYMENT_PROCESSINGPayment in processing stateIN_APP
PAYMENT_COMPLETEDPayment completedIN_APP
PAYMENT_DELETEDPayment record deletedIN_APP
REVENUE_CREATEDRevenue entry createdIN_APP
REVENUE_UPDATEDRevenue entry modifiedIN_APP
REVENUE_DELETEDRevenue entry deletedIN_APP, EMAIL
EXPENSE_CREATEDExpense entry createdIN_APP
EXPENSE_UPDATEDExpense entry modifiedIN_APP
EXPENSE_DELETEDExpense entry deletedIN_APP, EMAIL

Billing & Subscription

Event TypeDescriptionDefault Channels
BILLING_SUCCESSBilling operation successfulIN_APP, EMAIL
BILLING_ERRORBilling operation failedIN_APP, EMAIL
BILLING_WARNINGBilling warning or issueIN_APP, EMAIL

Release Management & Distribution

Event TypeDescriptionDefault Channels
RELEASE_SUBMITTEDRelease submitted for reviewIN_APP, EMAIL
RELEASE_APPROVEDRelease approved for distributionIN_APP, EMAIL
RELEASE_REJECTEDRelease rejectedIN_APP, EMAIL
RELEASE_FEEDBACK_ADDEDFeedback added to releaseIN_APP, EMAIL
RELEASE_AUTO_CREATEDRelease automatically createdIN_APP
RELEASE_AUTO_CREATION_FAILEDAuto-creation of release failedIN_APP
RELEASE_UPDATED_MANAGEMENTRelease updated by managementIN_APP
RELEASE_CREATEDRelease createdIN_APP
RELEASE_DELETEDRelease deletedIN_APP
RELEASE_ERRORRelease processing errorIN_APP, EMAIL
RELEASE_STATUS_REVERTEDRelease status revertedIN_APP

File Processing

Event TypeDescriptionDefault Channels
FILE_PROCESSING_STARTEDFile processing initiatedIN_APP
FILE_PROCESSING_COMPLETEFile processing completedIN_APP
FILE_PROCESSING_FAILEDFile processing failedIN_APP, EMAIL

DDEX Provider Delivery

Event TypeDescriptionDefault Channels
PROVIDER_DELIVERY_INITIATEDDelivery to provider startedIN_APP
PROVIDER_DELIVERY_COMPLETEDDelivery to provider completedIN_APP, EMAIL
PROVIDER_DELIVERY_FAILEDDelivery to provider failedIN_APP, EMAIL
PROVIDER_DELIVERY_ACKNOWLEDGEDProvider acknowledged deliveryIN_APP
PROVIDER_STATUS_UPDATEProvider status update receivedIN_APP

Default Notification Configuration

When users first sign up or are invited to a workspace, Royalti.io automatically creates smart default notification preferences based on event priority and importance.

Default Settings Overview

Philosophy: In-app notifications for all events, email only for high-priority actions that require attention or represent critical workflow changes.

Disabled by Default

These low-priority CRUD events are disabled by default to reduce notification noise:
Event TypeReason for Disabling
ARTIST_CREATEDRoutine catalog management
ARTIST_UPDATEDFrequent updates, low urgency
ASSET_CREATEDHigh-volume event in active workspaces
ASSET_UPDATEDFrequent metadata changes
PRODUCT_CREATEDRoutine release management
EXPENSE_CREATEDFinancial data entry
EXPENSE_UPDATEDRoutine financial updates
REVENUE_CREATEDFinancial data entry
REVENUE_UPDATEDRoutine financial updates
PAYMENT_PROCESSINGIntermediate state, not actionable
PAYMENT_DELETEDAdministrative action, low urgency
Note: Users can re-enable these through their notification preferences if needed.

Email-Enabled by Default

These high-priority events include both in-app and email notifications by default: Royalty File Processing (Critical)
  • ROYALTY_FILE_PROCESSED - Completion requires review
  • ROYALTY_FILE_PROCESSING_FAILED - Requires immediate attention
Payment Requests (Action Required)
  • PAYMENT_REQUEST_SENT - Approval workflow initiated
  • PAYMENT_REQUEST_APPROVED - Financial decision confirmed
  • PAYMENT_REQUEST_REJECTED - Requires follow-up action
User Collaboration (Important)
  • USER_INVITATION_SENT - New team member notification
  • USER_ADDED_TO_SPLIT - Revenue sharing change
Deletions (Data Loss Awareness)
  • ARTIST_DELETED, ASSET_DELETED, PRODUCT_DELETED
  • EXPENSE_DELETED, REVENUE_DELETED, USER_DELETED
Release Management (Workflow-Critical)
  • RELEASE_SUBMITTED - Distribution workflow step
  • RELEASE_APPROVED, RELEASE_REJECTED - Decision notification
  • RELEASE_FEEDBACK_ADDED - Requires review

In-App Only by Default

All other notification types use in-app notifications only by default. Users receive these notifications in the dashboard but not via email unless they explicitly enable email delivery.

Customizing Defaults

Admin Note: Default preferences are automatically initialized when:
  • A new user signs up
  • A user accepts an invitation
  • A user logs in for the first time
Users can customize their preferences at any time through the notification preferences API. Best Practice: Encourage users to review their notification preferences after joining to ensure they receive the right balance of updates for their workflow.

Quick Start

1

Get Notifications

Retrieve notifications for the authenticated user:
curl -X GET "https://api.royalti.io/notifications?page=1&pageSize=20" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "status": "success",
  "message": "Notifications retrieved successfully",
  "data": {
    "notifications": [
      {
        "id": "dd12f9bc-3ed5-453e-a929-69b6d5267f4b",
        "type": "ASSET_CREATED",
        "title": "Track Created",
        "content": "Track \"Midnight City\" has been created.",
        "resourceType": "Asset",
        "resourceId": "0b13028e-74a9-4d1d-bb9f-12cef06ff236",
        "actionUrl": "/assets/0b13028e-74a9-4d1d-bb9f-12cef06ff236",
        "isRead": false,
        "isImportant": false,
        "createdAt": "2025-08-21T11:42:37.717Z"
      }
    ],
    "total": 34,
    "page": 1,
    "pageSize": 20,
    "totalPages": 2
  }
}
2

Check Unread Count

Get the count of unread notifications:
curl -X GET "https://api.royalti.io/notifications/unread/count" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "status": "success",
  "message": "Unread notification count retrieved successfully",
  "data": {
    "count": 5
  }
}
3

Mark as Read

Mark a specific notification as read:
curl -X PATCH "https://api.royalti.io/notifications/dd12f9bc-3ed5-453e-a929-69b6d5267f4b/read" \
  -H "Authorization: Bearer YOUR_TOKEN"
Or mark all notifications as read:
curl -X PATCH "https://api.royalti.io/notifications/mark-all-read" \
  -H "Authorization: Bearer YOUR_TOKEN"
4

Configure Preferences

Customize notification preferences:
curl -X PUT "https://api.royalti.io/notifications/preferences" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "preferences": [
      {
        "notificationType": "PAYMENT_MADE_COMPLETED",
        "channels": ["EMAIL", "IN_APP", "PUSH"],
        "isEnabled": true
      },
      {
        "notificationType": "ASSET_CREATED",
        "channels": ["IN_APP"],
        "isEnabled": true
      }
    ]
  }'

Notification Structure

All notifications follow a standardized structure:
{
  "id": "dd12f9bc-3ed5-453e-a929-69b6d5267f4b",
  "type": "PAYMENT_MADE_COMPLETED",
  "title": "Payment Completed",
  "content": "Payment of $1,500.00 to Artist Name has been completed successfully.",
  "resourceType": "payment",
  "resourceId": "pay_123abc",
  "actionUrl": "/payments/pay_123abc",
  "isRead": false,
  "isImportant": true,
  "isArchived": false,
  "metadata": {
    "amount": 1500.00,
    "currency": "USD",
    "recipientName": "Artist Name",
    "method": "stripe"
  },
  "expiresAt": null,
  "TenantId": 2,
  "TenantUserId": "c75c54e3-b6e0-4b89-b443-928727b9a931",
  "createdAt": "2025-01-22T14:30:00.000Z",
  "updatedAt": "2025-01-22T14:30:00.000Z"
}

Field Descriptions

FieldTypeDescription
idstring (UUID)Unique notification identifier
typestringNotification type from NotificationType enum
titlestringShort notification title
contentstringDetailed notification message
resourceTypestringType of resource the notification relates to
resourceIdstringID of the related resource
actionUrlstringURL to navigate to when notification is clicked
isReadbooleanWhether the notification has been read
isImportantbooleanWhether the notification is marked as important
isArchivedbooleanWhether the notification is archived
metadataobjectAdditional event-specific data
expiresAtISO 8601When the notification expires (null for no expiration)
TenantIdintegerWorkspace ID
TenantUserIdstring (UUID)User ID the notification is for
createdAtISO 8601When the notification was created
updatedAtISO 8601When the notification was last updated

API Endpoints

Get Notifications

Retrieve paginated notifications with optional filtering. Endpoint: GET /notifications Query Parameters:
ParameterTypeDefaultDescription
pageinteger1Page number
pageSizeinteger20Number of items per page
isReadboolean-Filter by read status
isArchivedboolean-Filter by archived status
typestring-Filter by notification type
Example:
# Get unread notifications
curl -X GET "https://api.royalti.io/notifications?isRead=false&page=1&pageSize=10" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Get payment notifications
curl -X GET "https://api.royalti.io/notifications?type=PAYMENT_MADE_COMPLETED" \
  -H "Authorization: Bearer YOUR_TOKEN"

Get Unread Count

Get the count of unread notifications for quick badge display. Endpoint: GET /notifications/unread/count Example:
curl -X GET "https://api.royalti.io/notifications/unread/count" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "status": "success",
  "message": "Unread notification count retrieved successfully",
  "data": {
    "count": 12
  }
}

Mark Notification as Read

Mark a specific notification as read. Endpoint: PATCH /notifications/{notificationId}/read Path Parameters:
ParameterTypeRequiredDescription
notificationIdstring (UUID)YesID of the notification
Example:
curl -X PATCH "https://api.royalti.io/notifications/dd12f9bc-3ed5-453e-a929-69b6d5267f4b/read" \
  -H "Authorization: Bearer YOUR_TOKEN"

Mark All Notifications as Read

Mark all notifications as read for the authenticated user. Endpoint: PATCH /notifications/mark-all-read Example:
curl -X PATCH "https://api.royalti.io/notifications/mark-all-read" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "status": "success",
  "message": "All notifications marked as read"
}

Notification Preferences

Users can customize which notifications they receive and through which channels.

Get Notification Preferences

Retrieve the current notification preferences for the authenticated user. Endpoint: GET /notifications/preferences Example:
curl -X GET "https://api.royalti.io/notifications/preferences" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "status": "success",
  "message": "Notification preferences retrieved successfully",
  "data": {
    "preferences": [
      {
        "id": "65fdcd80-cada-4c76-83ec-70d8e895774d",
        "notificationType": "PAYMENT_MADE_COMPLETED",
        "channels": ["EMAIL", "IN_APP", "PUSH"],
        "isEnabled": true,
        "createdAt": "2025-05-27T19:55:02.423Z",
        "updatedAt": "2025-05-27T19:55:02.423Z"
      },
      {
        "id": "9e522898-358c-4208-9f7d-94bac43b7cf4",
        "notificationType": "ASSET_CREATED",
        "channels": ["IN_APP"],
        "isEnabled": true,
        "createdAt": "2025-05-27T21:17:56.973Z",
        "updatedAt": "2025-05-27T21:17:56.973Z"
      }
    ]
  }
}

Update Notification Preferences

Customize which notifications to receive and through which channels. Endpoint: PUT /notifications/preferences Request Body:
{
  "preferences": [
    {
      "notificationType": "PAYMENT_MADE_COMPLETED",
      "channels": ["EMAIL", "IN_APP", "PUSH"],
      "isEnabled": true
    },
    {
      "notificationType": "PAYMENT_MADE_FAILED",
      "channels": ["EMAIL", "PUSH"],
      "isEnabled": true
    },
    {
      "notificationType": "ASSET_CREATED",
      "channels": ["IN_APP"],
      "isEnabled": false
    }
  ]
}
Example:
curl -X PUT "https://api.royalti.io/notifications/preferences" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "preferences": [
      {
        "notificationType": "PAYMENT_MADE_COMPLETED",
        "channels": ["EMAIL", "IN_APP", "PUSH"],
        "isEnabled": true
      },
      {
        "notificationType": "ASSET_CREATED",
        "channels": ["IN_APP"],
        "isEnabled": false
      }
    ]
  }'
Response:
{
  "status": "success",
  "message": "Notification preferences updated successfully",
  "data": {
    "preferences": [
      {
        "id": "65fdcd80-cada-4c76-83ec-70d8e895774d",
        "notificationType": "PAYMENT_MADE_COMPLETED",
        "channels": ["EMAIL", "IN_APP", "PUSH"],
        "isEnabled": true,
        "createdAt": "2025-05-27T19:55:02.423Z",
        "updatedAt": "2025-01-22T15:30:00.000Z"
      }
    ]
  }
}

Preference Configuration

Available Channels

ChannelDescriptionDelivery Time
EMAILEmail to registered addressImmediate or batched (hourly aggregation)
IN_APPIn-app notification in dashboardReal-time
PUSHPush notification to mobile deviceReal-time

Notification Batching

Some notification types support batching to reduce email volume:
  • Immediate: Critical notifications (payments, failures) are sent immediately
  • Hourly Aggregation: Non-critical notifications (asset created, updates) are batched and sent hourly
  • Daily Cleanup: Expired notifications are automatically removed

Integration Patterns

Real-Time Notification Display

Implement a notification bell with unread count:
async function updateNotificationBell() {
  const response = await fetch(
    'https://api.royalti.io/notifications/unread/count',
    {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );

  const { data } = await response.json();

  // Update UI badge
  document.getElementById('notification-badge').textContent = data.count;
  document.getElementById('notification-badge').style.display =
    data.count > 0 ? 'block' : 'none';
}

// Poll every 30 seconds
setInterval(updateNotificationBell, 30000);

Notification List Component

Fetch and display notifications with pagination:
async function loadNotifications(page = 1) {
  const response = await fetch(
    `https://api.royalti.io/notifications?page=${page}&pageSize=10&isRead=false`,
    {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );

  const { data } = await response.json();

  data.notifications.forEach(notification => {
    renderNotification(notification);
  });

  // Handle pagination
  renderPagination(data.page, data.totalPages);
}

function renderNotification(notification) {
  const item = document.createElement('div');
  item.className = notification.isImportant ? 'notification important' : 'notification';
  item.innerHTML = `
    <h4>${notification.title}</h4>
    <p>${notification.content}</p>
    <small>${new Date(notification.createdAt).toLocaleString()}</small>
    ${notification.actionUrl ? `<a href="${notification.actionUrl}">View</a>` : ''}
  `;

  item.addEventListener('click', () => markAsRead(notification.id));

  document.getElementById('notification-list').appendChild(item);
}

async function markAsRead(notificationId) {
  await fetch(
    `https://api.royalti.io/notifications/${notificationId}/read`,
    {
      method: 'PATCH',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );

  // Refresh notification list
  loadNotifications();
}

Preference Management UI

Allow users to customize notification preferences:
async function loadPreferences() {
  const response = await fetch(
    'https://api.royalti.io/notifications/preferences',
    {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );

  const { data } = await response.json();

  data.preferences.forEach(pref => {
    renderPreferenceControl(pref);
  });
}

async function updatePreference(notificationType, channels, isEnabled) {
  const response = await fetch(
    'https://api.royalti.io/notifications/preferences',
    {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        preferences: [
          {
            notificationType,
            channels,
            isEnabled
          }
        ]
      })
    }
  );

  const result = await response.json();
  console.log('Preferences updated:', result);
}

Best Practices

✅ User Experience
  1. Display unread count prominently in your UI (bell icon with badge)
  2. Mark notifications as read when user views them
  3. Provide action links to relevant resources when applicable
  4. Group similar notifications to reduce clutter
  5. Auto-refresh notification count periodically (every 30-60 seconds)
  6. Show timestamps in user-friendly format (e.g., “5 minutes ago”)
  7. Highlight important notifications with visual indicators
  8. Allow bulk actions (mark all as read, archive, etc.)
✅ Performance Optimization
  1. Use pagination to limit the number of notifications loaded at once
  2. Cache unread count to reduce API calls
  3. Implement lazy loading for notification details
  4. Batch preference updates when changing multiple settings
  5. Use WebSockets or polling for real-time updates (if available)
✅ Preference Management
  1. Provide granular controls for each notification type
  2. Set sensible defaults based on notification importance
  3. Allow channel-specific preferences (email vs. in-app vs. push)
  4. Explain notification types so users understand what they’re opting into
  5. Respect user preferences immediately - no delay in applying changes
⚠️ Common Pitfalls
  1. Don’t overwhelm users with too many notifications
  2. Don’t ignore unread status - always mark as read when viewed
  3. Don’t hardcode notification types - use the API to get available types
  4. Don’t skip error handling - API calls may fail
  5. Don’t forget to implement pagination - notification lists can grow large

Troubleshooting

Notifications Not Appearing

✅ Checklist:
  1. Check notification preferences - is the event type enabled?
  2. Verify the user has the correct permissions
  3. Check if notifications are filtered by isRead or isArchived
  4. Ensure the tenant ID matches the authenticated user’s workspace
  5. Check the API response for errors

Missing Notification Preferences

✅ Solutions:
  1. Preferences are created on-demand when first updated
  2. Default preferences are used if none are set
  3. Call GET /notifications/preferences to see current state
  4. Update preferences with PUT /notifications/preferences

High Unread Count

✅ Management:
  1. Implement “Mark all as read” functionality
  2. Allow users to archive old notifications
  3. Set expiration dates for less important notifications
  4. Encourage users to customize preferences to reduce noise

FAQ

Yes, notifications are workspace-scoped. When events occur in your workspace (e.g., a teammate creates an asset), all relevant users receive notifications based on their preferences and permissions.
Notifications are stored indefinitely unless they have an expiresAt date. Expired notifications are automatically removed by the daily cleanup job at 2 AM UTC.
Yes, you can disable notifications by setting isEnabled: false for each notification type in your preferences. Alternatively, you can choose to only enable the IN_APP channel and manage notifications within the dashboard.
In-app and push notifications are sent in real-time. Email notifications for non-critical events may be batched and sent hourly to reduce email volume. Critical notifications (payments, failures) are always sent immediately.
Currently, notifications are workspace-level and cannot be filtered by specific resources. You can control notification types and channels, but not individual resources. This feature may be added in future updates.
Failed notifications are automatically retried based on the channel’s retry strategy. If all retry attempts fail, the notification is logged for debugging but the in-app notification remains accessible through the API.
Notification templates are currently managed by Royalti.io and cannot be customized per workspace. However, you can control which notifications you receive through your preferences.

Support & Resources

API Documentation: Related Guides: External Resources:
Last Updated: January 2025 Version: 1.0