Overview
Manage collaborators, assign roles, and track earnings for users in your workspace. The user management system supports flexible invitation workflows, role-based permissions, and direct integration with royalty calculations.
Key Features:
- Flexible invitations - Email-based or manual user creation
- Role-based access - User and Admin permissions
- Earnings tracking - View earnings per user
- Bulk operations - Manage multiple users efficiently
Prerequisites
Authentication
All endpoints require authentication using a Bearer token:
Authorization: Bearer YOUR_ACCESS_TOKEN
User Roles
| Role | Access Level |
|---|
| User | View own data, create releases, view earnings, request payments |
| Admin | Full workspace access, user management, financial operations |
Quick Start: Creating Your First User
Create User with Email Invite
const response = await fetch('https://api.royalti.io/user/', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstName: 'Jane',
lastName: 'Doe',
nickName: 'janedoe',
email: '[email protected]',
role: 'user',
userType: ['artist', 'producer'],
sendEmail: true,
message: 'Welcome to our workspace!',
redirect_url: 'https://app.royalti.io/welcome'
})
});
An invitation email is automatically sent with your custom message.Create User without Email
const response = await fetch('https://api.royalti.io/user/', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstName: 'Studio',
lastName: 'Catalog',
nickName: 'legacy-artist',
// No email - useful for catalog management
role: 'user',
userType: 'artist'
})
});
Users without email can still be assigned splits and earn royalties. Useful for managing historical catalog data.
Check Invitation Status
const invites = await fetch('https://api.royalti.io/user/invites', {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
User Types
Users can have one or more types to categorize their role:
Available Types:
artist, producer, writer, publisher, label, manager, engineer, band, other
Format:
- Single type:
"artist"
- Multiple types:
["artist", "producer"]
Managing Invitations
Resend an Invitation
If a user hasn’t received or needs a new invitation:
POST /user/invites/{inviteId}/resend
await fetch(`https://api.royalti.io/user/invites/${inviteId}/resend`, {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
Common reasons to resend:
- Email not received
- Invitation expired
- User requested new link
Cancel an Invitation
POST /user/invites/{inviteId}/cancel
await fetch(`https://api.royalti.io/user/invites/${inviteId}/cancel`, {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
View All Invitations
GET /user/invites
const invites = await fetch('https://api.royalti.io/user/invites', {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
// Returns invitation list with status and user details
User Profile & Updates
Get User Details
GET /user/{id}
const user = await fetch(`https://api.royalti.io/user/${userId}`, {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
// Returns complete profile with linked artists, assets, and invitation status
Update User Profile
PATCH /user/{id}
await fetch(`https://api.royalti.io/user/${userId}`, {
method: 'PATCH',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
nickName: 'updated-nickname',
phone: '+1234567890',
country: 'US',
userType: ['artist', 'producer'],
role: 'admin' // Admin only
})
});
Editable fields:
- Name and nickname
- Contact information (phone, country)
- User types
- Role (requires admin)
User Earnings & Statistics
Get User Stats
View catalog size and earnings for a user:
GET /user/{id}/stats
const stats = await fetch(`https://api.royalti.io/user/${userId}/stats`, {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
// Response:
{
artists: 5, // Number of artists
assets: 17, // Number of assets
products: 7, // Number of products
splits: 10, // Number of active splits
Royalty_Share: 1135.28, // Total earnings
paid: 100.00, // Amount paid
due: 1035.28 // Amount currently due
}
Monthly Earnings
Track earnings over time:
GET /user/{id}/monthly?period=last12months
const monthlyData = await fetch(
`https://api.royalti.io/user/${userId}/monthly?period=last12months`,
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
);
// Response includes month-by-month earnings data
Period options:
last12months - Previous 12 months (default)
ytd - Year to date
all - All time
custom - Use startDate and endDate parameters
View User’s Artists
GET /user/{id}/artists?stats=true
const artists = await fetch(`https://api.royalti.io/user/${userId}/artists?stats=true`, {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
// With stats=true: includes asset count, product count, and earnings per artist
View User’s Assets
GET /user/{id}/assets
const assets = await fetch(`https://api.royalti.io/user/${userId}/assets`, {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
View User’s Products
GET /user/{id}/products
const products = await fetch(`https://api.royalti.io/user/${userId}/products`, {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
List & Filter Users
Basic User List
GET /user/?page=1&size=10
const users = await fetch('https://api.royalti.io/user/?page=1&size=10', {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
Filter & Search
// Search by name
GET /user/?q=john&page=1&size=10
// Filter by role
GET /user/?role=admin
// Filter by external ID
GET /user/?externalId=ext-12345
// Include earnings data
GET /user/?accounting=true
// Sort by different fields
GET /user/?sort=name&order=asc
GET /user/?sort=due&order=desc&accounting=true
Sort options:
createdAt, updatedAt - By date
name - Alphabetically
split - By number of splits
gross, paid, due - By earnings (requires accounting=true)
Bulk Operations
Create Multiple Users
POST /user/bulk
await fetch('https://api.royalti.io/user/bulk', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
users: [
{
firstName: 'Artist',
lastName: 'One',
nickName: 'artist1',
email: '[email protected]',
role: 'user',
userType: 'artist'
},
{
firstName: 'Producer',
lastName: 'Two',
nickName: 'producer2',
email: '[email protected]',
role: 'user',
userType: 'producer'
}
],
sendEmail: true,
message: 'Welcome to our workspace!'
})
});
// Returns list of created users and any errors
Bulk operations support partial success. Some users may be created while others fail validation. Check the response for details.
Delete Multiple Users
POST /user/bulk/delete
await fetch('https://api.royalti.io/user/bulk/delete', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
ids: ['user-id-1', 'user-id-2', 'user-id-3']
})
});
Deleting users removes their split assignments. Accounting records are preserved for audit purposes. You cannot delete the workspace owner or your own account.
Create Users with Artist Assignment
Create users and assign them to artists with splits in one operation:
POST /user/bulk/entity
await fetch('https://api.royalti.io/user/bulk/entity', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: [
{
artistName: 'The Band',
firstName: 'John',
lastName: 'Smith',
email: '[email protected]',
splitShare: 50 // John gets 50%, admin gets remainder
}
],
sendEmail: true
})
});
Export User Data
POST /user/download/csv
await fetch('https://api.royalti.io/user/download/csv', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
userIds: ['user-id-1', 'user-id-2'] // Optional - omit for all users
})
});
// Returns CSV file with user data
Best Practices
User Creation
- Use email for active collaborators - Anyone who will log in should have an email
- Skip email for catalog entries - Historical or non-login users don’t need email
- Assign appropriate roles - Start with
user role, upgrade to admin only when needed
- Categorize with user types - Accurate types help with reporting and organization
Invitation Management
- Personalize messages - Custom invitation messages improve acceptance
- Clean up old invites - Cancel invitations that haven’t been accepted after reasonable time
- Use redirect URLs - Guide users to the right place after accepting
- Use bulk operations - More efficient than individual API calls
- Enable accounting parameter - Add
accounting=true for faster user lists with earnings
- Paginate appropriately - Use reasonable page sizes (10-50 users)
Common Workflows
Onboard a New Collaborator
- Create user with invitation email
- User accepts invitation and sets up account
- Assign user to relevant splits
- User can view their earnings and request payments
Manage Catalog Users
- Create users without email for historical artists
- Assign to catalog splits
- Track earnings centrally
- Process payments to rights holders
Team Management
- Create admin users for team members
- Regular users can view their own data
- Admins manage the workspace
- Export user data for reporting
Troubleshooting
”Email already associated with workspace”
- Email addresses must be unique per workspace
- Check if user already exists
- Update existing user instead of creating new
”Cannot delete workspace owner”
- Transfer ownership before deletion
- Contact support if needed
Invitation emails not received
- Check spam/junk folders
- Verify email address is correct
- Use resend endpoint
- Check with recipient’s email provider
API Reference
User Management:
Invitations:
User Data:
Bulk Operations:
Next Steps