npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@royaltyport/sdk

v0.2.0

Published

Official Node.js SDK for the Royaltyport API

Readme

@royaltyport/sdk

Official Node.js SDK for the Royaltyport API. List projects, query catalog data, upload contracts and statements, and search across project resources.

Documentation

Full SDK reference available at docs.royaltyport.com/sdk-reference.

Requirements

  • Node.js >= 18.0.0

Installation

npm install @royaltyport/sdk

Quick Start

import { Royaltyport } from '@royaltyport/sdk';

const royaltyport = new Royaltyport({
  apiKey: 'rp_your_token_here',
});

// List all projects
const { data: projects } = await royaltyport.projects.list();
for (const project of projects) {
  console.log(project.name);
}

// List artists in a project
const { data } = await royaltyport.artists.list(projects[0].id, { perPage: 50 });
for (const artist of data.items) {
  console.log(artist.name);
}

Authentication

The apiKey option accepts both API tokens (rp_ prefix) and OAuth access tokens. API tokens are created in Organizations > Settings > Tokens in the Royaltyport platform.

The SDK does not auto-read environment variables. To use one, pass it explicitly:

import { Royaltyport } from '@royaltyport/sdk';

const royaltyport = new Royaltyport({
  apiKey: process.env.ROYALTYPORT_TOKEN,
});

| Variable | Description | |----------|-------------| | ROYALTYPORT_TOKEN | API token or OAuth access token | | ROYALTYPORT_API_URL | Custom API base URL (default: https://api.royaltyport.com) |

Configuration

import { Royaltyport } from '@royaltyport/sdk';

const royaltyport = new Royaltyport({
  apiKey: 'rp_your_token_here',       // Required
  baseUrl: 'https://api.example.com', // Optional — defaults to https://api.royaltyport.com
  fetch: customFetch,                 // Optional — custom fetch implementation
});

Resources

| Resource | Methods | Description | |----------|---------|-------------| | royaltyport.projects | list, get | Projects | | royaltyport.artists | list, get | Artists (with merge history) | | royaltyport.writers | list, get | Writers (with merge history) | | royaltyport.recordings | list, get | Recordings (with products) | | royaltyport.compositions | list, get | Compositions (with products) | | royaltyport.entities | list, get | Entities (with merge history) | | royaltyport.relations | list, get | Relations (with merge history) | | royaltyport.contracts | list, get, upload, download, processes | Contracts with upload, download, and processing status | | royaltyport.statements | list, get, upload, download, processes | Statements with upload, download, and processing status | | royaltyport.search() | — | Cross-resource search |

File Uploads

upload() accepts a file path, Buffer, Uint8Array, or Blob. Files must be PDFs of at most 50 MB — enforced locally before any request and re-validated server-side against the real bytes.

// Statements
const { data } = await royaltyport.statements.upload(projectId, './statement.pdf');
console.log(data); // { staging_id: 123, status: 'uploaded', file_path: '...' }

// Contracts, with optional extractions
const { data: contract } = await royaltyport.contracts.upload(projectId, './contract.pdf', {
  extractions: ['extract-dates', 'extract-royalties'],
});

Behind a single upload() call the SDK mints a signed storage URL, PUTs the file bytes directly to storage, and completes the upload. Upload progress events are no longer emitted — poll processes() for staging progress instead:

const { data: status } = await royaltyport.statements.processes(projectId, data.staging_id);

If the flow fails after the file bytes reached storage, the SDK throws RoyaltyportUploadError with a step ('put' or 'complete') and the stagingId. On a 'complete' failure the bytes are already stored — completion can be re-run manually via POST /v1/{statements|contracts}/uploads/complete with that stagingId.

Error Handling

import {
  Royaltyport,
  RoyaltyportAuthenticationError,
  RoyaltyportRateLimitError,
  RoyaltyportValidationError,
} from '@royaltyport/sdk';

const royaltyport = new Royaltyport({
  apiKey: 'rp_your_token_here',
});

try {
  const { data } = await royaltyport.projects.list();
} catch (error) {
  if (error instanceof RoyaltyportAuthenticationError) {
    // 401 — invalid or expired token
  } else if (error instanceof RoyaltyportRateLimitError) {
    // 429 — rate limit exceeded (auto-retried up to 3x)
  } else if (error instanceof RoyaltyportValidationError) {
    // 400 — invalid parameters
  }
}

The SDK automatically retries 429 and 5xx errors up to 3 times with exponential backoff.

TypeScript

The SDK is written in TypeScript and ships with full type definitions. You get autocomplete and type checking out of the box — no additional @types packages needed.

Agent Skill

This repo includes a skills.sh-compatible skill that teaches AI agents how to use the SDK to query and manage Royaltyport project data programmatically.

Install it into your agent:

npx skills add royaltyport/royaltyport-sdk

The skill covers client setup, resource queries, file uploads, search patterns, and error handling — everything an agent needs to interact with the Royaltyport API via the SDK.

License

MIT