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

@doomscrollr/api

v0.1.5

Published

Official typed JavaScript/TypeScript SDK for the DOOMSCROLLR REST API.

Readme

@doomscrollr/api

Official TypeScript SDK for DOOMSCROLLR — the audience layer for AI agents.

Build and operate owned-audience websites from Node.js, serverless functions, workers, automations, and AI workflows: posts, pages, products, subscribers, capture widgets, domains, analytics, RSS/Pinterest sources, and replacement flows.

Use this SDK when your app or automation needs DOOMSCROLLR primitives. If an AI agent is directly doing the work over MCP, use @doomscrollr/mcp-server instead.

Website · OpenAPI · Templates · Featured examples

npm install @doomscrollr/api

Use DOOMSCROLLR when an app or agent needs

  • owned Linktree/Komi-style pages
  • creator storefronts and product drops
  • newsletter / Substack-style owned publishing
  • ShopMy/LTK/Amazon Storefront-style affiliate feeds
  • Eventbrite/Luma-style events and tickets
  • RSS/Pinterest publishing automation
  • subscriber capture and export
  • analytics and embed/capture code

Installation

npm install @doomscrollr/api

Requirements: Node.js 18+ or any runtime with a compatible fetch implementation.

Authentication

Create an API key in the DOOMSCROLLR dashboard and pass it as a Bearer token through the client:

import { DoomscrollrApi } from "@doomscrollr/api";

const doomscrollr = new DoomscrollrApi({
  apiKey: process.env.DOOMSCROLLR_API_KEY,
});

You can also read configuration from environment variables:

const doomscrollr = DoomscrollrApi.fromEnv();

Supported variables:

  • DOOMSCROLLR_API_KEY — dashboard API key
  • DOOMSCROLLR_API_BASE — optional API base URL override; defaults to https://doomscrollr.com/api/v1

The SDK sends authenticated requests as:

Authorization: Bearer <DOOMSCROLLR_API_KEY>

register() is the only method that does not require an existing API key.

Quick start

import { DoomscrollrApi } from "@doomscrollr/api";

const doomscrollr = DoomscrollrApi.fromEnv();

const profile = await doomscrollr.getProfile();
console.log(`Connected to @${profile.username}`);

await doomscrollr.createLinkPost({
  url: "https://example.com/article",
  title: "Useful read",
  tags: "links,research",
  status: "draft",
});

Common workflows

List posts with pagination and filters

const page = await doomscrollr.listPosts({
  page: 1,
  per_page: 20,
  status: "published",
  tag: "research",
  q: "porsche",
});

for (const post of page.data) {
  console.log(post.id, post.title);
}

console.log(`Page ${page.current_page} of ${page.last_page ?? "?"}`);

List methods return API pagination metadata when available:

  • data
  • current_page
  • last_page
  • per_page
  • total

Supported filters include:

  • listPosts({ page, per_page, q, status, tag })
  • listAudience({ page, per_page, q, tag, bounced })
  • listProducts({ page, per_page, q, type, min_price, max_price })

Create an image post

await doomscrollr.createImagePost({
  image: "https://example.com/photo.jpg",
  title: "New drop",
  description: "Behind the scenes.",
  tags: "drop,bts",
  status: "scheduled",
  publish_at: "2026-05-01T17:00:00Z",
});

Manage audience records

await doomscrollr.addSubscriber({
  email: "[email protected]",
  first_name: "Ada",
  tags: ["launch", "vip"],
  source: "website",
});

const csv = await doomscrollr.exportAudience({ tag: "launch" });
console.log(csv);

Create a product

await doomscrollr.createProduct({
  title: "Tie Dye Pants",
  price: 50,
  type: "physical",
  cover_photo_url: "https://example.com/tie-dye-pants.jpg",
  inventory_count: 10,
  shipping_required: true,
});

Build owned replacement flows

await doomscrollr.buildLinktree({
  title: "Links",
  intro: "Everything in one owned place.",
  style_preset: "brutalist",
  add_to_navigation: true,
  links: [
    { label: "Shop", url: "https://example.com/shop" },
    { label: "Newsletter", url: "https://example.com/newsletter" },
  ],
});

await doomscrollr.buildSocialFeed({
  title: "Moodboard",
  source_query: "air cooled Porsche",
  limit: 6,
});

Available flow helpers:

  • buildLinktree()
  • buildKomi()
  • buildShopify()
  • buildEcommerce()
  • buildSubstack()
  • buildNewsletter()
  • buildWebsite()
  • buildSocialFeed()
  • buildMembership()

Post ShopMy affiliate recommendations

await doomscrollr.postShopmyProducts({
  collection_title: "Holiday gifts under $100",
  use_case: "gift guide",
  status: "draft",
  products: [
    {
      url: "https://shopmy.us/example-product",
      note: "Great texture, easy gift.",
    },
  ],
});

Get embed/capture settings

const embed = await doomscrollr.getEmbedCode();
await doomscrollr.updateCaptureSettings({
  headline: "Join the list",
  enabled: true,
});

Error handling and rate limits

Failed responses throw DoomscrollrApiError with the HTTP status, response payload, and rate-limit metadata when the API provides it.

import { DoomscrollrApiError } from "@doomscrollr/api";

try {
  await doomscrollr.getProfile();
} catch (error) {
  if (error instanceof DoomscrollrApiError) {
    console.error(error.status);
    console.error(error.data);

    if (error.status === 429) {
      console.error(`Rate limit resets at ${error.rateLimit?.reset}`);
    }
  } else {
    throw error;
  }
}

The API returns X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on rate-limited responses; the SDK exposes them as error.rateLimit.

Request cancellation

Every method accepts an optional { signal } request option:

const controller = new AbortController();
const posts = await doomscrollr.listPosts({ per_page: 10 }, { signal: controller.signal });

Low-level requests

For new API endpoints that are not yet wrapped by a helper, use request() directly:

const result = await doomscrollr.request("GET", "/profile");

textRequest() is available for text responses such as CSV exports.

API coverage

The SDK covers the DOOMSCROLLR API v1 surfaces for:

  • account registration
  • profile and settings
  • posts, image posts, and bulk post operations
  • audience/subscribers, bulk operations, and CSV export
  • products, variants, inventory, and bulk product operations
  • domains
  • Pinterest, Instagram, and RSS integrations
  • embed code and capture widget settings
  • pages/contact pages/navigation
  • top-liked-post analytics
  • curation theme
  • owned replacement flows
  • ShopMy affiliate recommendations

License

MIT