Skip to content

SDK Documentation

@profullstack/coinpay - Node.js SDK & CLI for cryptocurrency payments

Installation

Install the CoinPay SDK using your preferred package manager:

Using pnpm (recommended)

pnpm add @profullstack/coinpay

Using npm

npm install @profullstack/coinpay

Global CLI Installation

# Install globally for CLI access
pnpm add -g @profullstack/coinpay

# Or with npm
npm install -g @profullstack/coinpay

Requirements: Node.js 20+ with ESM support

Quick Start

How CoinPay Works

  1. Your server calls the CoinPay API to create a payment request
  2. CoinPay generates a unique payment address and QR code
  3. Your customer sends cryptocurrency to that address
  4. CoinPay monitors the blockchain and notifies you via webhook
  5. Funds are automatically forwarded to your wallet (minus fees)

SDK Usage

Basic SDK Example

import { CoinPayClient, Blockchain } from '@profullstack/coinpay';

// Initialize with your API key (get it from your dashboard)
const coinpay = new CoinPayClient({
  apiKey: 'cp_live_your_api_key_here',
});

// Create a payment when customer checks out
const result = await coinpay.createPayment({
  businessId: 'your-business-id',  // From your dashboard
  amount: 100,                      // Amount in fiat currency
  currency: 'USD',                  // Fiat currency (default: USD)
  blockchain: Blockchain.BTC,       // Cryptocurrency to accept
  description: 'Order #12345',      // Shown to customer
  metadata: {                       // Your custom data
    orderId: '12345',
    customerEmail: 'customer@example.com'
  }
});

// Display to customer
console.log('Send payment to:', result.payment.payment_address);
console.log('Amount:', result.payment.crypto_amount, result.payment.blockchain);
console.log('QR Code:', result.payment.qr_code);

cURL Example

Direct API Call

curl -X POST https://coinpayportal.com/api/payments/create \
  -H "Authorization: Bearer cp_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "business_id": "your-business-id",
    "amount": 100,
    "blockchain": "BTC",
    "description": "Order #12345",
    "metadata": {"orderId": "12345"}
  }'

CLI Usage

CLI Quick Start

# Configure your API key (one-time setup)
coinpay config set-key cp_live_your_api_key

# Create a Bitcoin payment
coinpay payment create --business-id biz_123 --amount 100 --blockchain BTC

# Create an Ethereum payment with description
coinpay payment create --business-id biz_123 --amount 50 --blockchain ETH --description "Order #12345"

# Create a USDC payment on Polygon
coinpay payment create --business-id biz_123 --amount 25 --blockchain USDC_POL

# Send with fiat amount (wallet commands)
coinpay wallet send --chain SOL --to abc... --amount-fiat 10 --fiat USD
coinpay wallet send --chain ETH --to 0x123... --amount-fiat 25 --fiat EUR

# Get payment details
coinpay payment get pay_abc123

# List payments
coinpay payment list --business-id biz_123

# Get exchange rates with fiat support
coinpay rates get BTC --fiat USD
coinpay rates get SOL --fiat EUR

SDK Client Configuration

Initialize the CoinPayClient with your API key from your business dashboard:

Client Initialization

import { CoinPayClient } from '@profullstack/coinpay';

const client = new CoinPayClient({
  // Required: Your API key (starts with cp_live_)
  apiKey: 'cp_live_your_api_key_here',
  
  // Optional: Custom API URL (defaults to https://coinpayportal.com/api)
  baseUrl: 'https://coinpayportal.com/api',
  
  // Optional: Request timeout in milliseconds (default: 30000)
  timeout: 30000,
});

Environment Variables

VariableDescription
COINPAY_API_KEYAPI key (overrides config file)
COINPAY_BASE_URLCustom API URL

Payments API

Primary Use Case: Call this API from your backend when a customer wants to pay with cryptocurrency. Display the returned payment address and QR code to your customer.

Create Payment

Create a new payment

const result = await client.createPayment({
  businessId: 'your-business-id',  // Required: From your dashboard
  amount: 100,                      // Required: Amount in fiat
  currency: 'USD',                  // Optional: Fiat currency (default: USD)
  blockchain: 'BTC',                // Required: BTC, ETH, SOL, POL, BCH, USDC_ETH, USDC_POL, USDC_SOL
  description: 'Order #12345',      // Optional: Shown to customer
  metadata: {                       // Optional: Your custom data
    orderId: '12345',
    customerEmail: 'customer@example.com'
  }
});

// Response structure
console.log(result);
// {
//   success: true,
//   payment: {
//     id: 'pay_abc123',
//     payment_address: 'bc1q...',
//     crypto_amount: '0.00234567',
//     blockchain: 'BTC',
//     status: 'pending',
//     expires_at: '2024-01-01T13:00:00Z',
//     qr_code: 'data:image/png;base64,...'
//   },
//   usage: { current: 45, limit: 100, remaining: 55 }
// }

Check Payment Status

There are two ways to know when a payment is complete:

Option 1: Polling (Simple)

Poll for payment status

// Check status once
const result = await client.getPayment('pay_abc123');
console.log(result.payment.status); // 'pending', 'confirmed', 'forwarded', etc.

// Or wait for payment to complete (polls automatically)
const payment = await client.waitForPayment('pay_abc123', {
  interval: 5000,      // Check every 5 seconds
  timeout: 600000,     // Give up after 10 minutes
  onStatusChange: (status, payment) => {
    console.log(`Status changed to: ${status}`);
  }
});

if (payment.payment.status === 'confirmed' || payment.payment.status === 'forwarded') {
  console.log('Payment successful!');
} else {
  console.log('Payment failed or expired');
}

Option 2: Webhooks (Recommended)

Configure a webhook URL in your business settings to receive real-time notifications. See the Webhook Verification section below.

List Payments

List payments with filters

const payments = await client.listPayments({
  businessId: 'biz_123',
  status: 'completed', // optional filter
  limit: 20,           // optional, default 50
  offset: 0,           // optional, for pagination
});

console.log(`Found ${payments.length} payments`);

Get Payment QR Code

The QR code endpoint returns binary PNG image data that can be used directly in HTML.

QR code usage

// Get QR code URL for use in HTML <img> tags
const qrUrl = client.getPaymentQRUrl('pay_abc123');
// Returns: "https://coinpayportal.com/api/payments/pay_abc123/qr"

// Use directly in HTML:
// <img src={qrUrl} alt="Payment QR Code" />

// Or fetch as binary data (for server-side processing)
const imageData = await client.getPaymentQR('pay_abc123');

// Save to file (Node.js)
import fs from 'fs';
fs.writeFileSync('payment-qr.png', Buffer.from(imageData));

HTML usage

<!-- Use QR endpoint directly as image source -->
<img src="https://coinpayportal.com/api/payments/pay_abc123/qr" alt="Payment QR Code" />

Credit Card Payments

Accept credit and debit card payments via Stripe Connect. Merchants must complete Stripe onboarding before accepting card payments. Supports both direct payments (gateway mode) and escrow mode for holding funds until release.

🔗 Merchant Onboarding Required

Before accepting card payments, merchants must complete Stripe Connect onboarding. Use createStripeOnboardingLink() to generate the onboarding URL.

Customer Payment Choice Example

Let customers choose: Crypto OR Card

import { CoinPayClient } from '@profullstack/coinpay';

const client = new CoinPayClient({ apiKey: 'your-api-key' });

// Check what payment methods are available
const support = await client.getPaymentMethodSupport('business-id');

if (support.cards) {
  // Customer can choose crypto OR card
  console.log('✅ Crypto payments available');
  console.log('✅ Card payments available');
  
  // Create card payment
  const cardPayment = await client.createCardPayment({
    businessId: 'biz_123',
    amount: 5000, // $50.00 in cents
    currency: 'usd',
    description: 'Order #12345',
    successUrl: 'https://yourstore.com/success',
    cancelUrl: 'https://yourstore.com/cancel'
  });
  
  // Redirect customer to: cardPayment.checkout_url
  
} else {
  console.log('✅ Crypto payments available');
  console.log('❌ Card payments require Stripe onboarding');
  
  // Only crypto payments available
  const cryptoPayment = await client.createPayment({
    businessId: 'biz_123',
    amount: 50.00,
    currency: 'USD',
    blockchain: 'BTC',
    description: 'Order #12345'
  });
}

Merchant Stripe Onboarding

Create Stripe Connect onboarding link

// Generate onboarding link for merchant
const onboarding = await client.createStripeOnboardingLink('business-id', {
  email: 'merchant@example.com',
  country: 'US'
});

console.log('Onboarding URL:', onboarding.onboarding_url);
// Redirect merchant to complete Stripe onboarding

// Check onboarding status
const status = await client.getStripeAccountStatus('business-id');
console.log('Can accept cards:', status.onboarding_complete);

Create Card Payment

Create credit card payment

// Gateway Mode - Direct payment to merchant
const payment = await client.createCardPayment({
  businessId: 'biz_123',
  amount: 5000, // $50.00 in cents
  currency: 'usd',
  description: 'Order #12345',
  metadata: { orderId: '12345', customerId: 'cust_456' },
  successUrl: 'https://yourstore.com/success',
  cancelUrl: 'https://yourstore.com/cancel',
  escrowMode: false // Direct payment (default)
});

// Redirect customer to payment.checkout_url for card entry

Card Escrow Mode

Create card payment with escrow

// Escrow Mode - Hold funds until release
const escrowPayment = await client.createCardPayment({
  businessId: 'biz_123',
  amount: 10000, // $100.00 in cents
  currency: 'usd',
  description: 'Freelance Work - Logo Design',
  escrowMode: true, // Hold funds in escrow
  metadata: { projectId: 'proj_789' }
});

// Customer pays via payment.checkout_url
// Funds are held until release

// Later, release funds to merchant
const release = await client.releaseCardEscrow(escrowPayment.escrow_id, 'Work completed successfully');
console.log(`Released $${release.amount_transferred / 100} to merchant`);

Card Payment Convenience Functions

Using card-payments convenience module

import { 
  createQuickCardPayment, 
  formatCardAmount,
  calculateCardPaymentFees
} from '@profullstack/coinpay/card-payments';

// Quick payment with USD amount (auto-converts to cents)
const payment = await createQuickCardPayment(client, 'biz_123', 50.0, 'Order #123', {
  metadata: { orderId: '123' },
  escrowMode: true
});

// Format amounts for display
console.log(formatCardAmount(5000)); // "$50.00"
console.log(formatCardAmount(5050, 'EUR')); // "€50.50"

// Calculate platform fees
const fees = calculateCardPaymentFees(5000, 'free'); // free tier = 1%
console.log(`Platform fee: $${fees.platformFee / 100}`); // "$0.50"
console.log(`Merchant receives: $${fees.merchantReceives / 100}`); // "$49.50"

Webhook Events for Card Payments

Handle card payment webhooks

// Webhook events you'll receive for card payments:
// - card_payment_success: Customer paid successfully
// - card_dispute_created: Customer disputed the charge
// - card_refund: Payment was refunded
// - card_escrow_release: Escrow funds were released to merchant

app.post('/webhook', (req, res) => {
  const { event_type, data } = req.body;
  
  switch (event_type) {
    case 'card_payment_success':
      console.log('Card payment received:', data.amount / 100);
      // Update order status, send confirmation email, etc.
      break;
      
    case 'card_dispute_created':
      console.log('Dispute created for payment:', data.stripe_payment_intent_id);
      // Alert merchant, gather evidence
      break;
      
    case 'card_escrow_release':
      console.log('Escrow released:', data.amount / 100);
      // Mark project as completed, notify freelancer
      break;
  }
  
  res.status(200).send('OK');
});

Platform Fees

Platform Fee Structure

Free Tier: 1.0% platform fee
Pro Tier: 0.5% platform fee
Plus Stripe processing fees (2.9% + 30¢ for US cards)

Refunds

Refund card payments

// Full refund
const refund = await client.refundCardPayment('payment-intent-id');

// Partial refund ($25 out of $50 payment)
const partialRefund = await client.refundCardPayment('payment-intent-id', {
  amount: 2500, // $25.00 in cents
  reason: 'Customer complaint - partial refund'
});

console.log('Refund status:', refund.status);

Card Escrow — Release & Refund

Release and refund card escrow

// Release card escrow funds to merchant
const release = await client.releaseCardEscrow('escrow-id', 'Work completed successfully');
console.log(`Transfer ID: ${release.transfer_id}`);
console.log(`Amount released: $${(release.amount_transferred / 100).toFixed(2)}`);

// Refund card escrow — full refund
const refund = await client.refundCardPayment('escrow-id');
console.log(`Refund ID: ${refund.refund_id}`);

// Refund card escrow — partial refund
const partialRefund = await client.refundCardPayment('escrow-id', {
  amount: 2500, // $25.00 in cents
  reason: 'Partial refund — item returned'
});
console.log(`Refunded: $${(partialRefund.amount_refunded / 100).toFixed(2)}`);
console.log(`Escrow status: ${partialRefund.escrow_status}`); // 'partially_refunded'

CLI Card Commands

Card payment CLI

# Create a card payment ($50.00 = 5000 cents)
coinpay card create --business-id biz_123 --amount 5000 --description "Order #123"

# Create card payment with escrow mode
coinpay card create --business-id biz_123 --amount 10000 --escrow --description "Freelance work"

# Get card payment details
coinpay card get pay_abc123

# List card payments for a business
coinpay card list --business-id biz_123

# Stripe Connect — onboard a merchant
coinpay card connect onboard merch_123 --email merchant@example.com --country US

# Stripe Connect — check onboarding status
coinpay card connect status merch_123

# Release card escrow funds
coinpay card escrow release esc_123 --reason "Work completed"

# Refund card escrow (full)
coinpay card escrow refund esc_123

# Refund card escrow (partial, $25)
coinpay card escrow refund esc_123 --amount 2500 --reason "Partial refund"

Stripe Webhook Events

The platform processes these Stripe webhook events automatically:

payment_intent.succeededCard payment completed — updates transaction record, funds escrow if applicable, creates DID reputation event
charge.dispute.createdCustomer disputed a charge — creates dispute record, negative DID reputation impact (-50 weight)
payout.createdStripe payout initiated to merchant bank account
payout.paidPayout arrived in merchant bank account
account.updatedStripe Connect account capabilities changed (charges_enabled, payouts_enabled, etc.)

Businesses API

Create Business

Create a new business

const business = await client.createBusiness({
  name: 'My Store',
  webhookUrl: 'https://your-site.com/webhook',
  walletAddresses: {
    BTC: 'bc1q...',
    ETH: '0x...',
    SOL: '...',
  },
});

console.log(`Business ID: ${business.id}`);
console.log(`API Key: ${business.apiKey}`);

Get Business

Retrieve business details

const business = await client.getBusiness('biz_123');

console.log(business.name);
console.log(business.walletAddresses);

List Businesses

List all businesses

const businesses = await client.listBusinesses();

businesses.forEach(biz => {
  console.log(`${biz.name}: ${biz.id}`);
});

Update Business

Update business settings

const updated = await client.updateBusiness('biz_123', {
  name: 'Updated Store Name',
  webhookUrl: 'https://new-webhook-url.com/webhook',
});

Escrow API

Create and manage trustless crypto escrows. No accounts required — authentication uses unique tokens returned at creation.

Create Escrow

Create a new escrow (crypto amount)

const escrow = await client.createEscrow({
  chain: 'ETH',
  amount: 0.5,
  depositorAddress: '0xAlice...',
  beneficiaryAddress: '0xBob...',
  expiresInHours: 48,  // optional (default: 24, max: 720)
  metadata: { order_id: '12345' },  // optional
});

console.log('Deposit to:', escrow.escrowAddress);
console.log('Release token:', escrow.releaseToken);      // Save this! Given to depositor
console.log('Beneficiary token:', escrow.beneficiaryToken); // Save this! Given to beneficiary

Fiat Conversion Support

Convert fiat to crypto amount

// Convert fiat to crypto
const conversion = await client.convertFiatToCrypto(50, 'USD', 'SOL');
console.log(`$50 USD = ${conversion.cryptoAmount} SOL`);
console.log(`Rate: 1 SOL = $${conversion.rate}`);

Create escrow with fiat amount

// Create escrow with fiat amount (auto-converts internally)
const escrow = await client.createEscrow({
  chain: 'SOL',
  amountFiat: 50,
  fiatCurrency: 'USD',
  depositorAddress: '...',
  beneficiaryAddress: '...',
});

console.log(`Escrow created for $50 USD (${escrow.amount} SOL)`);

Get & List Escrows

Get escrow by ID

const escrow = await client.getEscrow('a1b2c3d4-...');
console.log(escrow.status);  // 'created' | 'funded' | 'released' | 'settled' | ...

List escrows with filters

const { escrows, total } = await client.listEscrows({
  status: 'funded',
  depositor: '0xAlice...',   // optional
  beneficiary: '0xBob...',   // optional
  limit: 20,
  offset: 0,
});

Release, Refund & Dispute

Release funds to beneficiary (depositor only)

await client.releaseEscrow('a1b2c3d4-...', 'esc_release_token...');
// Triggers on-chain settlement: funds → beneficiary minus fee

Refund to depositor (depositor only, no fee)

await client.refundEscrow('a1b2c3d4-...', 'esc_release_token...');
// Full amount returned — no platform fee on refunds

Open a dispute (either party)

await client.disputeEscrow('a1b2c3d4-...', 'esc_any_token...', 
  'Work was not delivered as agreed'
);

Events & Polling

Get audit log

const { events } = await client.getEscrowEvents('a1b2c3d4-...');
events.forEach(e => console.log(e.event_type, e.actor, e.created_at));

Wait for a specific status

// Poll until escrow reaches target status (or timeout)
const settled = await client.waitForEscrow('a1b2c3d4-...', 'settled', {
  intervalMs: 5000,   // check every 5s
  timeoutMs: 300000,  // timeout after 5min
});

Escrow Management

Authenticate with escrow tokens to manage escrows and determine available actions based on your role.

Authenticate and manage escrow

// Authenticate with escrow token
const { escrow, role } = await client.authenticateEscrow('escrow-id', 'token');
console.log(`Your role: ${role}`); // 'depositor' or 'beneficiary'

// Check available actions based on role and status
if (escrow.status === 'funded') {
  if (role === 'depositor') {
    console.log('Available actions: release, refund, dispute');
  } else if (role === 'beneficiary') {
    console.log('Available actions: dispute');
  }
}

Depositor workflow

// Depositor can release or refund
const auth = await client.authenticateEscrow(escrowId, releaseToken);
if (auth.role === 'depositor') {
  // Release to beneficiary
  await client.releaseEscrow(escrowId, releaseToken);
  
  // Or refund to self (if needed)
  // await client.refundEscrow(escrowId, releaseToken);
}

Beneficiary workflow

// Beneficiary can check status and dispute if needed
const auth = await client.authenticateEscrow(escrowId, beneficiaryToken);
if (auth.role === 'beneficiary') {
  console.log(`Escrow status: ${auth.escrow.status}`);
  
  // Open dispute if work not delivered
  if (auth.escrow.status === 'funded' && workNotDelivered) {
    await client.disputeEscrow(escrowId, beneficiaryToken, 
      'Work was not delivered as agreed upon'
    );
  }
}

Web Management: Both parties can also manage escrows through the web interface at /escrow/manage?id=xxx&token=yyy. Share the escrow ID and appropriate token for easy access.

Recurring Escrow Series

Create and manage automated periodic escrow payments. Supports both crypto and card payment methods.

Create Escrow Series

Create a recurring escrow series

const series = await client.createEscrowSeries({
  business_id: 'biz_123',
  payment_method: 'crypto',             // 'crypto' or 'card'
  customer_email: 'client@example.com',
  description: 'Weekly retainer — frontend dev',
  amount: 500,
  currency: 'USD',
  coin: 'USDC_SOL',                     // Required for crypto
  interval: 'weekly',                   // 'weekly' | 'biweekly' | 'monthly'
  max_periods: 12,                      // Optional: stop after N periods
  beneficiary_address: 'Bob...',        // Required for crypto
  // stripe_account_id: 'acct_...',     // Required for card method
});

console.log('Series ID:', series.id);
console.log('Next charge:', series.next_charge_at);

List Escrow Series

List series for a business

// List all active series
const { series, total } = await client.listEscrowSeries('biz_123', 'active');

// List all series (no status filter)
const all = await client.listEscrowSeries('biz_123');

Get Series Details

Get series with child escrows

const { series, escrows } = await client.getEscrowSeries('series_abc123');

console.log('Status:', series.status);
console.log('Periods completed:', series.periods_completed);
escrows.forEach(e => {
  console.log(`  Period ${e.period}: ${e.status} — ${e.amount} ${series.currency}`);
});

Update Series

Pause, resume, or change amount

// Pause a series
await client.updateEscrowSeries('series_abc123', { status: 'paused' });

// Resume a series
await client.updateEscrowSeries('series_abc123', { status: 'active' });

// Change amount for future periods
await client.updateEscrowSeries('series_abc123', { amount: 750 });

Cancel Series

Permanently cancel a series

await client.cancelEscrowSeries('series_abc123');
// In-flight escrows are not affected — release or refund them individually

CLI Commands

Recurring escrow CLI

# Create a recurring escrow series
coinpay escrow series create \
  --business-id biz_123 \
  --payment-method crypto \
  --email client@example.com \
  --amount 500 --currency USD --coin USDC_SOL \
  --interval weekly --max-periods 12 \
  --beneficiary Bob...

# List series for a business
coinpay escrow series list --business-id biz_123
coinpay escrow series list --business-id biz_123 --status active

# Get series details (includes child escrows)
coinpay escrow series get series_abc123

# Pause a series
coinpay escrow series pause series_abc123

# Resume a series
coinpay escrow series resume series_abc123

# Cancel a series permanently
coinpay escrow series cancel series_abc123

Exchange Rates

Get real-time cryptocurrency exchange rates in multiple fiat currencies. Supports fiat conversions for payments and escrows.

Get Single Rate

Get exchange rate for one cryptocurrency

// Get rate in USD (default)
const rate = await client.getExchangeRate('BTC');
console.log(`1 BTC = $${rate.price} USD`);

// Get rate in specific fiat currency
const eurRate = await client.getExchangeRate('SOL', 'EUR');
console.log(`1 SOL = €${eurRate.price} EUR`);

Get Multiple Rates

Get rates for multiple cryptocurrencies

// Get multiple rates in USD (default)
const rates = await client.getExchangeRates(['BTC', 'ETH', 'SOL']);

// Get multiple rates in specific fiat currency
const gbpRates = await client.getExchangeRates(['BTC', 'ETH', 'SOL'], 'GBP');
console.log(`BTC: £${gbpRates.rates.BTC}`);

Fiat Conversion

Convert fiat amounts to crypto

// Convert $100 USD to BTC
const conversion = await client.convertFiatToCrypto(100, 'USD', 'BTC');
console.log(`$100 USD = ${conversion.cryptoAmount.toFixed(8)} BTC`);

// Convert €50 EUR to SOL
const eurConversion = await client.convertFiatToCrypto(50, 'EUR', 'SOL');
console.log(`€50 EUR = ${eurConversion.cryptoAmount.toFixed(6)} SOL`);

Supported Fiat Currencies

USD
EUR
GBP
CAD
AUD
JPY
CHF
CNY
INR
BRL

Supported Blockchains

Bitcoin
BTC
Bitcoin Cash
BCH
Ethereum
ETH
Polygon
POL
Solana
SOL
USDC (Ethereum)
USDC_ETH
USDC (Polygon)
USDC_POL
USDC (Solana)
USDC_SOL

Webhook Verification

Verify webhook signatures to ensure requests are from CoinPay:

Manual Verification

Verify webhook signature

import { verifyWebhookSignature } from '@profullstack/coinpay';

// In your webhook handler
const isValid = verifyWebhookSignature({
  payload: rawBody,  // Raw request body as string
  signature: req.headers['x-coinpay-signature'],
  secret: 'your-webhook-secret',
});

if (!isValid) {
  return res.status(401).json({ error: 'Invalid signature' });
}

// Process the webhook...

Express Middleware

Use the webhook handler middleware

import express from 'express';
import { createWebhookHandler } from '@profullstack/coinpay';

const app = express();

// Use raw body parser for webhook route
app.post('/webhook', 
  express.raw({ type: 'application/json' }),
  createWebhookHandler({
    secret: 'your-webhook-secret',
    onEvent: async (event) => {
      console.log('Received event:', event.type);
      
      switch (event.type) {
        case 'payment.completed':
          // Handle completed payment
          await fulfillOrder(event.payment_id);
          break;
        case 'payment.expired':
          // Handle expired payment
          await cancelOrder(event.payment_id);
          break;
        case 'payment.failed':
          // Handle failed payment
          await notifyCustomer(event.payment_id);
          break;
      }
    },
    onError: (error) => {
      console.error('Webhook error:', error);
    },
  })
);

Webhook Events

payment.createdPayment was created
payment.pendingPayment is pending confirmation
payment.confirmingPayment is being confirmed on blockchain
payment.completedPayment completed successfully
payment.expiredPayment expired without completion
payment.failedPayment failed
payment.refundedPayment was refunded

Webhook Logs

Get webhook delivery logs

// Get recent webhook logs for a business
const logs = await client.getWebhookLogs('biz_123', 50);

logs.forEach(log => {
  console.log(`${log.event}: ${log.status} (${log.statusCode})`);
});

// Test webhook endpoint
const result = await client.testWebhook('biz_123', 'payment.completed');
console.log(`Test delivery: ${result.success ? 'OK' : 'Failed'}`);

CLI Commands

The CoinPay CLI provides command-line access to all API features:

Configuration

Configure CLI

# Set your API key
coinpay config set-key sk_live_xxxxx

# Set custom API URL (optional)
coinpay config set-url https://custom-api.example.com

# Show current configuration
coinpay config show

Payment Commands

Payment operations

# Create a Bitcoin payment
coinpay payment create \
  --business-id biz_123 \
  --amount 100 \
  --blockchain BTC \
  --description "Order #12345"

# Create a USDC payment on Polygon
coinpay payment create \
  --business-id biz_123 \
  --amount 50 \
  --blockchain USDC_POL

# Get payment details
coinpay payment get pay_abc123

# List payments
coinpay payment list --business-id biz_123 --status completed --limit 20

# Generate QR code
coinpay payment qr pay_abc123 --format png > payment-qr.png

Business Commands

Business operations

# Create a business
coinpay business create --name "My Store" --webhook-url https://example.com/webhook

# Get business details
coinpay business get biz_123

# List all businesses
coinpay business list

# Update business
coinpay business update biz_123 --name "New Name" --webhook-url https://new-url.com/webhook

Exchange Rate Commands

Rate operations

# Get rate for single cryptocurrency in USD (default)
coinpay rates get BTC

# Get rate in specific fiat currency
coinpay rates get SOL --fiat EUR

# List all supported rates in USD
coinpay rates list

# List all supported rates in EUR
coinpay rates list --fiat EUR

Escrow Commands

Escrow operations

# Create escrow with crypto amount
coinpay escrow create --chain ETH --amount 0.5 \
  --depositor 0xAlice... --beneficiary 0xBob...

# Create escrow with fiat amount
coinpay escrow create --chain SOL --amount-fiat 50 --fiat USD \
  --depositor abc... --beneficiary def...

# Create escrow with EUR amount
coinpay escrow create --chain SOL --amount-fiat 45 --fiat EUR \
  --depositor abc... --beneficiary def...

# Authenticate and manage escrow with token
coinpay escrow auth <id> --token <token>

# Get escrow details
coinpay escrow get a1b2c3d4-...

# List escrows by status
coinpay escrow list --status funded

# Release funds (depositor)
coinpay escrow release a1b2c3d4-... --token esc_abc123...

# Refund (depositor, no fee)
coinpay escrow refund a1b2c3d4-... --token esc_abc123...

# Open dispute (either party)
coinpay escrow dispute a1b2c3d4-... --token esc_def456... \
  --reason "Work not delivered as agreed"

# View audit log
coinpay escrow events a1b2c3d4-...

Webhook Commands

Webhook operations

# View webhook logs
coinpay webhook logs biz_123 --limit 50

# Test webhook endpoint
coinpay webhook test biz_123 --event payment.completed

Lightning Network (Custodial)

☝️ Custodial wallet: Lightning wallets are custodial — funds are held on CoinPay's LNbits server. This enables instant payments without channel management, but means CoinPay holds the keys. Keep balances small and withdraw regularly.

Enable Lightning

Provision a Lightning wallet

// Enable Lightning for a wallet (provisions LNbits custodial wallet)
const result = await client.lightning.enableWallet({
  wallet_id: 'your-wallet-uuid',
  mnemonic: 'your bip39 mnemonic words...',
});

console.log('Lightning enabled!', result);

Lightning Address

Register and manage Lightning Addresses

// Register a Lightning Address (username@coinpayportal.com)
const addr = await client.lightning.registerAddress({
  wallet_id: 'your-wallet-uuid',
  username: 'alice',  // 3-32 chars, lowercase alphanumeric
});
console.log('Address:', addr.lightning_address);
// → alice@coinpayportal.com

// Get current Lightning Address
const current = await client.lightning.getAddress('your-wallet-uuid');
console.log(current.lightning_address);

// Check if a username is available
const check = await client.lightning.checkAddressAvailable('alice');
console.log(check.available ? 'Available!' : 'Taken');

Create Invoice

Create a BOLT11 invoice to receive sats

const invoice = await client.lightning.createInvoice({
  wallet_id: 'your-wallet-uuid',
  amount_sats: 1000,
  description: 'Coffee payment',
});

console.log('Payment request:', invoice.payment_request);
console.log('Payment hash:', invoice.payment_hash);
// Share the payment_request (BOLT11 string) with the sender

Send Payment

Send sats to a Lightning Address or BOLT11 invoice

// Send to a Lightning Address
const payment = await client.lightning.sendPayment({
  wallet_id: 'your-wallet-uuid',
  destination: 'bob@coinpayportal.com',
  amount_sats: 100,
});
console.log('Sent!', payment.payment_hash);

// Send to a BOLT11 invoice (amount encoded in invoice)
const payment2 = await client.lightning.sendPayment({
  wallet_id: 'your-wallet-uuid',
  destination: 'lnbc1000n1p...',
});

Payment History

List Lightning payments

// List all payments
const result = await client.lightning.listPayments({
  wallet_id: 'your-wallet-uuid',
});

// Filter by direction
const incoming = await client.lightning.listPayments({
  wallet_id: 'your-wallet-uuid',
  direction: 'incoming',
});

// Get specific payment by hash
const payment = await client.lightning.getPayment('abc123...');

CLI Commands

Lightning CLI

# Enable Lightning for a wallet
coinpay ln enable --wallet-id <uuid>

# Register a Lightning Address
coinpay ln address --wallet-id <uuid> --username alice

# Check current Lightning Address
coinpay ln address --wallet-id <uuid>

# Check username availability
coinpay ln address-check --username alice

# Create an invoice
coinpay ln invoice --wallet-id <uuid> --amount 1000 --description "Coffee"

# Send a payment
coinpay ln send --wallet-id <uuid> --to bob@coinpayportal.com --amount 100

# Send to a BOLT11 invoice
coinpay ln send --wallet-id <uuid> --to lnbc1000n1p...

# List payment history
coinpay ln payments --wallet-id <uuid>
coinpay ln payments --wallet-id <uuid> --direction incoming

# Check Lightning balance
coinpay ln balance --wallet-id <uuid>

Error Handling

Handle errors gracefully in your integration:

Error handling example

import { CoinPayClient } from '@profullstack/coinpay';

const client = new CoinPayClient({ apiKey: 'cp_live_your_api_key' });

try {
  const result = await client.createPayment({
    businessId: 'your-business-id',
    amount: 100,
    blockchain: 'BTC',
  });
  
  console.log('Payment created:', result.payment.id);
  console.log('Address:', result.payment.payment_address);
} catch (error) {
  if (error.status === 401) {
    console.error('Invalid API key');
  } else if (error.status === 400) {
    console.error('Invalid request:', error.response?.error);
  } else if (error.status === 429) {
    // Transaction limit exceeded or rate limit
    console.error('Limit exceeded:', error.response?.error);
    console.error('Usage:', error.response?.usage);
  } else {
    console.error('Unexpected error:', error.message);
  }
}

Error Codes

400
Bad Request
Invalid parameters or missing required fields
401
Unauthorized
Invalid or missing API key
403
Forbidden
Access denied to resource
404
Not Found
Resource not found
429
Too Many Requests
Rate limit exceeded
500
Server Error
Internal server error

Account & Auth

Create merchant accounts, authenticate, and manage sessions — all from the CLI or SDK.

CLI Commands

Account management

# Register a new merchant account
coinpay auth register --email you@example.com --password yourpassword --name "Your Name"

# Login to get a JWT token (saved to config)
coinpay auth login --email you@example.com --password yourpassword

# Check who you're logged in as
coinpay auth me

SDK Methods

Authentication

import { CoinPayClient, registerMerchant, loginMerchant, getMe } from '@profullstack/coinpay';

// Create a client (no API key needed for registration)
const client = new CoinPayClient({ apiKey: 'unused', baseUrl: 'https://coinpayportal.com' });

// Register a new merchant
const { token, merchant } = await registerMerchant(client, {
  email: 'agent@example.com',
  password: 'securepassword',
  name: 'My Agent'
});
console.log('JWT:', token);
console.log('Merchant ID:', merchant.id);

// Login
const login = await loginMerchant(client, {
  email: 'agent@example.com',
  password: 'securepassword'
});
console.log('JWT:', login.token);

// Get current merchant info (requires JWT auth)
const me = await getMe(client);
console.log('Logged in as:', me.email);

Full Onboarding Flow

Register → Create Business → Claim DID

# 1. Register your account
coinpay auth register --email agent@example.com --password mypass123

# 2. Create a business (generates API key)
coinpay business create --name "My Agency" --chain ETH,SOL,BTC

# 3. Set your API key
coinpay config set-key cp_live_your_key_here

# 4. Claim your DID
coinpay reputation did claim

# 5. Check your reputation
coinpay reputation did

Reputation & DID

Track agent reputation, manage DIDs, and work with verifiable credentials.

SDK Methods

DID Management

import { CoinPayClient } from '@profullstack/coinpay';

const client = new CoinPayClient({ apiKey: 'cp_live_your_api_key' });

// Claim a DID
const did = await client.claimDid({ displayName: 'Agent Smith' });
console.log('DID:', did.did);

// Get your DID
const myDid = await client.getMyDid();
console.log('My DID:', myDid.did);

// Link an external DID
await client.linkDid({ externalDid: 'did:web:example.com' });

Reputation & Receipts

// Submit a task receipt (after escrow settlement)
const receipt = await client.submitReceipt({
  escrowId: 'esc_abc123',
  taskDescription: 'Frontend bug fix',
  rating: 5,
  counterpartyDid: 'did:coinpay:xyz789...',
});
console.log('Receipt:', receipt.receiptId);

// Query reputation for a DID
const rep = await client.queryReputation('did:coinpay:abc123...');
console.log('Score:', rep.score, 'Tasks:', rep.totalTasks);

Verifiable Credentials

// Get a credential
const cred = await client.getCredential('cred_ghi789');
console.log('Credential:', cred.credential);

// Verify a credential
const result = await client.verifyCredential('cred_ghi789');
console.log('Valid:', result.valid, 'Revoked:', result.revoked);

// Get revocation list
const revocations = await client.getRevocations();
console.log('Revoked credentials:', revocations.revocations.length);

// List all credentials for a DID
const creds = await client.getCredentials('did:key:z6Mk...');
console.log('Credentials:', creds.credentials.length);

// List all task receipts for a DID
const receipts = await client.getReceipts('did:key:z6Mk...');
console.log('Receipts:', receipts.receipts.length);

// Get embeddable reputation badge URL
import { getBadgeUrl } from '@profullstack/coinpay';
const badgeUrl = getBadgeUrl('https://coinpayportal.com', 'did:key:z6Mk...');
// Use in markdown: ![Reputation](badgeUrl)

CLI Commands

DID commands

# Claim a DID
coinpay reputation did claim --name "Agent Smith"

# Get your DID
coinpay reputation did

# Link an external DID
coinpay reputation did link --did "did:web:example.com"

Reputation commands

# Submit a receipt
coinpay reputation submit --escrow esc_abc123 --rating 5 --description "Bug fix"

# Query reputation
coinpay reputation query did:key:z6Mk...

# Get a credential
coinpay reputation credential cred_ghi789

# List all your credentials
coinpay reputation credentials

# List credentials for another DID
coinpay reputation credentials did:key:z6Mk...

# List your task receipts
coinpay reputation receipts

# List receipts for another DID
coinpay reputation receipts did:key:z6Mk...

# Get your embeddable reputation badge URL
coinpay reputation badge

# Get badge for another DID
coinpay reputation badge did:key:z6Mk...

# Verify a credential
coinpay reputation verify cred_ghi789

# List revocations
coinpay reputation revocations

TypeScript Support

The SDK is written in JavaScript (ESM) but includes JSDoc type annotations for IDE support:

Type hints in VS Code

import { CoinPayClient, Blockchain, PaymentStatus } from '@profullstack/coinpay';

// Use Blockchain constants for type safety
const result = await client.createPayment({
  businessId: 'biz_123',
  amount: 100,
  blockchain: Blockchain.BTC,  // BTC, BCH, ETH, POL, SOL, DOGE, XRP, ADA, BNB, USDT, USDC, USDC_ETH, USDC_POL, USDC_SOL
});

// result.payment.status: 'pending' | 'detected' | 'confirmed' | 'forwarding' | 'forwarded' | 'expired' | 'failed'
// result.payment.payment_address: string
// result.payment.crypto_amount: string

Trust Profile & Action Receipts (CPTL v2)

Phase 2 adds multi-dimensional trust scoring with categorized action receipts.

Submit Action Receipt

import { submitActionReceipt } from '@profullstack/coinpay/reputation';

const result = await submitActionReceipt(client, {
  receipt_id: '550e8400-...',
  task_id: '550e8400-...',
  agent_did: 'did:key:z6Mk...',
  buyer_did: 'did:key:z6Mk...',
  action_category: 'productivity.completion', // canonical category
  action_type: 'code_review',                 // custom action type
  amount: 250,
  currency: 'USD',
  outcome: 'accepted',
  signatures: { escrow_sig: '...' },
});

Get Trust Profile

import { getTrustProfile } from '@profullstack/coinpay/reputation';

const profile = await getTrustProfile(client, 'did:key:z6Mk...');
// profile.trust_vector = { E: 42.5, P: 12.3, B: 9.1, D: 2.08, R: 0.87, A: 0, C: 0 }
// profile.reputation = { windows: { ... }, anti_gaming: { ... } }
// profile.computed_at = "2026-02-13T..."

Valid action categories: economic.transaction, economic.dispute,economic.refund, productivity.task, productivity.application,productivity.completion, identity.profile_update,identity.verification, social.post, social.comment,social.endorsement, compliance.incident, compliance.violation