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

@reclaimprotocol/ai-sdk

v0.2.0

Published

Backend SDK for AI-built Reclaim proofs from any website through Popcorn.

Downloads

450

Readme

Reclaim AI SDK

A backend JavaScript SDK. Your backend creates a Popcorn verification URL, your frontend opens it in an iframe, popup, or tab, and your backend receives and validates the proofs. Node.js 18+ is required.

import { Reclaim } from '@reclaimprotocol/ai-sdk'

const reclaim = new Reclaim({
  appId: process.env.RECLAIM_APP_ID!,
  appSecret: process.env.RECLAIM_APP_SECRET!,
})
const session = await reclaim.initAiVerification('example.com/account', [
  { name: 'fullName' },
  { name: 'email', isOptional: true },
], 'Find the authenticated user’s profile.')

// Return this URL from your endpoint; initialization does not open a window.
const verificationUrl = session.verificationUrl
const proofs = await session.waitForProofs()

params accepts parameter names as strings, or { name, isOptional } objects when you need optional fields. Keep application credentials and proof handling on your backend. The frontend does not need this package.

Endpoint example

Mount these routes behind your application's authentication and bind each verification to its requesting user. This example uses memory for brevity; use persistent storage and a background worker in production, especially on serverless hosts where work cannot continue after an HTTP response.

import express from 'express'
import { randomUUID } from 'node:crypto'
import { Reclaim, type Proof } from '@reclaimprotocol/ai-sdk'

const app = express()
app.use(express.json())
const reclaim = new Reclaim({
  appId: process.env.RECLAIM_APP_ID!,
  appSecret: process.env.RECLAIM_APP_SECRET!,
})
const verifications = new Map<string, {
  status: 'pending' | 'completed' | 'failed'
  proofs?: Proof[]
}>()

app.post('/verifications', async (req, res, next) => {
  try {
    const session = await reclaim.initAiVerification(
      req.body.website, req.body.params, req.body.prompt,
    )
    const verificationId = randomUUID()
    verifications.set(verificationId, { status: 'pending' })
    void session.waitForProofs().then(
      proofs => verifications.set(verificationId, { status: 'completed', proofs }),
      () => verifications.set(verificationId, { status: 'failed' }),
    )
    res.json({ verificationId, verificationUrl: session.verificationUrl })
  } catch (error) {
    next(error)
  }
})

app.get('/verifications/:id', (req, res) => {
  const result = verifications.get(req.params.id)
  if (!result) { res.sendStatus(404); return }
  // Consume result.proofs in your backend's application logic.
  res.json({ status: result.status })
})

The frontend calls your endpoint and displays the URL:

const { verificationId, verificationUrl } = await fetch('/verifications', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    website: 'example.com/account',
    params: ['fullName'],
    prompt: 'Find the authenticated user’s profile.',
  }),
}).then(response => response.json())
iframe.src = verificationUrl
// Or open verificationUrl in a popup or another tab on a user click.
// Poll /verifications/:verificationId for your application status.

Backend callback URLs

Configure proof and error callback destinations at initialization:

const session = await reclaim.initAiVerification(
  'example.com/account', ['fullName'], 'Find the authenticated user’s profile.',
  {
    callbackUrl: 'https://your-app.example/reclaim/proofs',
    cancelCallbackUrl: 'https://your-app.example/reclaim/errors',
    jsonProofResponse: true,
  },
)
// Save the private descriptor before returning the URL to the frontend.
await saveSession(session.sessionId, session.toJSON())
return { verificationUrl: session.verificationUrl }

The JS SDK setters are also available on a freshly initialized session:

session.setAppCallbackUrl('https://your-app.example/reclaim/proofs', true)
session.setCancelCallbackUrl('https://your-app.example/reclaim/errors')
const verificationUrl = await session.getRequestUrl()

Set callbacks before opening or sharing verification. After a setter, call getRequestUrl() to regenerate the URL; reading verificationUrl or serializing the session before regeneration throws instead of returning an outdated URL. Restored sessions use their saved URL and callback configuration; configure destinations before serialization. getAppCallbackUrl(), getCancelCallbackUrl(), and getJsonProofResponse() expose the current settings.

Portal sends a POST to the proof callback with X-Reclaim-Session-Id. With jsonProofResponse: true, the body is a JSON proof array. The default is false, which sends URI-encoded JSON with application/x-www-form-urlencoded; read the raw text and use JSON.parse(decodeURIComponent(rawBody)) for that mode. Errors are always JSON POSTs to the cancel callback, including the session ID, exception type, and message. Custom destinations must be public HTTPS URLs on port 443; a public HTTPS tunnel is needed for a callback served on localhost. Portal enforces its existing callback destination and DNS rules.

Custom proof callbacks send proofs directly to your endpoint instead of storing them at Reclaim. In this mode, waitForProofs() throws immediately. Validate the incoming proofs with session.verifyProofs(payload) and save the result before acknowledging the callback. This method retrieves the session's actual generated provider version from the configured SDK backend, validates signatures, provider content, signed session context, and extraction requirements using the same checks as waitForProofs(). It accepts a proof or proof array and returns Proof[]. It has a 30-second timeout by default and supports { timeoutMs, signal }. Empty or invalid payloads fail validation. It can run before the callback is acknowledged; it does not require a submitted backend status.

For example, with the existing Express app and JSON proof mode:

import { AiVerificationSession } from '@reclaimprotocol/ai-sdk'

app.post('/reclaim/proofs', async (req, res, next) => {
  try {
    const sessionId = req.get('X-Reclaim-Session-Id')
    const saved = sessionId && await loadSession(sessionId)
    if (!saved) { res.sendStatus(404); return }
    const session = AiVerificationSession.fromJSON(saved)
    const proofs = await session.verifyProofs(req.body)
    await saveVerifiedResult(session.sessionId, proofs)
    res.sendStatus(200)
  } catch (error) {
    next(error)
  }
})

saveSession, loadSession, and saveVerifiedResult are your application's persistent storage operations. Use the signed session and validated proofs for acceptance; the session header identifies which saved descriptor to load. Keep callback handling idempotent because a failed delivery can be retried. A custom cancel callback routes errors to your handler, so coordinate cancellation there with your application's worker/frontend instead of relying on backend polling.

Proof context

Include application data such as a user or order ID in the signed proof context:

const session = await reclaim.initAiVerification(
  'example.com/account', ['fullName'], '',
  { context: { userId: 'user-123', orderId: 'order-456' } },
)

Configure context when initializing the session. It is saved in the private session descriptor and retained when restoring the session.

Context must be a JSON-serializable object. The SDK adds reclaimSessionId and attestation fields automatically; custom context cannot override those fields or extractedParameters. Context is specific to a session. It is visible in the verification request, so keep secrets out of it.

Both verifyProofs() and waitForProofs() require every configured context field to match the signed JSON.parse(proof.claimData.context) on every proof. Nested objects and arrays are compared as JSON values. Missing or mismatched context fails with SESSION_MISMATCH; generated proof fields may accompany your context. Without custom context, verification keeps its existing behavior.

API behavior

Verification reads the authenticated account and returns signed proofs for the requested fields. All required fields must be present in verified proof data; missing optional fields do not block completion.

After confirmed login, account data collection runs for at least two minutes. When the required fields and their supporting evidence are ready, verification can continue. Missing required fields or evidence after three minutes fail the verification. Proof generation and delivery may take additional time.

Portal proofs trust the Portal's registered signer. The SDK validates the signed proof's registered signer, signature, session, application context and required parameters. Witness proofs also require matching provider content.

Reclaim accepts optional backendUrl and portalUrl settings for local or staging deployments. backendUrl must be an HTTP(S) origin. Session descriptors retain this origin so backend workers poll and fetch the same provider versions. The underlying JS SDK sets its backend globally during initialization; use a separate process for each backend environment.

Request 1–32 unique identifier names of up to 64 characters. At least one must be required; isOptional defaults to false. Custom instructions can be empty and are limited to 10,000 characters. Each generated HTTP request can use at most 12 response matches to bound the underlying SDK's optional hash enumeration. Missing optional values are absent. Required values must be present in verified proof data.

waitForProofs({ timeoutMs, signal }) returns Proof[] after JS SDK signature verification, signed session, and extraction validation. Witness proofs also match the exact session provider configuration. Portal proofs attest facts directly and do not require a published provider version or config lookup. For batches whose signed contexts contain both isPortalProof: true and isAiProof: true, the SDK uses JS SDK verifyProof with provider-content matching disabled; registered-signer and signature verification stay enabled. A batch containing a witness proof retains provider-version and hash validation. Default wait: 10 minutes; normal polling: 3 seconds; proof-generation failure grace: 30 seconds. Transient status network errors use bounded backoff. Aborting stops local waiting. Verified values come from JSON.parse(proof.claimData.context).extractedParameters; the proof's display-only extractedParameterValues is not independently trusted. AiVerificationError.code distinguishes provider creation, session mismatch, invalid proofs, missing/conflicting values, cancellation, verification failure, timeout, and permanent HTTP errors.

For a background worker, persist session.toJSON() on the backend and restore it with AiVerificationSession.fromJSON(savedDescriptor). Keep descriptors and verification URLs private to the owning user's session. Only return the URL and your application's verification ID to the frontend.

Every initialization creates a fresh verification session and URL. Persist the complete descriptor returned by session.toJSON() rather than constructing or editing it yourself.

Provider resolution is not retried automatically. A concurrent creation may return HTTP 409 with Retry-After: 1; retry initAiVerification to sign a fresh request. Disabled or archived providers are rejected. The Reclaim backend must have a registered enabled application and an active creator. Proof delivery uses Reclaim's default backend callback and polling unless a custom callback is configured. Frontends choose how to open the verification URL.

Local playground

Run npm run build, configure the server-side application credentials using the playground setup, then start node examples/web/server.mjs. Open http://localhost:3333 to request and inspect verified proofs. Form inputs survive refresh, and recent inputs can be reused. The example binds to loopback and keeps application secrets on the server.

Development: npm ci, npm run typecheck, npm test, npm run build.