SDKs

Official SDKs wrap the MASK REST API with idiomatic methods, automatic retries, type-safe responses, and built-in pagination. Use them to integrate MASK into your application without dealing with raw HTTP requests.

SDKLanguagePackageStatus
Node.jsTypeScript / JavaScript@mask/sdkOfficial
PythonPython 3.8+mask-sdkOfficial

Node.js

The Node.js SDK supports Node.js 18+ and is written in TypeScript with full type definitions included. It works with both ESM and CommonJS.

Installation

npm
npm install @mask/sdk
pnpm
pnpm add @mask/sdk

Configuration

Initialize the client
import { Mask } from "@mask/sdk";

const mask = new Mask({
  apiKey: process.env.MASK_API_KEY,  // mk_live_...
});

Usage examples

Create a link
const link = await mask.links.create({
  url: "https://example.com/my-page",
  slug: "my-link",
  tags: ["campaign-q1"],
  utm_source: "twitter",
});

console.log(link.short_url);
// => "https://mask.pk/my-link"
List links with pagination
const { data, pagination } = await mask.links.list({
  limit: 10,
  tag: "campaign-q1",
});

for (const link of data) {
  console.log(link.slug, link.clicks);
}

// Fetch next page
if (pagination.has_more) {
  const nextPage = await mask.links.list({
    limit: 10,
    cursor: pagination.cursor,
  });
}
Get analytics
const clicks = await mask.analytics.clicks({
  linkId: "lnk_abc123",
  groupBy: "country",
  start: "2026-03-01",
  end: "2026-03-31",
});

for (const row of clicks.data) {
  console.log(row.country, row.clicks);
}
Create a QR code
const qr = await mask.qrCodes.create({
  link_id: "lnk_abc123",
  foreground_color: "#1a1a1a",
  size: 1024,
  error_correction: "H",
});

// Download as PNG buffer
const imageBuffer = await mask.qrCodes.download(qr.id, {
  format: "png",
});

Python

The Python SDK supports Python 3.8+ and provides both synchronous and asynchronous clients. Type hints are included for all methods and response objects.

Installation

pip
pip install mask-sdk

Configuration

Initialize the client
from mask import MaskClient

client = MaskClient(api_key="mk_live_...")

# Or use an environment variable (recommended)
import os
client = MaskClient(api_key=os.environ["MASK_API_KEY"])

Usage examples

Create a link
link = client.links.create(
    url="https://example.com/my-page",
    slug="my-link",
    tags=["campaign-q1"],
    utm_source="twitter",
)

print(link.short_url)
# => "https://mask.pk/my-link"
List links with pagination
response = client.links.list(limit=10, tag="campaign-q1")

for link in response.data:
    print(link.slug, link.clicks)

# Fetch next page
if response.pagination.has_more:
    next_page = client.links.list(
        limit=10,
        cursor=response.pagination.cursor,
    )
Get analytics
clicks = client.analytics.clicks(
    link_id="lnk_abc123",
    group_by="country",
    start="2026-03-01",
    end="2026-03-31",
)

for row in clicks.data:
    print(row["country"], row["clicks"])
Async client
from mask import AsyncMaskClient

async_client = AsyncMaskClient(api_key="mk_live_...")

link = await async_client.links.create(
    url="https://example.com",
    slug="async-link",
)

print(link.short_url)

Error handling

Both SDKs throw typed exceptions for API errors. Catch specific error types to handle different failure modes.

Node.js error handling
import { Mask, MaskError, RateLimitError, ValidationError } from "@mask/sdk";

try {
  const link = await mask.links.create({ url: "invalid-url" });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error("Validation failed:", error.details);
  } else if (error instanceof RateLimitError) {
    console.error("Rate limited. Retry after:", error.retryAfter, "seconds");
  } else if (error instanceof MaskError) {
    console.error("API error:", error.code, error.message);
  }
}
Python error handling
from mask.exceptions import MaskError, RateLimitError, ValidationError

try:
    link = client.links.create(url="invalid-url")
except ValidationError as e:
    print(f"Validation failed: {e.details}")
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after} seconds")
except MaskError as e:
    print(f"API error: {e.code} {e.message}")

Automatic retries

Both SDKs automatically retry failed requests on network errors and 429 / 5xx responses with exponential backoff. By default, up to 3 retries are attempted. You can configure this behavior:

Configure retries (Node.js)
const mask = new Mask({
  apiKey: process.env.MASK_API_KEY,
  maxRetries: 5,        // default: 3
  timeout: 30_000,      // request timeout in ms (default: 10000)
});
Configure retries (Python)
client = MaskClient(
    api_key="mk_live_...",
    max_retries=5,       # default: 3
    timeout=30.0,        # request timeout in seconds (default: 10.0)
)