New:Socket for Asana Is Now Available.Learn more
Get Started

@profullstack/coinpay

Package Overview
Dependencies
Maintainers
2
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@profullstack/coinpay

CoinPay SDK & CLI — Accept cryptocurrency and card payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet, swap and a live finances dashboard

latest
Source
npmnpm
Version
0.9.0
Version published
Maintainers
2
Created
Source

@profullstack/coinpay

CoinPay SDK & CLI — Accept cryptocurrency payments in your Node.js application.

npm version License: MIT Node.js

Non-custodial, multi-chain payment processing for Bitcoin, Ethereum, Solana, Polygon, Bitcoin Cash, and USDC (on ETH, POL, SOL).

Table of Contents

How It Works

┌──────────┐    1. Create payment     ┌──────────┐
│  Your    │ ───────────────────────> │ CoinPay  │
│  Server  │ <─────────────────────── │   API    │
│          │    Address + QR code     │          │
└────┬─────┘                          └────┬─────┘
     │                                     │
     │  2. Show address/QR                 │  4. Webhook notification
     │     to customer                     │     (payment confirmed)
     ▼                                     │
┌──────────┐    3. Sends crypto       ┌────▼─────┐
│ Customer │ ───────────────────────> │Blockchain│
│          │                          │ Network  │
└──────────┘                          └──────────┘
  • Your server calls the CoinPay API to create a payment request
  • CoinPay generates a unique payment address and QR code — display these to your customer
  • Customer sends cryptocurrency to the address
  • CoinPay monitors the blockchain and notifies you via webhook when payment is confirmed
  • Funds are automatically forwarded to your configured wallet

Installation

# pnpm (recommended)
pnpm add @profullstack/coinpay

# npm
npm install @profullstack/coinpay

# Global CLI
pnpm add -g @profullstack/coinpay

Requirements: Node.js ≥ 20. Zero runtime dependencies — uses built-in fetch and crypto.

Quick Start

1. Get Your API Key

  • Sign up at coinpayportal.com
  • Create a business in your dashboard
  • Configure wallet addresses for each crypto you want to accept
  • Copy your API key (starts with cp_live_)

2. Create a Payment

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

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

const { payment } = await client.createPayment({
  businessId: 'your-business-id',
  amount: 99.99,
  currency: 'USD',
  blockchain: Blockchain.BTC,
  description: 'Order #12345',
  metadata: { orderId: '12345' },
});

console.log('Send payment to:', payment.payment_address);
console.log('Amount:', payment.crypto_amount, 'BTC');
console.log('QR Code:', payment.qr_code);

3. Handle Payment Confirmation

import { createWebhookHandler, WebhookEvent } from '@profullstack/coinpay';

app.post('/webhook', createWebhookHandler({
  secret: 'your-webhook-secret',
  onEvent: async (event) => {
    if (event.type === WebhookEvent.PAYMENT_COMPLETED) {
      const orderId = event.data.payment.metadata.orderId;
      await markOrderAsPaid(orderId);
    }
  },
}));

Supported Blockchains

BlockchainCodeType
BitcoinBTCNative
Bitcoin CashBCHNative
EthereumETHNative
PolygonPOLNative
SolanaSOLNative
USDC (Ethereum)USDC_ETHStablecoin
USDC (Polygon)USDC_POLStablecoin
USDC (Solana)USDC_SOLStablecoin

Use the Blockchain constant to avoid typos:

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

Blockchain.BTC      // 'BTC'
Blockchain.ETH      // 'ETH'
Blockchain.USDC_POL // 'USDC_POL'

API Reference

CoinPayClient

The main class for all API operations.

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

const client = new CoinPayClient({
  apiKey: 'cp_live_xxxxx',                     // Required
  baseUrl: 'https://coinpayportal.com/api',    // Optional (default)
  timeout: 30000,                               // Optional: ms (default: 30s)
});
OptionTypeDefaultDescription
apiKeystringRequired. Your CoinPay API key
baseUrlstringhttps://coinpayportal.com/apiAPI base URL
timeoutnumber30000Request timeout in milliseconds

Throws Error if apiKey is missing or empty.

Payments

client.createPayment(params)

Create a new payment request. Generates a unique blockchain address for the customer to pay.

const { payment, usage } = await client.createPayment({
  businessId: 'biz_123',      // Required — from your dashboard
  amount: 100.00,             // Required — fiat amount
  currency: 'USD',            // Optional — fiat currency (default: 'USD')
  blockchain: 'ETH',          // Required — see Supported Blockchains
  description: 'Order #123',  // Optional — shown to customer
  metadata: {                 // Optional — your custom data
    orderId: '123',
    customerEmail: 'a@b.com',
  },
});

Parameters:

ParamTypeRequiredDescription
businessIdstringBusiness ID from your dashboard
amountnumberAmount in fiat currency
currencystringFiat currency code (default: 'USD'). Supports: USD, EUR, GBP, CAD, AUD
blockchainstringBlockchain code (e.g., 'BTC', 'ETH', 'USDC_POL')
descriptionstringPayment description visible to the customer
metadataobjectArbitrary key-value data attached to the payment

Returns:

{
  success: true,
  payment: {
    id: 'pay_abc123',
    business_id: 'biz_123',
    amount: 100,
    currency: 'USD',
    blockchain: 'ETH',
    crypto_amount: '0.0456',
    payment_address: '0x1234...5678',
    qr_code: 'data:image/png;base64,...',
    status: 'pending',
    expires_at: '2024-01-01T01:00:00.000Z',
    created_at: '2024-01-01T00:00:00.000Z',
    metadata: { orderId: '123' }
  },
  usage: {
    current: 45,
    limit: 100,
    remaining: 55
  }
}

client.getTokens(params?)

List checkout-ready tokens for a business. Use this instead of hard-coding a coin list. Business wallets take priority; merchant global wallets are used as fallback.

const { tokens } = await client.getTokens({
  businessId: 'biz_123',
  activeOnly: true,
});

for (const token of tokens) {
  console.log(token.code); // "btc", "usdc_pol", ...
}
ParamTypeRequiredDescription
businessIdstringJWT onlyOptional with a business API key; if set, it must match the key scope
activeOnlybooleanReturn active wallets only

client.getSupportedCoins(params?)

Returns the lower-level /api/supported-coins shape with coins instead of token-picker code fields.

client.getPayment(paymentId)

Retrieve a payment by its ID.

const { payment } = await client.getPayment('pay_abc123');

console.log(payment.status);          // 'pending', 'confirmed', etc.
console.log(payment.crypto_amount);   // '0.0456'
console.log(payment.tx_hash);         // '0xabc...def' (once detected)

client.listPayments(params)

List payments for a business with optional filtering and pagination.

const { payments } = await client.listPayments({
  businessId: 'biz_123',     // Required
  status: 'completed',       // Optional — filter by status
  limit: 20,                 // Optional — results per page (default: 20)
  offset: 0,                 // Optional — pagination offset (default: 0)
});

Payment Status Polling

client.waitForPayment(paymentId, options?)

Polls getPayment() until the payment reaches a terminal status. Useful for simple integrations that don't use webhooks.

const { payment } = await client.waitForPayment('pay_abc123', {
  interval: 5000,        // Poll every 5s (default)
  timeout: 600000,       // Give up after 10 min (default: 1 hour)
  targetStatuses: ['confirmed', 'forwarded', 'expired', 'failed'],
  onStatusChange: (status, payment) => {
    console.log(`Status → ${status}`);
  },
});

if (payment.status === 'confirmed' || payment.status === 'forwarded') {
  console.log('Payment successful!');
}
OptionTypeDefaultDescription
intervalnumber5000Polling interval in ms
timeoutnumber3600000Max wait time in ms
targetStatusesstring[]['confirmed','forwarded','expired','failed']Statuses that stop polling
onStatusChangefunctionCallback (status, payment) => void

⚠️ For production, use webhooks instead of polling.

Payment Statuses

StatusDescription
pendingWaiting for customer to send payment
detectedPayment detected on blockchain, awaiting confirmations
confirmedPayment confirmed — safe to fulfill the order
forwardingForwarding funds to your wallet
forwardedFunds successfully sent to your wallet
expiredPayment request expired (customer didn't pay in time)
failedPayment failed

QR Codes

client.getPaymentQRUrl(paymentId)

Returns the URL to the QR code image. Synchronous — no network request.

const url = client.getPaymentQRUrl('pay_abc123');
// "https://coinpayportal.com/api/payments/pay_abc123/qr"

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

client.getPaymentQR(paymentId)

Fetches the QR code as binary PNG data.

import fs from 'fs';

const imageData = await client.getPaymentQR('pay_abc123');
fs.writeFileSync('payment-qr.png', Buffer.from(imageData));

Exchange Rates

client.getExchangeRate(crypto, fiat?)

Get the exchange rate for a single cryptocurrency.

const rate = await client.getExchangeRate('BTC', 'USD');

client.getExchangeRates(cryptos, fiat?)

Get rates for multiple cryptocurrencies in one request.

const rates = await client.getExchangeRates(['BTC', 'ETH', 'SOL'], 'USD');

Business Management

client.createBusiness(params)

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

client.getBusiness(businessId)

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

client.listBusinesses()

const result = await client.listBusinesses();

client.updateBusiness(businessId, params)

const result = await client.updateBusiness('biz_123', {
  name: 'Updated Store Name',
  webhookUrl: 'https://mystore.com/webhook/v2',
});

Webhooks

client.getWebhookLogs(businessId, limit?)

Retrieve recent webhook delivery logs.

const logs = await client.getWebhookLogs('biz_123', 50);

client.testWebhook(businessId, eventType?)

Send a test webhook event to your configured endpoint.

await client.testWebhook('biz_123', 'payment.completed');

Standalone Functions

Convenience functions that auto-create a client. Best for one-off operations.

import { createPayment, getPayment, listPayments } from '@profullstack/coinpay';

// Create payment without instantiating a client
const result = await createPayment({
  apiKey: 'cp_live_xxxxx',
  businessId: 'biz_123',
  amount: 50,
  blockchain: 'BTC',
});

// Or pass an existing client
const result2 = await createPayment({
  client: existingClient,
  businessId: 'biz_123',
  amount: 50,
  blockchain: 'BTC',
});

// Get payment
const payment = await getPayment({
  apiKey: 'cp_live_xxxxx',
  paymentId: 'pay_abc123',
});

// List payments
const list = await listPayments({
  apiKey: 'cp_live_xxxxx',
  businessId: 'biz_123',
  status: 'completed',
  limit: 10,
});

Constants

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

Blockchain

KeyValueDescription
BTC'BTC'Bitcoin
BCH'BCH'Bitcoin Cash
ETH'ETH'Ethereum
POL'POL'Polygon
SOL'SOL'Solana
USDC_ETH'USDC_ETH'USDC on Ethereum
USDC_POL'USDC_POL'USDC on Polygon
USDC_SOL'USDC_SOL'USDC on Solana

Cryptocurrency is exported as a deprecated alias for Blockchain.

PaymentStatus

KeyValue
PENDING'pending'
CONFIRMING'confirming'
COMPLETED'completed'
EXPIRED'expired'
FAILED'failed'
REFUNDED'refunded'

FiatCurrency

KeyValue
USD'USD'
EUR'EUR'
GBP'GBP'
CAD'CAD'
AUD'AUD'

WebhookEvent

KeyValue
PAYMENT_CREATED'payment.created'
PAYMENT_PENDING'payment.pending'
PAYMENT_CONFIRMING'payment.confirming'
PAYMENT_COMPLETED'payment.completed'
PAYMENT_EXPIRED'payment.expired'
PAYMENT_FAILED'payment.failed'
PAYMENT_REFUNDED'payment.refunded'
BUSINESS_CREATED'business.created'
BUSINESS_UPDATED'business.updated'

CLI Reference

Installation

# Global
pnpm add -g @profullstack/coinpay

# Or use npx
npx @profullstack/coinpay --help

Configuration

coinpay config set-key cp_live_xxxxx     # Save API key
coinpay config set-url http://localhost:3000/api  # Custom URL
coinpay config show                       # Display config

Payments

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

# Get payment details
coinpay payment get pay_abc123

# List payments
coinpay payment list --business-id biz_123 --status pending --limit 10

# List checkout tokens
coinpay tokens list --business-id biz_123 --active-only

# Get QR code
coinpay payment qr pay_abc123

Invoices

Invoice creation is draft-only. It does not send the invoice or move funds. Drafts do not have a public payment link. Publish the draft to create payment details for manual sharing, or send it to create payment details and email the client. When using a business-scoped API key, --business-id may be omitted.

# Create a draft invoice
coinpay invoice create \
  --amount 250 \
  --currency USD \
  --client-id cli_001 \
  --crypto-currency USDC \
  --due-date 2026-09-01 \
  --notes "August development"

# Route eventual settlement through a saved wallet or a direct address
coinpay invoice create --amount 250 --wallet-id wal_001
coinpay invoice create --amount 250 --merchant-wallet-address 0xabc123

# Get invoice details
coinpay invoice get inv_abc123

# Update editable fields on a draft. Use --notes= to clear existing notes.
coinpay invoice update inv_abc123 \
  --amount 275 \
  --due-date 2026-09-15 \
  --notes "Updated scope"

# Publish creates real payment details without emailing the client. It asks for
# confirmation and prints a live /now/{invoiceId} link for manual chat sharing.
coinpay invoice publish inv_abc123

# Non-interactive publish requires explicit confirmation.
coinpay invoice publish inv_abc123 --yes --json

# Send creates real payment details and emails the client. The command asks for
# confirmation and prints the same /now/{invoiceId} link for manual chat sharing.
coinpay invoice send inv_abc123

# Non-interactive send requires explicit confirmation. JSON stays on stdout.
coinpay invoice send inv_abc123 --yes --json

# Permanently delete a draft invoice (also asks for confirmation).
coinpay invoice delete inv_abc123

# List invoices. Date filters apply to created_at and --date-to includes that day.
coinpay invoice list \
  --business-id biz_123 \
  --status sent \
  --client-id cli_001 \
  --date-from 2026-08-01 \
  --date-to 2026-08-31

# Use --json with any invoice command for machine-readable output
coinpay invoice list --status paid --json

Only draft invoices can be updated or deleted. Draft and overdue invoices can be sent; sending an overdue invoice issues new payment details and emails the client again. Only drafts can be published. --yes skips the confirmation for publish/send/delete, and is required when any of those commands runs without a terminal or with --json.

--wallet-id updates the invoice's stored wallet reference. To change the actual settlement destination, use --merchant-wallet-address (or change the crypto currency and let the server resolve the configured payee).

The CLI does not post invoice links to /chat automatically. Copy the printed share link into chat manually. Treat COINPAY_API_KEY and ~/.coinpay.json as sensitive: either credential can authorize invoice updates, sends, and deletes.

Businesses

coinpay business list
coinpay business get biz_123
coinpay business create --name "My Store" --webhook-url https://mysite.com/webhook
coinpay business update biz_123 --name "New Name"

Exchange Rates

coinpay rates get BTC
coinpay rates list

Webhooks

coinpay webhook logs biz_123
coinpay webhook test biz_123 --event payment.completed

Finances — your money in one place

coinpay finances                 # live dashboard (needs `coinpay login`)
coinpay finances --days 90       # window for earnings / cashflow: 7, 30, 90, 365
coinpay finances summary         # plain text, --json for machines
coinpay finances position        # debt vs income, credits vs debits (also: debt)
coinpay finances accounts        # linked bank & credit-card accounts (SimpleFIN / Plaid)
coinpay finances ledger --search anthropic --limit 20
coinpay finances connections     # institutions and their last sync
coinpay finances sync            # pull fresh balances (rate-limited by the bank bridge)

The dashboard has seven screens (17, Tab): Overview (gross volume, crypto vs cards, commission paid, processor fees, refunds, net earnings, bank position, cashflow, invoices, escrow, payouts, a volume-vs-commission graph and a live feed), Bank & Cards, Ledger, Crypto, Cards, Invoices & Escrow, Debt & Income. r refreshes, s syncs the bank feed, w cycles the window, p pauses, ? shows help, q quits. It refreshes every 30 seconds (--interval) and listens to the payments event stream, so a crypto payment shows up the moment it is detected.

Debt & Income is the basic-accounting view, and it reads the same for a company or a person: income against spending per month, total owed split into revolving and instalment, months to clear each balance at its current payment rate, debt-to-income, debt-service ratio, months of cover, card utilisation, the recurring bills it found with their next due date, and a business-versus-personal split of all of it.

Two things about those numbers. Transfers and card payments are excluded from both income and spending — a feed holding both a checking account and the card it pays contains every card payment twice, so counting raw credits as income inflates both sides by the whole card-payment volume. The untouched totals stay on screen as gross credits and gross debits, so the netting is auditable. And the figures come from about six months of history rather than the dashboard window (w does not move them), because a monthly charge cannot be seen in thirty days of rows; the per-month averages divide by the history that actually exists, which for a recently linked feed is much less than six months.

It is built on @profullstack/hqtui and needs Node 22.6+; the plain-text subcommands work on Node 20. Bank data needs the merchant session from coinpay login (business API keys are refused on purpose).

From the SDK:

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

const client = new CoinPayClient({ apiKey: sessionToken });
const snapshot = await collectFinanceSnapshot(client, { days: 30 });
console.log(snapshot.earnings.netUsd, snapshot.bank.liabilities, snapshot.invoices.totals.overdue);

Webhook Integration

Webhook Payload

When a payment status changes, CoinPay sends a POST request to your webhook URL:

{
  "id": "evt_abc123",
  "type": "payment.completed",
  "created_at": "2024-01-01T00:15:00.000Z",
  "business_id": "biz_123",
  "data": {
    "payment": {
      "id": "pay_abc123",
      "status": "confirmed",
      "amount": 100.00,
      "currency": "USD",
      "crypto_amount": "0.0456",
      "blockchain": "ETH",
      "tx_hash": "0xabc...def",
      "metadata": { "orderId": "12345" }
    }
  }
}

Signature Verification

Every webhook includes an X-CoinPay-Signature header in the format t=<timestamp>,v1=<hmac-sha256>. Always verify signatures before processing events.

Using the Middleware (Express)

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

const app = express();

app.post('/webhook',
  express.text({ type: 'application/json' }),
  createWebhookHandler({
    secret: process.env.COINPAY_WEBHOOK_SECRET,
    onEvent: async (event) => {
      switch (event.type) {
        case WebhookEvent.PAYMENT_COMPLETED:
          await fulfillOrder(event.data.payment.metadata.orderId);
          break;
        case WebhookEvent.PAYMENT_EXPIRED:
          await cancelOrder(event.data.payment.metadata.orderId);
          break;
      }
    },
    onError: (error) => {
      console.error('Webhook error:', error);
    },
  })
);

Manual Verification

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

const isValid = verifyWebhookSignature({
  payload: rawBody,                              // Raw request body string
  signature: req.headers['x-coinpay-signature'], // Signature header
  secret: process.env.COINPAY_WEBHOOK_SECRET,    // Your secret
  tolerance: 300,                                 // Optional: seconds (default: 300)
});

if (isValid) {
  const event = parseWebhookPayload(rawBody);
  // event.id, event.type, event.data, event.createdAt, event.businessId
}

Generating Test Signatures

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

const signature = generateWebhookSignature({
  payload: JSON.stringify(testEvent),
  secret: 'whsec_test_secret',
  timestamp: Math.floor(Date.now() / 1000), // Optional
});
// "t=1705312500,v1=a3f2b1..."

Webhook Events

EventWhen
payment.createdPayment request created
payment.pendingAwaiting blockchain detection
payment.confirmingTransaction detected, awaiting confirmations
payment.completedPayment confirmed — safe to fulfill
payment.expiredCustomer didn't pay in time
payment.failedPayment failed
payment.refundedPayment was refunded
business.createdNew business created
business.updatedBusiness settings updated

Error Handling

All API errors include a status code and optional response object:

try {
  const payment = await client.createPayment({ ... });
} catch (error) {
  console.log(error.message);   // Human-readable message
  console.log(error.status);    // HTTP status code (401, 400, 429, etc.)
  console.log(error.response);  // Full error response from the API

  switch (error.status) {
    case 400:
      // Invalid request — check parameters
      break;
    case 401:
      // Invalid API key
      break;
    case 404:
      // Resource not found
      break;
    case 429:
      // Rate limit or transaction limit exceeded
      console.log('Usage:', error.response?.usage);
      break;
  }
}

Timeout errors throw a standard Error with message "Request timeout after {ms}ms".

Constructor errors throw if apiKey is missing: "API key is required".

Integration Patterns

E-commerce Checkout

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

const client = new CoinPayClient({ apiKey: process.env.COINPAY_API_KEY });

// Checkout endpoint
app.post('/checkout', async (req, res) => {
  const { orderId, amount, blockchain } = req.body;

  const { payment } = await client.createPayment({
    businessId: process.env.COINPAY_BUSINESS_ID,
    amount,
    blockchain,
    description: `Order #${orderId}`,
    metadata: { orderId },
  });

  await db.orders.update(orderId, {
    paymentId: payment.id,
    paymentAddress: payment.payment_address,
  });

  res.json({
    paymentAddress: payment.payment_address,
    cryptoAmount: payment.crypto_amount,
    qrCode: payment.qr_code,
    expiresAt: payment.expires_at,
  });
});

// Webhook
app.post('/webhook', express.text({ type: 'application/json' }),
  createWebhookHandler({
    secret: process.env.COINPAY_WEBHOOK_SECRET,
    onEvent: async (event) => {
      if (event.type === WebhookEvent.PAYMENT_COMPLETED) {
        const { orderId } = event.data.payment.metadata;
        await db.orders.update(orderId, { status: 'paid' });
        await sendConfirmationEmail(orderId);
      }
    },
  })
);

Stablecoin Subscriptions

Use USDC for predictable pricing — no volatility:

const { payment } = await client.createPayment({
  businessId: BUSINESS_ID,
  amount: 9.99,
  blockchain: Blockchain.USDC_POL,  // USDC on Polygon — low fees
  description: 'Monthly subscription',
  metadata: { userId: user.id, period: '2024-01' },
});

Direct API (fetch / cURL)

# Create payment
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": 50.00,
    "currency": "USD",
    "blockchain": "ETH"
  }'

# Check payment status
curl https://coinpayportal.com/api/payments/pay_abc123 \
  -H "Authorization: Bearer cp_live_your_api_key"

TypeScript

Full TypeScript support via .d.ts declaration files — no build step required.

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

import type {
  CoinPayClientOptions,
  PaymentParams,
  Payment,
  CreatePaymentResponse,
  WaitForPaymentOptions,
  VerifyWebhookParams,
  ParsedWebhookEvent,
} from '@profullstack/coinpay';

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

const { payment }: CreatePaymentResponse = await client.createPayment({
  businessId: 'biz_123',
  amount: 100,
  blockchain: Blockchain.ETH,
});

Subpath Imports

// Import only what you need
import { Blockchain, PaymentStatus } from '@profullstack/coinpay/payments';
import { verifyWebhookSignature, WebhookEvent } from '@profullstack/coinpay/webhooks';

Environment Variables

VariableDescription
COINPAY_API_KEYAPI key (overrides config file in CLI)
COINPAY_BASE_URLCustom API URL (for development)

Examples

See the examples/ directory for runnable code:

ExampleDescription
01-quick-start.jsCreate a payment and check status
02-create-payment.jsAll blockchain types, metadata, multi-currency
03-check-payment-status.jsOne-time check and waitForPayment polling
04-list-payments.jsFiltering and pagination
05-exchange-rates.jsSingle and batch rate lookups
06-webhook-handler.jsExpress webhook server
07-ecommerce-checkout.jsComplete checkout → webhook → fulfillment flow
08-business-management.jsCreate, list, and update businesses
09-error-handling.jsAuth, validation, rate-limit, and timeout errors
COINPAY_API_KEY=cp_live_xxx COINPAY_BUSINESS_ID=biz_xxx node examples/01-quick-start.js

Testing

# Run tests
pnpm test

# Watch mode
pnpm test:watch

Tests use Vitest with mocked fetch — no API key needed.

Support

TaskMarket delegation (x402 v2)

@profullstack/coinpay/taskmarket lets an agent or user create and fund a TaskMarket task from inside a CoinPay-powered app, using the standard x402 v2 transfer-authorization flow this SDK already speaks.

import { createTask, discoverTasks, getTask, listSubmissions } from '@profullstack/coinpay/taskmarket';

// Browse open work (public endpoint)
const open = await discoverTasks({ status: 'open', limit: 25, mode: 'bounty' });

// Create + fund a task. The wallet signs the EIP-712 transfer authorization
// itself; this module never sees a private key.
const { taskId } = await createTask(
  { title: 'Fix my parser bug', description: 'Repro + expected output attached in the linked issue.', reward: 2500000 },
  {
    signer: myWalletSigner, // { address, signTypedData({domain, types, primaryType, message}) }
    capabilities: ['eip155:8453'],
    spendingLimitUsd: 10,                 // hard cap; refuses anything above
    authorize: async (d) => confirm(`Send ${d.amount} ${d.asset} to ${d.payTo}?`),
  }
);

// Track it and present submissions for human review (never auto-accept)
const live = await getTask(taskId);
const submissions = await listSubmissions(taskId);

Safety: no keys ever enter the module; every payment needs fresh authorize() consent; spendingLimitUsd is enforced against the quoted amount in base units; after a payment with unknown settlement the caller is told to verify with getTask instead of retrying blindly.

License

MIT © Profullstack, Inc.

Keywords

coinpay

FAQs

Package last updated on 06 Sep 2026

Related posts