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

@exchangehandles/sdk

v1.0.0

Published

Official TypeScript SDK for ExchangeHandles - AI Agent Identity Registry

Readme

@exchangehandles/sdk

Official TypeScript SDK for ExchangeHandles - the AI Agent Identity Registry. Manage handle availability, claim usernames, verify identities, and build AI agent profiles across 23+ platforms.

Installation

npm install @exchangehandles/sdk

Quick Start

import { ExchangeHandles } from '@exchangehandles/sdk';

const eh = new ExchangeHandles({ 
  apiKey: 'eh_...' // Get your API key from https://exchangehandles.com/api-keys
});

// Check handle availability
const availability = await eh.handles.check('coolname', 'twitter');
console.log(availability); // { handle: 'coolname', platform: 'twitter', available: true }

// Search the marketplace
const results = await eh.handles.search({ 
  query: 'crypto',
  platform: 'twitter',
  maxPrice: 1000 
});

// Claim a handle
const claimed = await eh.handles.claim('mynewhandle', 'github');
console.log(`Claimed ${claimed.handle} on ${claimed.platform}!`);

Configuration

const eh = new ExchangeHandles({
  apiKey: 'eh_your_api_key_here',
  baseUrl: 'https://exchangehandles.com' // Optional, defaults to production
});

Environment Variables

You can also set your API key via environment variable:

export EXCHANGEHANDLES_API_KEY="eh_your_api_key_here"

API Reference

Handles

// Check single platform
await eh.handles.check('username', 'twitter');

// Check multiple platforms
await eh.handles.checkMultiple('username', ['twitter', 'github', 'instagram']);

// Check all platforms
await eh.handles.checkAll('username');

// Search marketplace
await eh.handles.search({
  query: 'crypto',
  platform: 'twitter', // optional
  minPrice: 100,       // optional
  maxPrice: 1000,      // optional
  sortBy: 'price'      // 'price' | 'relevance' | 'length' | 'popularity'
});

// Claim handle
await eh.handles.claim('handle', 'platform', {
  duration: 365,     // days, optional
  autoRenew: true    // optional
});

// Release handle
await eh.handles.release('handle-id');

// List your handles
await eh.handles.list({
  status: 'active',  // optional filter
  limit: 50,         // optional
  offset: 0          // optional
});

// Extend claim
await eh.handles.extend('handle-id', 30); // extend by 30 days

Identity & Verification

// Get identity token
const token = await eh.identity.getToken(['read', 'write']);

// Verify token
await eh.identity.verifyToken(token.token);

// Get user info
const user = await eh.identity.getUser();

// Start verification process
await eh.verify.initiate('handle-id', 'email', '[email protected]');

// Confirm with verification code
await eh.verify.confirm('handle-id', '123456');

// Check verification status
await eh.verify.status('handle-id');

Agent Profiles

// Create profile
const profile = await eh.profile.create({
  name: 'My AI Assistant',
  description: 'A helpful AI agent',
  industry: ['technology', 'ai'],
  capabilities: ['chat', 'analysis', 'automation']
});

// Get profile
await eh.profile.get('my-agent-slug');

// Update profile
await eh.profile.update({
  description: 'Updated description',
  capabilities: ['chat', 'analysis', 'automation', 'coding']
});

// Upload avatar
await eh.profile.uploadAvatar(imageBase64);

// Search directory
await eh.directory.list({
  industry: ['ai'],
  verified: true,
  minReputation: 4.0,
  sortBy: 'reputation'
});

// Search agents
await eh.directory.search('trading bot', {
  capabilities: ['trading'],
  limit: 10
});

Watchdog Monitoring

// Monitor handle availability
await eh.watchdog.create('handle-id', {
  type: 'availability',
  conditions: { checkInterval: '1h' },
  notificationChannels: ['email', 'webhook']
});

// Monitor price changes
await eh.watchdog.create('handle-id', {
  type: 'price_change',
  conditions: { 
    threshold: 0.1, // 10% change
    direction: 'any' // 'up' | 'down' | 'any'
  }
});

// Check watchdog status
await eh.watchdog.check('handle-id');

// List alerts
await eh.watchdog.list({
  triggered: false,
  type: 'availability'
});

Namespace Reservations

// Reserve namespace pattern
await eh.namespace.reserve('mycompany-*', {
  platforms: ['twitter', 'github', 'instagram'],
  duration: 365,
  autoRenew: true
});

// List reservations
await eh.namespace.list({
  status: 'active',
  platform: 'twitter'
});

// Check for conflicts
await eh.namespace.checkConflicts('newpattern-*', ['twitter', 'github']);

// Get pricing
await eh.namespace.getPricing('pattern-*', ['twitter', 'github'], 365);

Webhooks

// Create webhook
const webhook = await eh.webhooks.create(
  'https://myapp.com/webhook',
  ['handle.claimed', 'handle.verified', 'watchdog.triggered'],
  'webhook-secret-key'
);

// List webhooks
await eh.webhooks.list({ active: true });

// Test webhook
await eh.webhooks.test(webhook.id);

// Get delivery logs
await eh.webhooks.getLogs(webhook.id, {
  status: 'failed',
  limit: 50
});

// Validate webhook signature (in your webhook handler)
const isValid = WebhooksService.validateSignature(
  requestBody,
  signature,
  'your-webhook-secret'
);

Billing

// Check balance
const balance = await eh.billing.balance();
console.log(`Balance: $${balance.amount} ${balance.currency}`);

// Deposit funds
await eh.billing.deposit({
  amount: 100,
  currency: 'USD',
  paymentMethod: 'stripe'
});

// Get transaction history
await eh.billing.getTransactions({
  type: 'purchase',
  limit: 50,
  startDate: '2024-01-01'
});

// Set up auto top-up
await eh.billing.setAutoTopUp({
  enabled: true,
  threshold: 50,
  amount: 100,
  paymentMethod: 'stripe'
});

OAuth (for "Sign in with ExchangeHandles")

// Register OAuth app
const app = await eh.oauth.register({
  name: 'My App',
  redirectUris: ['https://myapp.com/callback'],
  scopes: ['read:profile', 'read:handles']
});

// Generate auth URL
const authUrl = eh.oauth.generateAuthUrl(
  app.clientId,
  'https://myapp.com/callback',
  ['read:profile'],
  'random-state-value'
);

// Exchange code for token (in your callback handler)
const tokens = await eh.oauth.exchangeCode({
  clientId: app.clientId,
  clientSecret: app.clientSecret,
  code: 'authorization-code',
  redirectUri: 'https://myapp.com/callback'
});

// Refresh expired token
await eh.oauth.refreshToken({
  clientId: app.clientId,
  clientSecret: app.clientSecret,
  refreshToken: tokens.refreshToken
});

Platforms

// List all platforms
const platforms = await eh.platforms.list();

// Get platform details
const twitter = await eh.platforms.get('twitter');

// Get platform statistics
await eh.platforms.getStats('twitter');

// Check platform status
await eh.platforms.checkStatus();

Health & Status

// API health check
const health = await eh.health.check();

// Lightweight ping
const ping = await eh.health.ping();

// Get system metrics
const metrics = await eh.health.getMetrics();

// Get version info
const version = await eh.health.version();

Error Handling

The SDK provides typed error classes:

import { EHApiError, EHAuthError, EHInsufficientCredits, EHRateLimitError } from '@exchangehandles/sdk';

try {
  await eh.handles.claim('expensive-handle', 'twitter');
} catch (error) {
  if (error instanceof EHInsufficientCredits) {
    console.log('Not enough credits:', error.message);
    console.log('Required:', error.required, 'Available:', error.available);
  } else if (error instanceof EHAuthError) {
    console.log('Authentication error:', error.message);
  } else if (error instanceof EHRateLimitError) {
    console.log('Rate limited, retry after:', error.retryAfter, 'seconds');
  } else if (error instanceof EHApiError) {
    console.log('API error:', error.status, error.message);
  } else {
    console.log('Unknown error:', error);
  }
}

Retry Logic

The SDK automatically retries failed requests with exponential backoff:

  • Retries: 3 attempts by default
  • Rate limits: Auto-handled with proper delays
  • Timeouts: 30 seconds default
  • 5xx errors: Automatically retried
  • 4xx errors: Not retried (client errors)

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type { 
  HandleAvailability, 
  AgentProfile, 
  WatchdogAlert,
  Platform 
} from '@exchangehandles/sdk';

const availability: HandleAvailability = await eh.handles.check('test', 'twitter');
const profile: AgentProfile = await eh.profile.me();

Platform Support

The SDK supports 23+ platforms:

  • Social: Twitter, Instagram, TikTok, Facebook, LinkedIn, Snapchat
  • Professional: GitHub, LinkedIn
  • Communication: Discord, Telegram, WhatsApp
  • Content: YouTube, Twitch, Medium, Substack
  • Music: Spotify, SoundCloud
  • Emerging: Threads, Bluesky, Mastodon
  • Development: npm, PyPI
  • Domains: .com, .io, .ai, etc.

Rate Limits

  • Free tier: 100 requests/hour
  • Pro tier: 1,000 requests/hour
  • Enterprise: Custom limits

Rate limit headers are automatically handled by the SDK.

Examples

Complete Agent Setup

import { ExchangeHandles } from '@exchangehandles/sdk';

const eh = new ExchangeHandles({ apiKey: process.env.EXCHANGEHANDLES_API_KEY });

async function setupAgent() {
  // 1. Create agent profile
  const profile = await eh.profile.create({
    name: 'TradingBot Pro',
    description: 'Advanced cryptocurrency trading bot',
    industry: ['finance', 'cryptocurrency'],
    capabilities: ['trading', 'analysis', 'risk-management']
  });

  // 2. Search for available handles
  const handles = await eh.handles.search({
    query: 'trading',
    platforms: ['twitter', 'github'],
    maxPrice: 500
  });

  // 3. Claim preferred handles
  for (const handle of handles.data.slice(0, 2)) {
    try {
      const claimed = await eh.handles.claim(handle.handle, handle.platform);
      console.log(`✓ Claimed @${claimed.handle} on ${claimed.platform}`);
      
      // 4. Set up monitoring
      await eh.watchdog.create(claimed.id, {
        type: 'availability',
        conditions: { checkInterval: '1h' }
      });
    } catch (error) {
      console.log(`✗ Failed to claim @${handle.handle}`);
    }
  }

  // 5. Set up webhooks for notifications
  await eh.webhooks.create(
    'https://mybot.com/webhook',
    ['handle.claimed', 'watchdog.triggered'],
    process.env.WEBHOOK_SECRET
  );

  console.log(`Agent ${profile.name} is ready!`);
}

setupAgent().catch(console.error);

Support

License

MIT © ExchangeHandles