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

@chitmark/sdk

v0.5.2

Published

Official TypeScript SDK for Chitmark by Open Agent Ledger: trust decisions on agent-mediated actions (verify, feedback, challenge)

Readme

@chitmark/sdk

Official TypeScript / JavaScript SDK for Chitmark: trust decisions on agent-mediated actions, tuned by business outcomes.

AI agents and multi-account farms drain free tiers, trial credits, and API allowances while looking exactly like your best customers. Chitmark scores each action in under 50 ms and returns allow, challenge, or deny. Then your outcomes (conversion, credit burn, chargeback) come back through feedback and tune the next decision.

npm version

Try it without a key: run the playground. Live service health: chitmark.com/status.

Install

npm install @chitmark/sdk
# or
pnpm add @chitmark/sdk

Requires Node >= 24. Runs on Node, browsers, Cloudflare Workers, and other edge runtimes (see the /edge entrypoint below).

Quick start

import { Chitmark } from "@chitmark/sdk";

const chitmark = new Chitmark({
  apiKey: process.env.CHITMARK_API_KEY!,
  // Optional, defaults shown
  onDegraded: "challenge", // timeouts return a challenge, they never throw or allow
  timeoutMs: 800,
  piiMode: "hashed", // 'hashed' | 'none' | 'raw'
  env: "production",
});

const verdict = await chitmark.verify({
  action: "signup",
  session: "sess_9f3a",
  surface: "app.acme.com/signup",
  subject: {
    email: "[email protected]", // hashed client-side before the wire
    ip: "203.0.113.7", // truncated to /24 client-side
    userAgent: req.headers["user-agent"],
    headers: req.headers,
  },
});

if (verdict.decision === "challenge") {
  // stop and run the challenge flow (below)
}
// Persist verdict.eventId on the account row: feedback joins only on that id.

The three verbs

| Verb | Method | Endpoint | When | | :------------ | :--------------------- | :------------------- | :--------------------------- | | verify | chitmark.verify() | POST /v1/verify | At signup / trial / action | | feedback | chitmark.feedback() | POST /v1/feedback | After an outcome is known | | challenge | chitmark.challenge() | POST /v1/challenge | On challenge or degraded |

Timeouts and transport errors return a degraded challenge verdict and never throw on verify. HTTP errors throw ChitmarkApiError with the status attached. Set onDegraded to challenge (the only supported value), never allow on degraded.

Report outcomes

Store the eventId from verify on the account row, then report what happened against that same id. Never guess or derive the id from email or IP.

// At signup: persist the join key
db.accounts.update(userId, { chitmarkEventId: verdict.eventId });

// Later, when a label matures:
await chitmark.feedback({
  eventId: account.chitmarkEventId, // the stored join key
  outcome: "credit_burn", // converted | chargeback | abuse_confirmed | ...
  value: 87.4, // dollar amount: `unit` rides along (default "usd")
  observedAt: "2026-08-06T04:00:00Z",
});

Exact duplicate feedback bodies derive the same warehouse id, so retrying a connector never double-counts a burned value.

Handle a challenge

When verify returns challenge, issue one, solve it on the client, and complete it. Proof-of-work difficulty is server-issued (4 by default, up to 6 at higher risk tiers): about 65k hashes, milliseconds for one real user, costly at farm scale.

import { createHash } from "node:crypto";

const issued = await chitmark.challenge({
  eventId: verdict.eventId,
  session: "sess_9f3a", // the challenge binds to this session
});

if (issued.instructions.type === "pow") {
  const { challengeId, instructions } = issued;
  const prefix = "0".repeat(instructions.difficulty);
  let nonce = 0;
  for (; ; nonce++) {
    const hex = createHash("sha256")
      .update(`${challengeId}:${instructions.seed}:${nonce}`)
      .digest("hex");
    if (hex.startsWith(prefix)) break;
  }
  await chitmark.completeChallenge({
    eventId: verdict.eventId,
    challengeId,
    session: "sess_9f3a",
    proof: { type: "proof_of_work", nonce: String(nonce) },
  });
  // Re-verify with context: { challengeId } so the next verdict honors it.
}

Verify the receipt

Every production verdict ships a verdictToken: an ES256 JWT bound to session, origin, and event. Verify it before acting on high-value decisions:

const claims = await chitmark.verifyVerdictToken(verdict.verdictToken, {
  session: "sess_9f3a", // enforce session binding (recommended)
  aud: "api.chitmark.com", // enforce origin binding
});
// claims: { eventId, decision, actorType, confidence, jti, exp, ... }

Rejects expired tokens, unknown keys, bad signatures, and session or origin mismatches with typed VerdictTokenError codes.

PII modes

| Mode | Behavior | | :----------------- | :--------------------------------------------------------- | | hashed (default) | SHA-256 email, /24 IP truncation, allowlisted form fields | | none | Derived/header-shape signals only (Web Bot Auth preserved) | | raw | Tenant opt-in only; triggers higher compliance review |

Framework integrations

Express middleware and a Next.js route helper ship in the package:

// Express: 403 on deny, 428 + challenge payload on challenge
import { chitmarkGate } from "@chitmark/sdk";
app.post("/signup", chitmarkGate(chitmark, "signup"), signupHandler);

// Next.js App Router
import { verifyNextRequest } from "@chitmark/sdk";
const verdict = await verifyNextRequest(req, chitmark, { action: "signup" });

Cloudflare Workers

The /edge entrypoint is the same client with a request-first helper:

import { Chitmark } from "@chitmark/sdk/edge";

const chitmark = new Chitmark({ apiKey: env.CHITMARK_API_KEY });
const verdict = await chitmark.verifyRequest(req, { action: "signup" });

Agent integration

Using Cursor, Claude Code, Codex, or another coding agent? Point it at chitmark.com/SKILL.md, or paste this into your prompt: Integrate Chitmark into my app following https://chitmark.com/SKILL.md.

Resources

License

Proprietary: see LICENSE.