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

@sharecontent/sdk

v1.0.5

Published

TypeScript SDK for ShareContent API - Complete API client for short links, analytics, ads, folders, and files

Downloads

16

Readme

sharecontent

TypeScript SDK for the ShareContent API - Complete client for short links, analytics, ads, folders, and files.

Installation

npm install @sharecontent/sdk
# or
yarn add @sharecontent/sdk
# or
pnpm add @sharecontent/sdk

Quick Start

import ShareContent from '@sharecontent/sdk';

// Initialize the SDK
const client = new ShareContent({
  token: 'your-jwt-or-api-token', // Optional, can be set later
});

// Create a short link
const shortLink = await client.shortLinks.create({
  url: 'https://example.com',
  title: 'My Link',
  short_code: 'my-link',
});

// The response includes short_url with the complete shortened URL
console.log(shortLink.short_url); // Ex: 'https://sharecontent.io/x/my-link'

Configuration

Basic Configuration

import ShareContent from '@sharecontent/sdk';

const client = new ShareContent({
  timeout: 30000, // Optional, default: 30000ms
  token: 'your-token',
  projectId: 'project-uuid' // Optional, to scope requests by project
});

Authentication

The SDK supports API Tokens

To get an API Key: Visit https://sharecontent.io/dashboard/api-tokens to create an API token.

// Set token on initialization
const client = new ShareContent({
  token: 'your-jwt-or-api-token',
  projectId: 'project-uuid', // Optional
});

// Or set it later
client.setToken('your-token');
client.setProjectId('project-uuid');

// Clear project (uses default project)
client.clearProjectId();

API Reference

Projects

All entities (links, ads, folders, etc.) are scoped by project. Use projectId to specify which project to use in requests.

// Set project on initialization
const client = new ShareContent({
  token: 'your-token',
  projectId: 'project-uuid'
});

// Or set it later
client.setProjectId('project-uuid');

// Clear project (uses default project automatically)
client.clearProjectId();

Note: If projectId is not provided, the system will automatically use the user's default project.

Shortened URLs and Custom Domains

All responses from creating or updating links include the short_url attribute, which contains the complete shortened URL ready to use. The short_url automatically considers:

  • Custom domains: If you specify the domain property when creating a link, the short_url will be built using that custom domain (ex: https://mydomain.com/ABC123)
  • Default domain: If no custom domain is specified, the short_url will use the platform's default domain (ex: https://sharecontent.io/x/ABC123)

Short Links

Check Code Availability

const result = await client.shortLinks.checkCode('my-code');
// Response: { available: boolean }

Create Short Link

const shortLink = await client.shortLinks.create({
  url: 'https://example.com',
  title: 'My Link Title', // Optional
  short_code: 'my-link', // Optional
  folder_id: 'folder-uuid', // Optional
  utm_source: 'twitter', // Optional
  utm_campaign: 'promo', // Optional
  show_ads: true, // Optional
  content_type: 'link', // Optional: 'link' | 'text' | 'file'
  expires_in_days: 30, // Optional
  public_analytics: true, // Optional
  domain: 'mydomain.com', // Optional: use custom domain
});

// The response includes short_url with the complete shortened URL
console.log(shortLink.short_url); // Ex: 'https://mydomain.com/my-link' or 'https://sharecontent.io/x/my-link'

Create Text Content

const textLink = await client.shortLinks.create({
  content_type: 'text',
  content_text: 'This is my text content',
  title: 'My Text', // Optional
  content_password: 'password123', // Optional
  expire_after_view: true, // Optional
  domain: 'mydomain.com', // Optional: use custom domain
});

// The response includes short_url with the complete shortened URL
console.log(textLink.short_url); // Ex: 'https://mydomain.com/ABC123' or 'https://sharecontent.io/x/ABC123'

List Short Links

const links = await client.shortLinks.list({
  folder_id: 'folder-uuid', // Optional
  search: 'keyword', // Optional
  sort_by: 'recent', // Optional: 'recent' | 'oldest' | 'most_viewed'
  content_type: 'link', // Optional: 'link' | 'text' | 'file'
  page: 1, // Optional
  limit: 10, // Optional
});

// Response: { data: ShortLink[], total: number, page: number, limit: number }
// Each ShortLink in the list includes short_url if it was created/updated recently
links.data.forEach(link => {
  if (link.short_url) {
    console.log(`${link.title}: ${link.short_url}`);
  }
});

Get Short Link

const link = await client.shortLinks.get('my-code');
// Response varies according to content type (link, text, or file)

Update Short Link

const updated = await client.shortLinks.update('link-id', {
  url: 'https://new-url.com',
  title: 'New Title',
  show_ads: false,
});

// The response includes short_url with the updated complete shortened URL
console.log(updated.short_url); // Ex: 'https://mydomain.com/my-link' or 'https://sharecontent.io/x/my-link'

Move to Folder

const result = await client.shortLinks.moveToFolder('link-id', {
  folder_id: 'folder-uuid', // or null to remove from folder
});

Update Title

const result = await client.shortLinks.updateTitle('link-id', {
  title: 'New Title', // or null to remove
});

Verify Password (for protected content)

const result = await client.shortLinks.verifyPassword('code', {
  password: 'password123',
});

// Response: { success: boolean, token: string, content_text?: string, view_token: string }

Confirm View

const result = await client.shortLinks.confirmView('code', {
  view_token: 'token-from-previous-request',
});

Delete Short Link

const result = await client.shortLinks.delete('link-id');
// Response: { message: string }

Folders

Create Folder

const folder = await client.folders.create({
  name: 'My Folder',
});

List Folders

const folders = await client.folders.list();
// Response: Folder[]

Update Folder

const updated = await client.folders.update('folder-id', {
  name: 'New Folder Name',
});

Delete Folder

const result = await client.folders.delete('folder-id');
// Response: { message: string }

Ads

Create Ad

const ad = await client.ads.create({
  name: 'My Ad',
  description: 'Ad description',
  product_url: 'https://example.com/product',
  product_name: 'Product Name', // Optional
  is_active: false, // Optional
  delay_seconds: 5, // Optional, 1-30
  button_text: 'Buy Now', // Optional
  button_bg_color: '#2563eb', // Optional
  page_bg_color: '#111827', // Optional
  image_desktop: fileObject, // Optional, File or Blob
  image_mobile: fileObject, // Optional, File or Blob
});

List Ads

const ads = await client.ads.list();
// Response: Ad[]

Get Ad

const ad = await client.ads.get('ad-id');

Update Ad

const updated = await client.ads.update('ad-id', {
  name: 'Updated Ad Name',
  delay_seconds: 10,
  // ... other optional fields
});

Toggle Active Status

const result = await client.ads.toggleActive('ad-id', {
  is_active: true,
});

Delete Ad

const result = await client.ads.delete('ad-id');
// Response: { message: string }

Analytics

Get General Analytics

const analytics = await client.analytics.getGeneral();
// Response: {
//   anuncios: AnalyticsAd[],
//   totals: { totalViews, totalClicks, totalCtr },
//   shortLinks: { total, totalViews, totalDownloads },
//   detailed: { operatingSystems, browsers, deviceTypes, topCountries }
// }

Get Link Analytics

const linkAnalytics = await client.analytics.getByLink('link-code');
// Response: {
//   slug: string,
//   totalViews: number,
//   uniqueViews: number,
//   viewsByDay: Record<string, number>,
//   topCountries: Array<{ country: string, views: number }>,
//   deviceTypes: Record<string, number>,
//   browsers: Record<string, number>
// }

Get Ad Analytics

const adAnalytics = await client.analytics.getByAd('ad-id');
// Response: {
//   id: string,
//   name: string,
//   views: number,
//   clicks: number,
//   ctr: number,
//   operatingSystems: Record<string, number>,
//   browsers: Record<string, number>,
//   deviceTypes: Record<string, number>,
//   topCountries: Array<{ country: string, views: number }>,
//   ...
// }

Files

Upload File

const fileLink = await client.files.upload({
  file: fileObject, // File or Blob
  title: 'My File', // Optional
  short_code: 'my-file', // Optional
  folder_id: 'folder-uuid', // Optional
  content_password: 'password123', // Optional
  expires_in_days: 7, // Optional
  show_ads: true, // Optional
  expire_after_view: false, // Optional
  domain: 'mydomain.com', // Optional: use custom domain
});

// The response includes short_url with the complete shortened URL
console.log(fileLink.short_url); // Ex: 'https://mydomain.com/my-file' or 'https://sharecontent.io/x/my-file'

Download File

const { blob, filename, contentType } = await client.files.download(
  'file-code',
  'password-token' // Optional, if the file is password protected
);

// Use the blob to create a download link or save the file
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename || 'download';
a.click();

Verify File Password

const result = await client.files.verifyPassword('file-code', {
  password: 'password123',
});

// Response: { success: boolean, token: string, view_token: string, file_name: string, ... }
// Use the token for subsequent download requests

Ad Clicks

Register Ad Click

const result = await client.adClick.register({
  anuncio_id: 'ad-uuid',
  short_link_id: 'link-uuid',
  click_type: 'button', // Optional: 'button' | 'image', default: 'button'
});

// Response: { message: string }

Custom Domains

Custom domains allow you to use your own domain for short links. All endpoints require authentication and the X-Project-Id header (automatically managed by the SDK if you configured projectId).

List Custom Domains

const domains = await client.customDomains.list();
// Response: CustomDomain[]

// Example response:
// [
//   {
//     id: 'uuid',
//     domain: 'example.com',
//     root_domain: 'example.com',
//     verification_token: 'abc123...',
//     is_verified: true,
//     is_active: true,
//     ssl_certificate_status: 'active',
//     created_at: '2024-01-01T00:00:00.000Z',
//     ...
//   }
// ]

Create Custom Domain

const domain = await client.customDomains.create({
  domain: 'example.com', // or 'links.example.com' for subdomain
});

// Response: CustomDomain with verification_token
// After creating, you need to verify the domain via DNS
console.log('Verification token:', domain.verification_token);

Note: After creating the domain, you need to add a TXT DNS record:

  • Name: sharecontent (or sharecontent.example.com for subdomains)
  • Value: The verification_token returned in the response

Verify Domain via DNS

const result = await client.customDomains.verify('domain-id');

// Response: { verified: boolean, domain?: CustomDomain, message?: string, code?: string }

if (result.verified) {
  console.log('Domain verified successfully!');
  console.log('Active domain:', result.domain?.is_active);
} else {
  console.log('Domain not verified:', result.message);
  // Check if the TXT DNS record was configured correctly
}

Verification process:

  1. The system searches for a TXT DNS record at sharecontent.<domain> or sharecontent.<root-domain>
  2. The TXT record value must match the domain's verification_token
  3. If found, the domain is marked as verified and activated automatically

Delete Custom Domain

const result = await client.customDomains.delete('domain-id');
// Response: { message: string }

Check if Domain is in Use (Public)

const check = await client.customDomains.check('example.com');

// Response: { exists: boolean, user_id?: string, is_active?: boolean, is_verified?: boolean, domain_id?: string }

if (check.exists) {
  console.log('Domain is already in use');
} else {
  console.log('Domain available');
}

Note: This endpoint is public and does not require authentication. It is used internally by the routing system.

Domain Limits by Plan

  • Free: Limit based on plan (check your current plan)
  • Agency: Unlimited domains

If you reach the limit, you will receive a 403 error with code CUSTOM_DOMAIN_LIMIT_REACHED when trying to create a new domain.

Root Domain Ownership

Once a user verifies a root domain (ex: example.com), they become the owner of that root domain. This means:

  • The same user can add subdomains (ex: links.example.com) without new verification
  • Other users cannot use the same root domain
  • If you delete all domains of a root, ownership is released

Error Handling

The SDK provides custom error classes for different scenarios:

import {
  ShareContentError,
  ShareContentAuthError,
  ShareContentRateLimitError,
  ShareContentValidationError,
  ShareContentNotFoundError,
  ShareContentServerError,
} from '@sharecontent/sdk';

try {
  await client.shortLinks.create({ url: 'invalid' });
} catch (error) {
  if (error instanceof ShareContentAuthError) {
    console.error('Authentication failed:', error.message);
  } else if (error instanceof ShareContentRateLimitError) {
    console.error('Rate limit exceeded. Try again after:', error.retryAfter, 'seconds');
  } else if (error instanceof ShareContentValidationError) {
    console.error('Validation errors:', error.errors);
  } else if (error instanceof ShareContentNotFoundError) {
    console.error('Resource not found:', error.message);
  } else if (error instanceof ShareContentServerError) {
    console.error('Server error:', error.message);
  } else if (error instanceof ShareContentError) {
    console.error('API error:', error.message, 'Status:', error.statusCode);
  }
}

TypeScript Support

The SDK is fully typed with TypeScript. All request and response types are exported:

import type {
  ShortLink,
  Folder,
  Ad,
  ContentType,
  EditPermission,
  SortBy,
  // ... and many others
} from '@sharecontent/sdk';

Advanced Usage

Access Axios Instance

For advanced use cases, you can access the underlying axios instance:

const axiosInstance = client.getAxiosInstance();
// Use axiosInstance for custom requests

Use API Classes Individually

You can also use the API classes directly:

import { ShareContentClient, ShortLinksAPI } from '@sharecontent/sdk';

const client = new ShareContentClient({ token: 'your-token' });
const shortLinks = new ShortLinksAPI(client.getAxiosInstance());

const link = await shortLinks.create({ url: 'https://example.com' });

Browser and Node.js Support

The SDK works in both browser and Node.js environments.

Note for Node.js users:

  • Node.js 18+ has native FormData support, so file uploads work without additional configuration
  • For Node.js < 18, you may need to install the form-data package and convert files appropriately
  • The SDK uses the global FormData that is available in modern Node.js versions

License

ISC

Support

For API documentation and support, visit the ShareContent API documentation.