royalti-api

Royalti.io REST API v2.6 pattern reference for developers. Covers authentication, CRUD patterns, pagination, error handling, webhooks, WebSocket events, and data models. Use when helping developers integrate with the Royalti API (api.royalti.io) or when writing integration code, API documentation, or troubleshooting API issues.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "royalti-api" with this command: npx skills add royalti-io/royalti-api-skill/royalti-io-royalti-api-skill-royalti-api

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": "user@example.com", "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..."

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
  • Other endpoints: No documented limits (subject to fair use)

RBAC Roles (ascending privilege)

guest < user < admin < owner < super_admin < main_super_admin

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

{
  "status": "success",
  "data": [ ... ],
  "totalItems": 142,
  "totalPages": 15,
  "currentPage": 1
}

Summary Response (v2.6.4+)

Available on: /artist/summary, /asset/summary, /product/summary, /user/summary, /split/summary, /payment/summary, /expense/summary, /revenue/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, already exists)
422Unprocessable entity
429Rate limited (login endpoint)
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
GET /artist/{id}/statsArtist analytics
POST /artist/{id}/mergeMerge duplicate artists
POST /artist/bulksplitBulk assign splits

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.).

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
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

Labels (/labels/)

Standard CRUD plus:

EndpointDescription
GET /labels/hierarchyLabel tree structure

Releases (/releases)

Full release lifecycle:

EndpointDescription
POST /releasesCreate release (draft)
POST /releases/{id}/submitSubmit for review
POST /releases/{id}/reviewStart review
POST /releases/{id}/approveApprove release
POST /releases/{id}/rejectReject release
POST /releases/{id}/tracksAdd track to release
GET /releases/{id}/tracksGet release tracklist
GET /releases/{id}/statsRelease statistics

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. 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": "john@label.com"
    },
    "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


6. WebSocket Events (Socket.io)

Real-time events for file processing 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.

File Processing Events

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

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
  }
}

7. Key Data Models

User (Global)

id, email, isVerified, isAdmin, provider, googleId, linkedinId, facebookId

TenantUser (Workspace-Scoped)

id, UserId, TenantId, firstName, lastName,
role: main_super_admin | super_admin | owner | admin | user | guest,
userType, paymentSettings, permissions (JSONB)

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

8. 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
6. GET  /file/processing/{jobId}        → Poll processing status
   OR subscribe to WebSocket: file:processing:progress
7. POST /accounting/refresh             → Recalculate after processing

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

9. 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.

10. Further Reading

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated
Coding

ask-claude

Delegate a task to Claude Code CLI and immediately report the result back in chat. Supports persistent sessions with full context memory. Safe execution: no data exfiltration, no external calls, file operations confined to workspace. Use when the user asks to run Claude, delegate a coding task, continue a previous Claude session, or any task benefiting from Claude Code's tools (file editing, code analysis, bash, etc.).

Archived SourceRecently Updated
Coding

ai-dating

This skill enables dating and matchmaking workflows. Use it when a user asks to make friends, find a partner, run matchmaking, or provide dating preferences/profile updates. The skill should execute `dating-cli` commands to complete profile setup, task creation/update, match checking, contact reveal, and review.

Archived SourceRecently Updated
Coding

clawhub-rate-limited-publisher

Queue and publish local skills to ClawHub with a strict 5-per-hour cap using the local clawhub CLI and host scheduler.

Archived SourceRecently Updated