agentsclimarketplace

Royalti api

Skill Royalti-io/royalti-api-skill/skills/royalti-api

Royalti.io REST API v2.6 Agent Skill — install in Claude Code, Cursor, Codex CLI, or any Agent Skills compatible tool

Install
npx -y skills add Royalti-io/royalti-api-skill --skill royalti-api

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Royalti.io REST API v2.6 pattern reference for developers. Covers authentication, CRUD patterns, pagination, error handling, webhooks, WebSocket events, data models, DDEX distribution, AI chat, source creator, global search, checklist workflows, music publishing, billing, and more. Use when helping developers integrate with the Royalti API (api.royalti.io) or when writing integration code, API documentation, or troubleshooting API issues.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

57.1 KB, as published. Nobody here has run it

Royalti API v2.6 — Developer Reference

Pattern reference for integrating with the Royalti.io REST API.

Base URL: https://api.royalti.io Current Version: 2.6.4 Architecture: Multi-tenant (workspace-scoped)


1. Authentication

Token Types

TokenPrefixExpiryUse Case
JWT Access Token6 hoursAll API requests
JWT Refresh Token1 dayObtain new access tokens
Workspace API KeyRWAKNever (revocable)Programmatic workspace access
User API KeyRUAKNever (revocable)Programmatic user access

Two-Step JWT Login

# Step 1: Login — returns refresh token + workspace list
curl -X POST https://api.royalti.io/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "[email protected]", "password": "secret" }'

# Response:
# {
#   "refresh_token": "eyJ...",
#   "workspaces": [{ "id": "ws_abc", "name": "My Label", ... }]
# }

# Step 2: Exchange refresh token for access token (scoped to a workspace)
curl https://api.royalti.io/auth/authtoken?currentWorkspace=ws_abc \
  -H "Authorization: Bearer <refresh_token>"

# Response:
# { "data": { "access_token": "eyJ..." } }

Using the Access Token

All subsequent requests include the access token:

curl https://api.royalti.io/artist/ \
  -H "Authorization: Bearer <access_token>"

API Key Authentication

API keys can be used instead of JWT tokens. Pass them in the Authorization header:

# Workspace API key
curl https://api.royalti.io/artist/ \
  -H "Authorization: Bearer RWAK_abc123..."

# User API key
curl https://api.royalti.io/asset \
  -H "Authorization: Bearer RUAK_def456..."

API Key Auth Resolution (Internals)

Understanding how RWAK/RUAK keys resolve to a workspace context helps debug auth errors:

1. Token prefix detected as RWAK/RUAK (not JWT)
2. ApiKeys table lookup → finds TenantId
3. Tenants table lookup → finds workspace (must be status='active')
4. Tenants.user field → used to find the owner TenantUser via TenantUser.findByPk()
5. Owner TenantUser populates req.user for all downstream handlers

Key detail: Tenants.user must store a TenantUser.id (UUID), NOT a User.id. These are different tables with different PKs. If this field is wrong, the API returns "Workspace user not found" (HTTP 404) despite the API key being valid.

The Tenants.user field is also used by:

  • Accounting endpoints — to exclude the workspace owner from payee/due calculations
  • Admin auth — to resolve workspace context for admin JWT tokens

Other Auth Methods

EndpointMethodPurpose
POST /auth/loginlinkPOSTMagic link login
POST /auth/forgotpasswordPOSTRequest password reset
PATCH /auth/resetpassword?code=CODEPATCHApply password reset
GET /auth/googleGETGoogle OAuth
GET /auth/linkedinGETLinkedIn OAuth
GET /auth/facebookGETFacebook OAuth

Rate Limiting

  • Login endpoint: 20 requests per 3 minutes per IP
  • AI endpoints: Rate limited per tenant subscription tier (billing-period aligned)
  • Other endpoints: No documented limits (subject to fair use)

RBAC Roles (ascending privilege)

guest < user < admin < owner < super_admin < main_super_admin

Feature Gating

Certain API features require subscription-level feature flags:

Feature FlagRequired For
royaltyAccessRoyalty file upload, source creator, analytics
aiAgentAI chat conversations and messages
addonsAccessDDEX, Merlin, Publisher addons

Addon-specific checks: ddex, publisher, merlin — require the addon to be enabled on the tenant.


2. Request Patterns

Standard Headers

Authorization: Bearer <access_token | API_KEY>
Content-Type: application/json

Pagination (all list endpoints)

ParamDefaultDescription
page1Page number
size1020Items per page (max 100)
sortupdatedAtSort field
orderdescasc or desc
GET /artist/?page=2&size=25&sort=artistName&order=asc

Filtering (analytics endpoints)

ParamTypeDescription
startYYYY-MM-DDDate range start
endYYYY-MM-DDDate range end
dspCSV stringFilter by DSP/platform
countryCSV stringFilter by territory (ISO 3166-1 alpha-2)
artistsCSV stringFilter by artist IDs
upcCSV stringFilter by UPC
isrcCSV stringFilter by ISRC
aggregatorCSV stringFilter by distributor
typestringFilter by sale type
periodFilterTypeaccounting or saleDate filtering mode
includePreviousPeriodbooleanInclude comparison data
table_namestringFilter by royalty file source table

Search

Many list endpoints support a search query param for text-based filtering:

GET /artist/?search=drake&page=1&size=10

Bulk Operations

Most resources support bulk create and delete:

POST /artist/bulk          # Create multiple artists
DELETE /artist/bulk/delete  # Delete multiple artists
POST /asset/bulksplits     # Assign splits to multiple assets

3. Response Patterns

Success Response

{
  "status": "success",
  "message": "Operation successful",
  "data": { ... }
}

Paginated List Response

Response shapes vary by resource. Most use data[], but some use resource-specific keys:

// Standard shape (labels, splits, payments, expenses, revenue, notifications)
{
  "status": "success",
  "data": [ ... ],
  "totalItems": 142,
  "totalPages": 15,
  "currentPage": 1
}

// Users — uses "Users" key, no "status" field
{
  "message": "success",
  "totalItems": 10,
  "Users": [ ... ],
  "totalPages": 1,
  "currentPage": 1
}

// Artists — uses "Artists" key, includes "filteredItems"
{
  "totalItems": 50,
  "Artists": [ ... ],
  "totalPages": 5,
  "currentPage": 1,
  "filteredItems": 50
}

// Products — uses "Products" key
// Assets — uses "data" key

Tip: Always check for both data and the resource-specific key (e.g., Users, Artists, Products) when parsing list responses.

Summary Response (v2.6.4+)

Available on: /artist/summary, /asset/summary, /product/summary, /user/summary, /split/summary, /payment/summary, /expense/summary, /revenue/summary, /file/summary

{
  "message": "Summary retrieved successfully",
  "summary": {
    "total": 250,
    "byStatus": { "active": 200, "inactive": 50 },
    "byFormat": { "Single": 120, "Album": 80, "EP": 50 },
    "byType": { "Audio": 230, "Video": 20 },
    "revenue": { "total": 15000.50, "currency": "USD" }
  }
}

Error Response

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": ["optional", "array", "of", "details"]
  }
}

Common HTTP Status Codes

CodeMeaning
200Success
201Created
400Bad request / validation error
401Unauthorized (missing or invalid token)
403Forbidden (insufficient role/permissions)
404Resource not found
409Conflict (duplicate, schema disparity)
422Unprocessable entity
429Rate limited
500Server error

4. Core Resources

All resources follow the same CRUD pattern unless noted. Every resource is workspace-scoped (multi-tenant).

Standard CRUD Pattern

GET    /{resource}/          # List (paginated)
POST   /{resource}/          # Create
GET    /{resource}/{id}      # Get by ID
PUT    /{resource}/{id}      # Update
DELETE /{resource}/{id}      # Delete
GET    /{resource}/summary   # Summary stats (v2.6.4+)
GET    /{resource}/download/csv  # CSV export
POST   /{resource}/bulk      # Bulk create
DELETE /{resource}/bulk/delete   # Bulk delete

Users (/user/)

Standard CRUD plus:

EndpointDescription
GET /user/{id}/statsUser royalty statistics
GET /user/{id}/monthlyMonthly breakdown
GET /user/{id}/artistsUser's artists
GET /user/{id}/assetsUser's assets
GET /user/{id}/productsUser's products
GET /user/{id}/autUser accounting data
GET /user/invitesPending invitations
POST /user/invites/{id}/resendResend invitation
POST /user/invites/{id}/cancelCancel invitation

Artists (/artist/)

Standard CRUD plus:

EndpointDescription
GET /artist/{id}/assetsArtist's tracks
GET /artist/{id}/productsArtist's releases
GET /artist/{id}/splitsArtist's splits
GET /artist/{id}/splits/{type}Splits by type
PUT /artist/{id}/splits/{type}Update split by type
DELETE /artist/{id}/splits/{type}Delete split by type
POST /artist/{id}/splitsCreate artist default split
GET /artist/{id}/statsArtist analytics
POST /artist/{id}/mergeMerge duplicate artists
POST /artist/bulksplitBulk assign splits
POST /artist/download/csvDownload artist CSV

Key fields: artistName, signDate, label, publisher, copyright, externalId, artistImg, links (spotify/youtube/instagram/etc.), genres, realName, pseudonyms

Assets / Tracks (/asset)

Standard CRUD plus:

EndpointDescription
GET /asset/{id}/artistsTrack's artists
GET /asset/{id}/statsTrack analytics
POST /asset/{id}/setdefaultsplitSet default split
GET /asset/{id}/mediaTrack media files
DELETE /asset/{id}/media/{mediaName}Delete media
GET /asset/{id}/ddex-metadataDDEX metadata
GET /asset/{id}/ddex-readinessDDEX readiness check
GET /asset/{assetId}/worksMusical works (ISWC)
POST /asset/bulksplitsBulk assign splits
DELETE /asset/bulk/deletesplitBulk remove splits
POST /asset/bulk/defaultsplitBulk set default splits

Key fields: title, ISRC, type (Audio|Video|Ringtone|YouTube), version, displayArtist, mainArtist[], mainGenre[], subGenre[], explicit, language, tempo, key, mood[], lyrics, label, copyright, publisher

Products / Releases (/product/)

Standard CRUD plus:

EndpointDescription
GET /product/{id}/artistsRelease's artists
GET /product/{id}/assetsRelease's tracks
GET /product/{id}/statsRelease analytics
POST /product/{id}/setdefaultsplitSet default split
GET /product/{id}/mediaRelease artwork/media
GET /product/{id}/deliveryDelivery info
GET /product/{id}/delivery/statusDelivery status
POST /product/batch-deliveryBatch deliver releases
GET /product/{id}/deliveriesDelivery history
POST /product/{id}/deliveries/{deliveryId}/retryRetry failed delivery
GET /product/delivery-providersAvailable distributors
GET /product/download/metadataMetadata export

Key fields: title, UPC, format (Single|EP|Album|LP), release_date, takedown_date, label, display_artist, type (Audio|Video), catalog_number, status (active|inactive|pending|Live|Taken Down|Scheduled|Error), distribution, external_id

Splits (/split/)

Standard CRUD plus:

EndpointDescription
POST /split/defaultCreate split from artist default
POST /split/matchFind splits matching criteria
DELETE /split/bulk/catalog-splitsRemove catalog-level splits

Split types: simple, conditional, temporal

{
  "entity_type": "artist",
  "entity_id": "uuid",
  "split_type": "conditional",
  "effective_date": "2025-01-01",
  "shares": [
    { "user": "user-uuid-1", "percentage": 60 },
    { "user": "user-uuid-2", "percentage": 40 }
  ],
  "conditions": {
    "territories": ["US", "GB", "CA"],
    "mode": "include",
    "sources": ["Spotify", "Apple Music"],
    "period_start": "2025-01-01",
    "period_end": "2025-12-31",
    "memo": "North America streaming deal"
  }
}

Rules: Shares must sum to 100. entity_type is artist, product, or asset. Conditions are optional (omit for simple splits).

Royalties / Analytics (/royalty/)

Read-only analytics endpoints. All support the standard filter params (start, end, dsp, country, etc.). Requires royaltyAccess feature.

EndpointDescription
GET /royalty/Main summary
GET /royalty/monthMonthly trends
GET /royalty/dspBy DSP/platform
GET /royalty/countryBy country/territory
GET /royalty/artistBy artist
GET /royalty/productBy product/release
GET /royalty/assetBy track
GET /royalty/tablesBy data source
GET /royalty/saletypeBy sale type (stream, download, etc.)
GET /royalty/aggregatorBy distributor
GET /royalty/accountingperiodBy accounting period

Analytics response shape:

{
  "Downloads": 1500,
  "Streams": 250000,
  "Royalty": 1234.56,
  "Count": 251500,
  "RatePer1K": 4.91,
  "RoyaltyPercentage": 45.2,
  "CountPercentage": 38.7,
  "PreviousRoyalty": 1100.00,
  "PreviousCount": 220000
}

PreviousRoyalty and PreviousCount are only present when includePreviousPeriod=true.

Accounting (/accounting/)

EndpointDescription
GET /accounting/{id}/statsUser accounting stats
GET /accounting/transactionsTransaction list
GET /accounting/transactions/summaryTransaction summary
GET /accounting/transactions/monthlyMonthly transaction breakdown
GET /accounting/getcurrentdueCurrent amount due per user
GET /accounting/gettotaldueTotal outstanding across workspace
POST /accounting/refreshRecalculate accounting
POST /accounting/refreshstatsRefresh stats cache
POST /accounting/users/{id}/recalculateRecalculate single user
POST /accounting/tenant/recalculateRecalculate entire workspace
GET /accounting/queue/statusProcessing queue status

Payments (/payment/)

Standard CRUD. Supports both JSON and multipart/form-data (for attaching receipts).

EndpointDescription
GET /payment/summaryPayment totals
POST /payment/bulkBulk create payments

Payment Requests (/payment-request/)

EndpointDescription
GET /payment-request/List requests
GET /payment-request/{id}Get request
POST /payment-request/{id}/approveApprove request
POST /payment-request/{id}/declineDecline request

Royalty Files (/file/)

EndpointDescription
GET /file/royaltyList uploaded royalty files
GET /file/royalty/{id}Get file details
DELETE /file/royalty/{id}Delete file
GET /file/summaryFile summary stats
POST /file/createroyaltyUpload royalty file
GET /file/upload-urlGet presigned upload URL
POST /file/confirm-upload-completionConfirm upload finished
GET /file/detection/{sessionId}Poll auto-detection status
POST /file/confirm-detection/{sessionId}Confirm detected format
GET /file/auto-processing-configAuto-processing settings
POST /file/enable-auto-processingEnable auto-processing
GET /file/sourcesList royalty sources (DSPs)
GET /file/{id}/downloadDownload file
GET /file/processing/{jobId}Processing job status
POST /file/session/{sessionId}/start-source-creatorBridge to source creator for unknown formats
POST /file/upload-from-driveUpload from Google Drive

Labels (/labels/)

Standard CRUD plus:

EndpointDescription
GET /labels/hierarchyLabel tree structure

Releases (/releases)

Full release lifecycle with media management:

Release CRUD:

EndpointDescription
POST /releasesCreate release (draft)
GET /releasesList releases
GET /releases/statsRelease statistics
GET /releases/{id}Get release details
PUT /releases/{id}Update release
DELETE /releases/{id}Delete release

Lifecycle Workflow:

EndpointRoleDescription
POST /releases/{id}/submituserSubmit for review
POST /releases/{id}/reviewadminStart review
POST /releases/{id}/feedbackadminAdd feedback
POST /releases/{id}/revert-statusadminRevert release status

Release Media:

EndpointDescription
POST /releases/{id}/media/filesUpload release files (artwork, etc.)
POST /releases/{id}/media/linksSubmit release links
GET /releases/{id}/mediaGet release media
DELETE /releases/{id}/media/{mediaId}Delete release media

Track Management:

EndpointDescription
POST /releases/{id}/tracksCreate track in release
PUT /releases/{id}/tracks/{trackId}Update track
DELETE /releases/{id}/tracks/{trackId}Delete track
POST /releases/{id}/tracks/reorderReorder release tracks
POST /releases/{id}/tracks/link-assetLink existing asset to release

Track Media:

EndpointDescription
POST /releases/{id}/tracks/{trackId}/media/fileUpload track audio/video file
POST /releases/{id}/tracks/{trackId}/media/linkSubmit track link
GET /releases/{id}/tracks/{trackId}/mediaGet track media
DELETE /releases/{id}/tracks/{trackId}/media/{mediaId}Delete track media

Expenses & Revenue

Both follow standard CRUD at /expense/ and /revenue/ with summary endpoints.

Notifications (/notifications/)

EndpointDescription
GET /notifications/List notifications
PATCH /notifications/{id}/readMark as read
PATCH /notifications/read-allMark all as read
GET /notifications/unread-countUnread count

Downloads / Reports (/download/)

EndpointDescription
POST /download/generateGenerate report download
GET /download/{id}/statusCheck generation status
GET /download/listList available downloads

5. Global Search (/search)

Cross-entity search across the entire catalog.

EndpointRoleDescription
GET /search?q={query}&types={types}userGlobal search
GET /search/recentuserGet recent searches
DELETE /search/recentuserClear search history

Query Parameters:

ParamTypeDescription
qstringSearch query text
typesCSV stringEntity types to search (e.g., artist,product,asset,user)

6. Royalty Sources (/sources)

Manage royalty data sources (DSPs, distributors, custom sources).

Tenant Routes:

EndpointRoleDescription
GET /sourcesuserList tenant's royalty sources
POST /sourcesuserCreate new tenant source
GET /sources/{id}userGet source details
PUT /sources/{id}userUpdate source
DELETE /sources/{id}userDelete source
POST /sources/{id}/activateuserActivate source
POST /sources/{id}/deactivateuserDeactivate source

7. Source Creator (/source-creator)

AI-powered wizard for creating new royalty source definitions. Requires royaltyAccess feature.

Analysis & Mapping:

EndpointDescription
POST /source-creator/analyzeUpload and analyze file (multipart)
POST /source-creator/ai-map-columnsGet AI column mapping suggestions (rate limited)
PUT /source-creator/sessions/{id}/mappingsSave user-confirmed mappings
PUT /source-creator/sessions/{id}/periodsConfirm accounting periods
POST /source-creator/sessions/{id}/suggest-nameGet smart name suggestion

Query Generation & Testing:

EndpointDescription
POST /source-creator/generate-queriesGenerate BigQuery SQL from mappings (rate limited)
POST /source-creator/test-queriesTest queries against sample data

Save & Reuse:

EndpointDescription
POST /source-creator/saveSave as draft source
POST /source-creator/reuseReuse existing source for new file
GET /source-creator/sources/{id}/mappingsGet source column mappings
GET /source-creator/sources/{id}/queriesGet source queries

Session Management:

EndpointDescription
GET /source-creator/sessionsList sessions
GET /source-creator/sessions/{id}Get session details
DELETE /source-creator/sessions/{id}Delete session

Admin Routes (super admin only):

EndpointDescription
GET /source-creator/admin/draftsList all draft sources across tenants
GET /source-creator/admin/sessions/{id}Get full session detail
POST /source-creator/admin/{id}/promotePromote draft to global source

Source Creator Flow

1. POST /source-creator/analyze              → Upload file, get column analysis
2. POST /source-creator/ai-map-columns       → Get AI mapping suggestions
3. PUT  /source-creator/sessions/{id}/mappings → Confirm mappings
4. PUT  /source-creator/sessions/{id}/periods  → Confirm accounting periods
5. POST /source-creator/generate-queries      → Generate BigQuery SQL
6. POST /source-creator/test-queries          → Validate against sample data
7. POST /source-creator/save                  → Save as draft source
   (Admin) POST /source-creator/admin/{id}/promote → Promote to global

8. Checklist / Data Quality (/checklist)

Data quality validation, catalog enrichment, and workflow orchestration. Requires admin role.

Validation Checks:

EndpointDescription
GET /checklist/royaltyassetsAssets appearing in royalty data but not in catalog
GET /checklist/royaltyproductsProducts appearing in royalty data but not in catalog
GET /checklist/assetsplitsAssets missing split assignments
GET /checklist/productsplitsProducts missing split assignments
GET /checklist/allsplitsAll split coverage issues
GET /checklist/missingroyaltysplitsRoyalty items without splits
GET /checklist/artistsplitsArtist split user issues
GET /checklist/missingprimaryartistsAssets/products missing primary artists
GET /checklist/duplicateartistsDuplicate artist detection
GET /checklist/productswithoutassetsProducts with no linked assets
GET /checklist/assetswithoutproductsAssets with no linked products

Import from Royalty Data:

EndpointDescription
POST /checklist/royaltyassets/importImport missing assets from royalty data
POST /checklist/royaltyproducts/importImport missing products from royalty data

Catalog Enrichment:

EndpointDescription
POST /checklist/assets/enrichEnrich assets with external metadata
POST /checklist/products/enrichEnrich products with external metadata
GET /checklist/enrichmentList enrichment items
GET /checklist/enrichment/job/{jobId}Get enrichment job status
GET /checklist/enrichment/{id}Get enrichment item details
PUT /checklist/enrichment/{id}Update enrichment item
POST /checklist/enrichment/approveApprove enrichment items
POST /checklist/enrichment/rejectReject enrichment items
POST /checklist/enrichment/re-enrichRe-enrich rejected items
POST /checklist/enrichment/cleanupCleanup enrichment items

Workflow Orchestration:

EndpointDescription
POST /checklist/workflowStart a checklist workflow
GET /checklist/workflowList workflows
GET /checklist/workflow/{id}Get workflow details
POST /checklist/workflow/{id}/respondRespond to workflow prompt
POST /checklist/workflow/{id}/cancelCancel workflow

9. DDEX Distribution (/ddex)

Digital Data Exchange standard support for release distribution. Requires addonsAccess feature + ddex addon.

ERN (Electronic Release Notification):

EndpointRoleDescription
POST /ddex/ern/generateadminGenerate ERN message for a release
POST /ddex/ern/generate-batchadminGenerate multiple ERN messages

MEAD (Music Enrichment and Description):

EndpointRoleDescription
POST /ddex/mead/generateadminGenerate MEAD message
PUT /ddex/mead/{entityId}adminUpdate MEAD metadata

Message Management:

EndpointRoleDescription
GET /ddex/messagesuserList all DDEX messages
GET /ddex/messages/{messageId}userGet message details
POST /ddex/messages/{messageId}/validateadminValidate message
GET /ddex/messages/{messageId}/downloadadminDownload message XML

Delivery:

EndpointRoleDescription
POST /ddex/delivery/deliver/{messageId}adminDeliver message to provider
POST /ddex/delivery/deliver-batchadminBatch delivery
POST /ddex/delivery/retry/{messageId}adminRetry failed delivery
GET /ddex/delivery/status/{messageId}userGet delivery status
GET /ddex/delivery/logs/{messageId}adminGet delivery logs
POST /ddex/delivery/test-connectionownerTest DSP connection
POST /ddex/delivery/test-all-connectionsownerTest all provider connections

Provider Management:

EndpointRoleDescription
GET /ddex/providersuserList available DSP providers
GET /ddex/providers/{providerId}userGet provider details
GET /ddex/providers/{providerId}/statsuserGet provider statistics

Tenant Provider Configuration:

EndpointRoleDescription
GET /ddex/tenant-providersadminList tenant's configured providers
POST /ddex/tenant-providersownerConfigure new provider
PUT /ddex/tenant-providers/{id}ownerUpdate provider config
DELETE /ddex/tenant-providers/{id}ownerRemove provider config

Queue & Monitoring:

EndpointRoleDescription
GET /ddex/queue/jobsadminList queue jobs
GET /ddex/queue/jobs/{jobId}adminGet job details
GET /ddex/queue/jobs/{jobId}/logsadminGet job logs
GET /ddex/monitoring/dashboardadminMonitoring dashboard

Usage:

EndpointRoleDescription
GET /ddex/usageadminGet DDEX usage stats
GET /ddex/usage/dashboardadminUsage dashboard

DDEX Distribution Flow

1. POST /ddex/tenant-providers                    → Configure DSP provider (one-time)
2. POST /ddex/delivery/test-connection            → Verify connection
3. POST /ddex/ern/generate { releaseId }          → Generate ERN message
4. POST /ddex/messages/{messageId}/validate       → Validate message
5. POST /ddex/delivery/deliver/{messageId}        → Deliver to DSP
6. GET  /ddex/delivery/status/{messageId}         → Monitor delivery status
   If failed: POST /ddex/delivery/retry/{messageId}

10. AI Chat Agent (/ai)

Conversational AI assistant with workspace context. Requires aiAgent feature. Supports Vercel AI SDK streaming.

Conversations:

EndpointDescription
POST /ai/conversationsCreate conversation
GET /ai/conversationsList conversations
GET /ai/conversations/{conversationId}Get conversation
PUT /ai/conversations/{conversationId}Update conversation
DELETE /ai/conversations/{conversationId}Archive conversation

Messages:

EndpointDescription
GET /ai/conversations/{conversationId}/messagesGet messages
POST /ai/conversations/{conversationId}/messagesSend message (rate limited)
POST /ai/chatVercel AI SDK streaming chat

Status & Configuration:

EndpointDescription
GET /ai/healthHealth check (public)
GET /ai/rate-limitCheck rate limit status
GET /ai/budget-statusCheck cost budget status
GET /ai/suggestionsGet context-aware follow-up suggestions
GET /ai/configGet AI configuration
POST /ai/feedbackSubmit conversation feedback
GET /ai/conversations/{conversationId}/statsConversation stats

Retention Config (admin):

EndpointDescription
GET /ai/retention-configGet retention policy
PUT /ai/retention-configUpdate retention policy
POST /ai/retention/apply-nowApply retention immediately

AI Chat Streaming

The /ai/chat endpoint supports Vercel AI SDK streaming format:

POST /ai/chat
Content-Type: application/json

{
  "messages": [
    { "role": "user", "content": "What are my top performing artists this quarter?" }
  ],
  "conversationId": "optional-conversation-uuid"
}

The response is a server-sent event stream compatible with useChat() from the Vercel AI SDK.


11. Merlin Addon (/merlin)

Automated royalty file import via FTP with approval workflows. Requires addonsAccess feature + merlin addon.

Configuration:

EndpointRoleDescription
POST /merlin/configownerCreate or update Merlin config
GET /merlin/configadminGet Merlin configuration
DELETE /merlin/configownerDisable Merlin integration

Credentials & Connection:

EndpointRoleDescription
PUT /merlin/credentialsownerUpdate FTP credentials
POST /merlin/test-connectionownerTest FTP connection
GET /merlin/connection-statusadminGet connection status
PUT /merlin/featuresadminUpdate enabled features

Import Configuration (requires royaltyImport addon feature):

EndpointRoleDescription
GET /merlin/import/configadminGet import config
PUT /merlin/import/configadminUpdate import config
PUT /merlin/import/scheduleadminUpdate import schedule

Import Operations:

EndpointRoleDescription
POST /merlin/import/triggeradminTrigger manual import
GET /merlin/import/batchesuserList import batches
GET /merlin/import/batch/{id}userGet batch details
POST /merlin/import/batch/{id}/canceladminCancel batch

Pending Import Approval:

EndpointRoleDescription
GET /merlin/pendinguserList pending imports
GET /merlin/pending/groupeduserPending imports grouped by source/period
GET /merlin/pending/{id}userGet pending import details
GET /merlin/pending/{id}/previewuserPreview file contents
GET /merlin/pending/{id}/recommendationuserGet confidence recommendation
POST /merlin/pending/{id}/approveadminApprove pending import
POST /merlin/pending/{id}/rejectadminReject pending import
POST /merlin/pending/bulk-approveadminBulk approve
POST /merlin/pending/bulk-rejectadminBulk reject

Auto-Approval:

EndpointRoleDescription
GET /merlin/batches/{batchId}/auto-approvableuserGet auto-approvable candidates
GET /merlin/imports/groupableuserGet groupable imports

History & Stats:

EndpointRoleDescription
GET /merlin/sourcesuserList Merlin-compatible sources
GET /merlin/historyuserImport history
GET /merlin/statsuserImport statistics
GET /merlin/metricsuserComprehensive metrics

12. Data Shares (/data-shares)

Cross-tenant royalty data sharing for labels sharing sources.

EndpointRoleDescription
GET /data-sharesadminList data shares
POST /data-sharesownerCreate data share
GET /data-shares/{id}adminGet share details
PUT /data-shares/{id}ownerUpdate share
DELETE /data-shares/{id}ownerDelete share

13. Music Publishing

Publishing management with CWR (Common Works Registration) export. Requires publisher addon.

Publishers (/publishers)

EndpointRoleDescription
GET /publishersuserList publishers
POST /publishersadminCreate publisher
GET /publishers/{id}userGet publisher
PUT /publishers/{id}adminUpdate publisher
DELETE /publishers/{id}adminDelete publisher
GET /publishers-with-user-datauserPublishers with associated user data

Territory Management:

EndpointRoleDescription
GET /publishers/{id}/territoriesuserList territories
POST /publishers/{id}/territoriesadminAdd territory
PUT /publishers/{id}/territories/{territoryId}adminUpdate territory
DELETE /publishers/{id}/territories/{territoryId}adminDelete territory

Agreement Management:

EndpointRoleDescription
GET /publishers/{id}/agreementsuserList agreements
POST /publishers/{id}/agreementsadminCreate agreement
PUT /publishers/{id}/agreements/{agreementId}adminUpdate agreement
DELETE /publishers/{id}/agreements/{agreementId}adminDelete agreement

Sub-Publishing:

EndpointRoleDescription
POST /sub-publishingadminCreate sub-publishing agreement
GET /sub-publishinguserList sub-publishing agreements
GET /sub-publishing/{id}userGet agreement details
PUT /sub-publishing/{id}adminUpdate agreement
POST /sub-publishing/check-conflictsadminCheck territory conflicts

Writers (/writers)

EndpointRoleDescription
GET /writersuserList writers
POST /writersadminCreate writer
GET /writers/{id}userGet writer
PUT /writers/{id}adminUpdate writer
DELETE /writers/{id}adminDelete writer
GET /writers-with-user-datauserWriters with associated user data
POST /writers/{writerId}/works/{workId}adminAssign writer to work
DELETE /writers/{writerId}/works/{workId}adminRemove writer from work

Musical Works (/works)

EndpointRoleDescription
GET /worksuserList works
POST /worksadminCreate work
GET /works/{id}userGet work
PUT /works/{id}adminUpdate work
DELETE /works/{id}adminDelete work

Work-Recording Links:

EndpointRoleDescription
POST /works/{workId}/recordings/{assetId}adminLink work to recording
GET /works/{workId}/recordingsuserGet work's recordings
POST /works/{workId}/recordings/{assetId}/primaryadminSet primary recording
GET /works/{workId}/recordings/primaryuserGet primary recording
GET /works/recordings/{assetId}/worksuserGet recording's works

Work Registrations:

EndpointRoleDescription
POST /works/registrationsadminCreate/update registration
GET /works/registrationsuserList all registrations
GET /works/{workId}/registrationsuserGet work's registrations
GET /works/registrations/summaryuserRegistration summary
GET /works/registrations/{id}userGet registration details
DELETE /works/registrations/{id}adminDelete registration
PATCH /works/registrations/{id}/statusadminUpdate registration status

Work-Writer Relationships:

EndpointRoleDescription
GET /works/work-writersuserList work-writer relationships

CWR Export (/cwr)

EndpointRoleDescription
POST /cwr/exportadminExport CWR file
GET /cwr/status/{publisherId}userGet export status
POST /cwr/canceladminCancel export
POST /cwr/acknowledgmentadminProcess acknowledgment file (upload)
GET /cwr/works/registration-statususerGet work registration statuses
GET /cwr/works/{workId}/registrationuserGet work's CWR registration
PATCH /cwr/registrations/{registrationId}/statusadminUpdate registration status

14. Currency Management (/currencies)

Public Routes:

EndpointDescription
GET /currenciesList all supported currencies
GET /currencies/{code}Get currency details

Tenant Routes:

EndpointRoleDescription
GET /currencies/tenantuserGet tenant's enabled currencies
GET /currencies/tenant/defaultuserGet tenant's default currency
POST /currencies/tenant/{code}/enableadminEnable currency
POST /currencies/tenant/{code}/disableadminDisable currency
POST /currencies/tenant/{code}/defaultownerSet default currency

15. Billing & Subscriptions (/billing)

Subscription management with Stripe integration.

Current State:

EndpointRoleDescription
GET /billing/activeuserGet active subscription
GET /billing/sync-statususerSubscription sync status
GET /billing/usageuserUsage summary

Plans:

EndpointRoleDescription
GET /billing/plansuserList available plans
GET /billing/plans/stripeuserGet Stripe plans

Subscription Management:

EndpointRoleDescription
GET /billing/subscriptionsadminList subscriptions
GET /billing/subscriptions/{id}adminGet subscription
POST /billing/subscriptionsownerCreate subscription
POST /billing/subscriptions/{id}/cancelownerCancel subscription

Plan Changes:

EndpointRoleDescription
POST /billing/upgrade/checkout-sessionownerCreate Stripe checkout for upgrade
POST /billing/upgrade/{lookupKey}ownerDirect plan upgrade
POST /billing/downgradeownerDowngrade plan

Custom Invoices:

EndpointRoleDescription
POST /billing/invoices/customownerCreate custom invoice
PUT /billing/invoices/custom/{id}ownerUpdate custom invoice
DELETE /billing/invoices/custom/{id}ownerDelete custom invoice
POST /billing/invoices/custom/{id}/mark-paidownerMark invoice as paid
GET /billing/invoicesadminList invoices

Stripe Integration:

EndpointRoleDescription
POST /billing/portalownerCreate Stripe customer portal session
POST /billing/customer-sessionownerCreate Stripe customer session
POST /billing/refreshownerForce refresh subscription data

16. Custom Domains (/domains)

Cloudflare SaaS custom domain management.

EndpointRoleDescription
POST /domains/setupadminSetup custom domain
GET /domains/statususerGet domain status
GET /domains/instructionsuserGet DNS setup instructions
POST /domains/switch-validationadminSwitch validation method
POST /domains/restart-validationadminRestart domain validation
DELETE /domainsownerDelete custom domain
GET /domains/alladminList all domains

17. Admin Dashboard (/admin/dashboard)

Centralized admin dashboard for workspace management.

EndpointRoleDescription
GET /admin/dashboard/overviewadminDashboard overview metrics
GET /admin/dashboard/analyticsadminRelease analytics
GET /admin/dashboard/healthadminSystem health monitoring
GET /admin/dashboard/usersadminUser management data
POST /admin/dashboard/releases/bulk-actionownerBulk approve/reject releases
GET /admin/dashboard/configadminGet dashboard config
PUT /admin/dashboard/configownerUpdate dashboard config
GET /admin/dashboard/config/exportadminExport config JSON
POST /admin/dashboard/config/importownerImport config JSON
GET /admin/dashboard/workers/statsadminBackground worker statistics
POST /admin/dashboard/workers/{workerName}/pauseadminPause worker
POST /admin/dashboard/workers/{workerName}/resumeadminResume worker

18. Audit Trail (/api/audit)

Audit logging for compliance and security monitoring. Requires admin role.

EndpointRoleDescription
GET /api/auditadminList all audit trails
GET /api/audit/entity/{entityType}/{entityId}adminGet entity audit trail
GET /api/audit/user/{userId}/activityadmin/selfGet user activity (self-access allowed)
GET /api/audit/high-riskadminGet high-risk security events

19. Monitoring (/api/monitoring)

System monitoring for delivery pipelines and integrations.

FUGA Delivery Monitoring:

EndpointRoleDescription
GET /api/monitoring/fuga/metricsuserFUGA delivery metrics
GET /api/monitoring/fuga/healthuserFUGA health status
GET /api/monitoring/fuga/alertsuserFUGA alerts
GET /api/monitoring/fuga/stuck-deliveriesuserStuck deliveries
GET /api/monitoring/fuga/ftp-healthuserFTP connection health
PUT /api/monitoring/fuga/thresholdsadminUpdate alert thresholds

DDEX Registry Monitoring:

EndpointRoleDescription
GET /api/monitoring/registries/healthuserRegistry health
GET /api/monitoring/registries/adaptersuserAdapter health
GET /api/monitoring/registries/providersuserRegistered providers
GET /api/monitoring/registries/metricsuserAdapter metrics

Prometheus Metrics:

EndpointDescription
GET /api/monitoring/metrics/fugaPrometheus-compatible metrics endpoint

20. Webhooks

Outbound Webhooks (Royalti → Your Endpoint)

Configure your webhook endpoint via tenant settings:

# Set webhook URL
PUT /tenant/settings/webhook-url
{ "webhookUrl": "https://yourapp.com/webhooks/royalti" }

# Enable/disable webhooks
PUT /tenant/settings/webhook-isActive
{ "isActive": true }

# Subscribe to event types
PUT /tenant/settings/webhook-enabledEvents
{ "enabledEvents": ["PAYMENT_COMPLETED", "ROYALTY_FILE_PROCESSED"] }

Event Categories

Financial Events:

  • PAYMENT_COMPLETED, PAYMENT_PROCESSING, PAYMENT_MADE_FAILED
  • PAYMENT_REQUEST_SENT, PAYMENT_REQUEST_APPROVED, PAYMENT_REQUEST_REJECTED
  • PAYMENT_DELETED
  • REVENUE_CREATED, REVENUE_UPDATED, REVENUE_DELETED
  • EXPENSE_CREATED, EXPENSE_UPDATED, EXPENSE_DELETED

Catalog Events:

  • ASSET_CREATED, ASSET_UPDATED, ASSET_DELETED
  • PRODUCT_CREATED, PRODUCT_UPDATED, PRODUCT_DELETED

Roster Events:

  • USER_CREATED, USER_UPDATED, USER_DELETED
  • USER_INVITATION_SENT
  • ARTIST_CREATED, ARTIST_UPDATED, ARTIST_DELETED

Royalty Events (opt-in):

  • ROYALTY_FILE_UPLOADED
  • ROYALTY_FILE_PROCESSED
  • ROYALTY_FILE_PROCESSING_FAILED

Split Events:

  • USER_ADDED_TO_SPLIT
  • USER_REMOVED_FROM_SPLIT

Webhook Payload Structure

{
  "id": "whd_{uuid}",
  "event": "PAYMENT_COMPLETED",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "version": "1.0",
  "tenant": {
    "id": "tenant-uuid",
    "name": "My Label",
    "domain": "mylabel.royalti.io"
  },
  "source": {
    "service": "royalti-api",
    "environment": "production",
    "traceId": "trace-uuid"
  },
  "data": {
    "event": {
      "id": "evt-uuid",
      "type": "PAYMENT_COMPLETED",
      "category": "financial",
      "timestamp": "2025-01-15T10:30:00.000Z",
      "importance": "high"
    },
    "actor": {
      "id": "user-uuid",
      "type": "user",
      "name": "John Doe",
      "email": "[email protected]"
    },
    "resource": {
      "type": "payment",
      "id": "payment-uuid",
      "url": "https://app.royalti.io/payments/payment-uuid",
      "displayName": "Payment #1234"
    },
    "attributes": {
      "amount": 500.00,
      "currency": "USD",
      "recipientId": "user-uuid"
    },
    "previous": {}
  },
  "delivery": {
    "attempt": 1,
    "maxAttempts": 3,
    "nextRetryAt": "2025-01-15T10:35:00.000Z"
  }
}
  • previous is only populated on *_UPDATED events (contains pre-update values)
  • delivery.maxAttempts is 3 with exponential backoff
  • Financial and split events include HMAC signature for verification

HMAC Signature Validation

Financial and split webhook deliveries include an HMAC signature header for verification. Validate the signature before processing the payload.

Webhook Delivery Management

EndpointDescription
GET /webhook-deliveriesList deliveries (filterable by status, event type, date)
GET /webhook-deliveries/summaryDelivery stats
GET /webhook-deliveries/{id}Delivery details
POST /webhook-deliveries/{id}/retryRetry failed delivery

Delivery statuses: pending, success, failed, timeout, cancelled


21. WebSocket Events (Socket.io)

Real-time events for file processing and workflow progress.

Connection

import { io } from "socket.io-client";

const socket = io("wss://api.royalti.io", {
  auth: { token: "<access_token>" }
});

Events are user-scoped — only the user who uploaded the file receives processing events. Workflow events are emitted to the tenant room.

File Processing Events

EventWhen
file:processing:startedFile processing begins
file:processing:progressProgress update (~10% intervals)
file:processing:completedProcessing finished successfully
file:processing:failedProcessing failed

Workflow Events

EventWhen
workflow:promptWorkflow requires user input
workflow:step-startedWorkflow step begins
workflow:step-completeWorkflow step finishes
workflow:completedWorkflow finished

File Processing Event Payload

{
  "fileId": "file-uuid",
  "fileName": "spotify-2025-01.csv",
  "status": "processing",
  "progress": 75,
  "message": "Processing row 750 of 1000",
  "error": null,
  "metadata": {
    "rowsProcessed": 750,
    "source": "Spotify",
    "accountingPeriod": "2025-01",
    "salePeriod": "2025-01",
    "processingTimeMs": 45000
  }
}

22. Key Data Models

Tenant (Workspace)

id (integer), name, email, user (varchar — must be a TenantUser.id UUID),
status (active|inactive|suspended), plan, stripeCustomerId,
bigqueryDataset, domain, uid

Important: The user field on Tenants stores a TenantUser.id, not a User.id. This is used by API key auth resolution and accounting owner-exclusion. See "API Key Auth Resolution" in Section 1.

User (Global)

id (UUID), email, isVerified, isAdmin, provider, googleId, linkedinId, facebookId

A User can belong to multiple workspaces via TenantUser records.

TenantUser (Workspace-Scoped)

id (UUID), UserId (FK → User.id), TenantId (FK → Tenant.id),
firstName, lastName, email, nickName, profileImg,
role: main_super_admin | super_admin | owner | admin | user | guest,
userType, paymentSettings, permissions (JSONB),
ipi, externalId, country, phone, isActive

Key distinction: TenantUser.id is the workspace-scoped identity used throughout the API (splits, payments, accounting). User.id (UserId) is the global auth identity. API responses for /user/ return TenantUser records, not User records.

Artist

id (UUID), artistName, signDate, label, publisher, copyright,
externalId, artistImg, links {spotify, youtube, instagram, ...},
genres[], realName, pseudonyms, biography, influences,
instruments, activeYears, associatedActs, contributors

Asset (Track)

id (UUID), title, ISRC, type (Audio|Video|Ringtone|YouTube),
version, displayArtist, mainArtist[], mainGenre[], subGenre[],
explicit, language, tempo, key, mood[], lyrics,
label, copyright, publisher, copyrightOwner,
recordingDate, recordingLocation, productionYear,
enableDDEX, focusTrack, ddexMetadata, resourceReference

Product (Release)

id (UUID), title, UPC, format (Single|EP|Album|LP),
release_date, takedown_date, label, display_artist,
type (Audio|Video), catalog_number, version, explicit,
main_genre, sub_genre, status (active|inactive|pending|Live|Taken Down|Scheduled|Error),
distribution, external_id

Split

id, entity_type (artist|product|asset), entity_id,
split_type (simple|conditional|temporal),
effective_date,
shares: [{ user: UUID, percentage: 0-100 }],
conditions: { territories[], mode, sources[], period_start, period_end, memo }

Transaction

id (UUID), type (payment|royalty|expense|adjustment),
amount, currency, status (pending|processed|failed),
reference, metadata

TenantRoyaltySource

id (UUID), name, displayName, type (dsp|distributor|custom),
salesDataQuery (BigQuery SQL), extractionQueries[],
periodConfig { type, format, startField, endField },
feeRate, currency, isActive, parentSourceId, version

TenantDataShare

id (UUID), sourceTenantId, targetTenantId,
sourceId, status (active|inactive),
sharedColumns[], filters

Publisher

id (UUID), name, ipiNumber, ipiNameNumber,
territories[], agreements[],
type (original|sub), parentPublisherId

Writer

id (UUID), firstName, lastName, ipiNumber, ipiNameNumber,
prAffiliation, mrAffiliation, srAffiliation,
writerDesignationCode, citizenshipCountry

Work (Musical Work)

id (UUID), title, iswc, alternativeTitles[],
writers[] (with shares), publishers[] (with shares),
recordings[] (linked assets), registrations[]

23. Common Integration Patterns

Sync Catalog from External System

1. POST /artist/bulk          → Create artists
2. POST /product/bulk         → Create products
3. POST /asset/bulk           → Create assets/tracks
4. POST /split/               → Assign splits per entity
5. POST /accounting/refresh   → Recalculate accounting

Upload and Process Royalty File

1. GET  /file/upload-url               → Get presigned upload URL
2. PUT  <presigned_url>                 → Upload file to cloud storage
3. POST /file/confirm-upload-completion → Notify API upload is done
4. GET  /file/detection/{sessionId}     → Poll auto-detection (or listen via WebSocket)
5. POST /file/confirm-detection/{sessionId} → Confirm detected format
   If unknown source:
   POST /file/session/{sessionId}/start-source-creator → Bridge to Source Creator
6. GET  /file/processing/{jobId}        → Poll processing status
   OR subscribe to WebSocket: file:processing:progress
7. POST /accounting/refresh             → Recalculate after processing

Create a New Royalty Source (Source Creator)

1. POST /source-creator/analyze              → Upload & analyze file
2. POST /source-creator/ai-map-columns       → Get AI mapping suggestions
3. PUT  /source-creator/sessions/{id}/mappings → Confirm column mappings
4. PUT  /source-creator/sessions/{id}/periods  → Confirm periods
5. POST /source-creator/generate-queries      → Generate BigQuery SQL
6. POST /source-creator/test-queries          → Sandbox validation
7. POST /source-creator/save                  → Save as draft

DDEX Release Distribution

1. POST /ddex/tenant-providers                → Configure DSP provider
2. POST /ddex/delivery/test-connection        → Verify connection
3. POST /ddex/ern/generate { releaseId }      → Generate ERN
4. POST /ddex/messages/{id}/validate          → Validate
5. POST /ddex/delivery/deliver/{id}           → Deliver to DSP
6. GET  /ddex/delivery/status/{id}            → Monitor

Data Quality Checklist

1. GET /checklist/royaltyassets          → Find missing catalog items
2. POST /checklist/royaltyassets/import  → Import them
3. POST /checklist/assets/enrich         → Enrich with metadata
4. POST /checklist/enrichment/approve    → Approve enrichments
5. GET /checklist/missingroyaltysplits   → Find unsplit royalties
6. POST /checklist/workflow              → Start automated workflow

Fetch Analytics Dashboard Data

1. GET /royalty/?start=2025-01-01&end=2025-12-31              → Overview
2. GET /royalty/month?start=2025-01-01&end=2025-12-31         → Monthly trend
3. GET /royalty/dsp?start=2025-01-01&end=2025-12-31           → Platform breakdown
4. GET /royalty/country?start=2025-01-01&end=2025-12-31       → Geographic breakdown
5. GET /royalty/asset?start=2025-01-01&end=2025-12-31&size=10 → Top tracks

Set Up Webhook Listener

1. PUT /tenant/settings/webhook-url          → Set your endpoint
2. PUT /tenant/settings/webhook-enabledEvents → Choose event types
3. PUT /tenant/settings/webhook-isActive     → Enable
4. GET /webhook-deliveries                   → Monitor deliveries
5. POST /webhook-deliveries/{id}/retry       → Retry failures

Release Lifecycle

1. POST /releases                          → Create draft release
2. POST /releases/{id}/media/files         → Upload artwork
3. POST /releases/{id}/tracks              → Add tracks
4. POST /releases/{id}/tracks/{trackId}/media/file → Upload audio
5. POST /releases/{id}/tracks/reorder      → Set track order
6. POST /releases/{id}/submit              → Submit for review
7. POST /releases/{id}/review              → Admin reviews
8. POST /releases/{id}/feedback            → Admin feedback (optional)
   OR POST /ddex/ern/generate              → Generate DDEX for distribution

24. Code Examples

Language-specific integration examples are available in the references/ directory:

  • references/examples-javascript.md — Node.js/TypeScript client, auth, CRUD, file upload, WebSocket, Express webhook receiver
  • references/examples-python.md — Python client, auth, pagination, file upload, Flask webhook receiver, socketio
  • references/examples-php.md — PHP client, auth, pagination, file upload, Laravel and plain PHP webhook receivers

Load these files when the developer is working in a specific language.

25. Troubleshooting

Common Errors

Error MessageHTTP CodeCauseFix
"Workspace user not found"404API key's workspace has Tenants.user pointing to wrong ID (UserId instead of TenantUserId), or no owner TenantUser existsVerify Tenants.user matches a TenantUser.id where role='owner' for that workspace
"Workspace not found"404Tenant doesn't exist or status != 'active'Check tenant status in admin panel
"Authorization token is missing"401No Authorization header or malformed tokenEnsure Authorization: Bearer <token> header is present
"Route does not exist"Wrong URL path (e.g., /api/users instead of /user/)Check endpoint paths — no /api prefix, resource names are singular
"Access denied"403Token valid but user lacks required role for endpointCheck RBAC requirements for the endpoint

Endpoint Path Gotchas

  • Paths use singular nouns: /user/, /artist/, /asset, /product/
  • Exceptions: /labels/, /releases, /notifications/, /publishers, /writers
  • Most paths require a trailing slash: /user/ not /user
  • No /api prefix — endpoints are at the root: https://api.royalti.io/artist/
  • Sources endpoint: /file/sources (nested under files, not standalone)

26. Further Reading

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.