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

@proofchain/partner-sdk

v1.4.1

Published

ProofChain Partner SDK for integrating with campaign data

Readme

ProofChain Partner SDK

SDK for partners to integrate with ProofChain campaigns. Provides methods for:

  • OTT authentication — redeem one-time tokens to verify user identity from redirects
  • Fetching campaign configuration with dynamic feedback schemas
  • Checking user consent status
  • Querying user data views
  • Submitting feedback events with schema validation

Installation

npm install @proofchain/partner-sdk

Quick Start

OTT Authentication (Redeem a One-Time Token)

If your app receives users via redirect from a ProofChain tenant, use OTT to verify their identity:

import { ProofChainPartner } from '@proofchain/partner-sdk';

const partner = new ProofChainPartner({
  partnerKey: 'pk_live_xxx', // from Portal > Integrators > Partner Keys
});

// In your redirect callback handler
const session = await partner.redeemOTT(req.query.ott);

session.user_id;         // stable ProofChain user identifier
session.session_data;    // non-PII fields (e.g. display_name, avatar)
session.session_timeout; // seconds until session expires
session.jwt;             // signed HS256 JWT (if redemption mode = "jwt")

Campaign Data Queries

If your app also queries campaign data, provide both keys:

const partner = new ProofChainPartner({
  partnerKey: 'pk_live_xxx',          // for OTT redemption
  apiKey: 'ik_live_xxx',              // for campaign data queries
  campaignId: 'your-campaign-uuid',   // for campaign data queries
});

// Get campaign configuration (includes feedback schemas)
const config = await partner.getConfig();
console.log('Available views:', config.data_views);
console.log('Feedback types:', config.feedback.types);

// Check if user has consented
const consent = await partner.checkConsent('user_123');
if (!consent.has_consent) {
  // Redirect to consent page
  const consentUrl = partner.getConsentUrl('user_123', {
    redirectUrl: 'https://your-site.com/callback'
  });
  window.location.href = consentUrl;
}

// Query user data
const profile = await partner.getUserProfile('user_123');
console.log('User profile:', profile.data);

// Submit feedback event
const result = await partner.submitFeedback('user_123', 'purchase', {
  amount: 99.99,
  currency: 'USD',
  product_id: 'ticket-123'
});
console.log('Feedback submitted:', result.feedback_id);

Dynamic Feedback Schemas

Each campaign can define custom feedback types with their own schemas. The SDK provides methods to discover and validate against these schemas:

// Get all available feedback types
const feedbackTypes = await partner.getFeedbackTypes();
// Returns: [
//   {
//     type: 'purchase',
//     name: 'Purchase',
//     description: 'Track when a user makes a purchase',
//     schema: {
//       type: 'object',
//       properties: {
//         amount: { type: 'number', minimum: 0 },
//         currency: { type: 'string', enum: ['USD', 'EUR', 'GBP', 'ZAR'] },
//         product_id: { type: 'string' }
//       },
//       required: ['amount', 'currency']
//     }
//   },
//   ...
// ]

// Get schema for a specific feedback type
const purchaseSchema = await partner.getFeedbackSchema('purchase');

// Validate data before submitting
const validation = await partner.validateFeedback('purchase', {
  amount: 99.99,
  currency: 'INVALID'
});
if (!validation.valid) {
  console.error('Validation errors:', validation.errors);
}

React Integration

The SDK includes React components and hooks:

import { 
  PartnerProvider, 
  usePartner, 
  ConsentWidget, 
  FeedbackForm 
} from '@proofchain/partner-sdk/react';

function App() {
  return (
    <PartnerProvider config={{
      apiKey: 'ik_live_xxx',
      campaignId: 'your-campaign-uuid',
    }}>
      <MyComponent />
    </PartnerProvider>
  );
}

function MyComponent() {
  const { partner, config, loading } = usePartner();
  
  if (loading) return <div>Loading...</div>;
  
  return (
    <div>
      <h1>{config?.campaign_name}</h1>
      
      {/* Consent widget */}
      <ConsentWidget
        partner={partner}
        userId="user_123"
        onSuccess={(consent) => console.log('Consented!', consent)}
        onCancel={() => console.log('Cancelled')}
      />
      
      {/* Dynamic feedback form */}
      <FeedbackForm
        partner={partner}
        userId="user_123"
        feedbackType="purchase"
        onSuccess={(result) => console.log('Submitted!', result)}
      />
    </div>
  );
}

OTT Integration Examples

Express.js

import express from 'express';
import { ProofChainPartner } from '@proofchain/partner-sdk';

const app = express();
const partner = new ProofChainPartner({
  partnerKey: process.env.PROOFCHAIN_PARTNER_KEY!,
});

// Handle the redirect from the tenant app
app.get('/auth/callback', async (req, res) => {
  const { ott } = req.query;
  if (!ott) return res.redirect('/login?error=missing_token');

  try {
    const session = await partner.redeemOTT(ott as string);

    // Create your own session from the verified identity
    req.session.userId = session.user_id;
    req.session.displayName = session.session_data.display_name;

    res.redirect('/dashboard');
  } catch (err) {
    // OTT is single-use — if already redeemed, returns 404
    console.error('OTT redemption failed:', err);
    res.redirect('/login?error=invalid_token');
  }
});

Next.js (App Router)

// app/api/auth/ott/route.ts
import { ProofChainPartner } from '@proofchain/partner-sdk';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

const partner = new ProofChainPartner({
  partnerKey: process.env.PROOFCHAIN_PARTNER_KEY!,
});

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const ott = searchParams.get('ott');

  if (!ott) return redirect('/login?error=missing_token');

  try {
    const session = await partner.redeemOTT(ott);

    if (session.jwt) {
      const cookieStore = await cookies();
      cookieStore.set('session', session.jwt, {
        httpOnly: true,
        secure: true,
        maxAge: session.session_timeout,
      });
    }

    return redirect('/dashboard');
  } catch {
    return redirect('/login?error=invalid_token');
  }
}

Full Flow: OTT + Campaign Data

const partner = new ProofChainPartner({
  partnerKey: 'pk_live_xxx',
  apiKey: 'ik_live_xxx',
  campaignId: 'campaign-uuid',
});

// 1. Redeem the OTT to identify the user
const session = await partner.redeemOTT(ott);

// 2. Query their campaign data
const profile = await partner.queryView(session.user_id, 'fan_profile');
const activity = await partner.getActivitySummary(session.user_id);

// 3. Submit feedback based on their actions
await partner.submitFeedback(session.user_id, 'page_visit', {
  page: '/dashboard',
  referrer: 'ott_redirect',
});

API Reference

ProofChainPartner

Constructor

new ProofChainPartner({
  partnerKey?: string,  // Partner key (pk_live_xxx) — required for OTT
  apiKey?: string,      // Integrator key (ik_live_xxx) — required for campaign operations
  campaignId?: string,  // Campaign UUID — required for campaign operations
  baseUrl?: string,     // API base URL (default: https://api.proofchain.io)
  timeout?: number,     // Request timeout in ms (default: 30000)
  debug?: boolean,      // Enable debug logging
})

At least one of partnerKey or apiKey must be provided.

Methods

OTT Authentication

| Method | Description | |--------|-------------| | redeemOTT(ott) | Redeem a one-time token. Returns { user_id, session_data, session_timeout, jwt? }. Requires partnerKey. |

Campaign Operations (require apiKey + campaignId)

| Method | Description | |--------|-------------| | getConfig() | Get campaign configuration including feedback schemas | | getAvailableViews() | Get list of available data views | | getFeedbackTypes() | Get available feedback types with schemas | | getFeedbackSchema(type) | Get schema for a specific feedback type | | checkConsent(userId) | Check if user has consented | | getConsentUrl(userId, options?) | Get URL for consent widget | | queryView(userId, viewName) | Query a data view | | getUserProfile(userId) | Get user's fan profile | | getActivitySummary(userId) | Get user's activity summary | | getEvents(userId) | Get user's recent events | | submitFeedback(userId, type, data) | Submit a feedback event | | validateFeedback(type, data) | Validate feedback data against schema |

Error Handling

All methods throw PartnerError on failure:

interface PartnerError {
  status: number;    // HTTP status code
  code: string;      // Error code
  message: string;   // Human-readable message
  details?: object;  // Additional details
}

Common error codes:

  • TIMEOUT - Request timed out (client-side, configurable via timeout option)
  • INVALID_FEEDBACK_TYPE - Feedback type not allowed for this campaign
  • MISSING_REQUIRED_FIELDS - Required fields missing from feedback data
  • CONSENT_REQUIRED - User has not consented to data sharing
  • RATE_LIMITED - Too many requests

OTT-specific errors:

  • HTTP 404 — Token not found (expired or already redeemed)
  • HTTP 403 — Partner key does not match the key that created the token
  • HTTP 422 — Missing or invalid ott parameter

License

MIT