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

@workoutx/sdk

v0.1.0

Published

Official TypeScript/JavaScript SDK for the WorkoutX API — exercises, GIFs, workouts, supplements, and body scan.

Readme

@workoutx/sdk

Official TypeScript/JavaScript SDK for the WorkoutX API. One client covers both products:

  • Exercises — exercises, GIFs, workout generator, supplements (API-key auth)
  • Body Scan — credits, history, keys, checkout (logged-in user / Bearer auth)
  • Account & Billing — register/login, API-key management, password reset, webhooks, subscription checkout (Bearer auth)

Works in Node.js 18+ and modern browsers. Zero runtime dependencies (uses native fetch).

Install

npm install @workoutx/sdk

Quick start

import { WorkoutX } from "@workoutx/sdk";

const wx = new WorkoutX({
  apiKey: "wx_your_key_here",        // exercises / gifs / workout / supplements
  scan: { token: "eyJ..." },          // body scan (optional)
});

// Exercises
const page    = await wx.exercises.list({ limit: 20 });
const byId    = await wx.exercises.get("0001");
const lunges  = await wx.exercises.byName("lunges");   // ← name lookup
const similar = await wx.exercises.similar("0001");
const alts    = await wx.exercises.alternatives("0001", { equipment: "dumbbell" });

// GIFs (binary)
const bytes = await wx.gifs.get("0001");                // ArrayBuffer
const src   = wx.gifUrl("0001");                        // for <img src>

// Workout & supplements
const workout = await wx.workout.generate({ goal: "hypertrophy", days: 4 });
const stack   = await wx.supplements.stack({ goal: "cut" });

// Body Scan
const credits = await wx.scan.credits();
const history = await wx.scan.history({ limit: 10 });

// Account & billing
const { token } = await wx.auth.login("[email protected]", "•••"); // token cached for scan/auth/billing
const me        = await wx.auth.me();
const keys      = await wx.auth.listKeys();
const sub       = await wx.billing.status();
const checkout  = await wx.billing.checkout("pro", "yearly");      // → { url } to redirect to Stripe

Authentication

The two products use different credentials — the SDK handles both transparently.

| Product | Endpoints | Credential | |---------|-----------|------------| | Exercises | exercises, gifs, workout, supplements | apiKey (wx_...) → X-WorkoutX-Key header | | Body Scan | scan.* | Bearer JWT |

For Body Scan you can either pass a ready token or let the SDK log in for you:

// Option A — you already have a token
new WorkoutX({ apiKey, scan: { token: "eyJ..." } });

// Option B — auto-login on first scan call, then cache the token
new WorkoutX({ apiKey, scan: { email: "[email protected]", password: "•••" } });

You can also set/replace the token later:

wx.setScanToken("eyJ...");

Avoiding the "name as ID" 404

exercises.get(id) expects an exact numeric ID (IDs have gaps and are not sequential). Passing a human name like "lunges" returns 404. Use byName, or the convenience resolver that tries an ID first then falls back to a name search:

const ex = await wx.exercises.find("lunges"); // Exercise | null

Error handling

Every non-2xx response throws a WorkoutXError with structured fields:

import { WorkoutXError } from "@workoutx/sdk";

try {
  await wx.exercises.get("not-a-real-id");
} catch (err) {
  if (err instanceof WorkoutXError) {
    err.status;        // 404
    err.code;          // "Not Found"
    err.message;       // human-readable
    err.tip;           // hint from the API, when present
    err.isNotFound;    // boolean helpers: isAuthError, isRateLimited, isNotFound
  }
}

Transient failures (HTTP 429 and 5xx, plus network errors) are retried automatically with exponential backoff, honoring the Retry-After header.

Options

new WorkoutX({
  apiKey,
  scan,
  baseUrl: "https://api.workoutxapp.com", // default
  timeout: 30_000,                         // ms, default 30s
  maxRetries: 2,                           // default 2
  headers: { "X-Trace": "abc" },           // extra headers on every request
  fetch: customFetch,                      // custom fetch impl (optional)
});

API surface

  • wx.exerciseslist, get, byName, byBodyPart, byTarget, byEquipment, search, similar, alternatives, calories, changes, find, bodyPartList, targetList, equipmentList, secondaryMuscleList
  • wx.gifsget, url
  • wx.workoutgenerate, program
  • wx.supplementslist, filters, stack, forExercise, get
  • wx.scancredits, me, history, listKeys, createKey, deleteKey, checkout, packs
  • wx.authregister, login, me, updateMe, changePassword, listKeys, createKey, deleteKey, updateKeyPlan, usage, forgotPassword, resetPassword, verifyEmail, resendVerification, getWebhook, setWebhook, testWebhook
  • wx.billingstatus, checkout, portal

auth, billing, and scan use the same Bearer token. A successful auth.login() caches it, so subsequent scan.* / billing.* calls work without re-supplying credentials. Google OAuth (/v1/auth/google) is a browser-redirect flow and is intentionally not wrapped in the SDK.

Some endpoints are plan-gated (e.g. search, workout.generate, supplements.stack). Calling them on a plan without the feature returns a WorkoutXError with a 403/upgrade message.

License

MIT