@zyndpay/sdk
v1.2.2
Published
Official ZyndPay Node.js/TypeScript SDK — accept USDT payments with a few lines of code
Downloads
465
Maintainers
Readme
@zyndpay/sdk
Official ZyndPay Node.js / TypeScript SDK — accept USDT TRC20 payments with a few lines of code.
Requirements
- Node.js 18+
- A ZyndPay account and API key
Installation
npm install @zyndpay/sdk
# or
pnpm add @zyndpay/sdk
# or
yarn add @zyndpay/sdkQuickstart
import { ZyndPay } from '@zyndpay/sdk';
const zyndpay = new ZyndPay({ apiKey: 'zyp_live_sk_...' });
// Create a payment request
const payin = await zyndpay.payins.create({ amount: '100' });
console.log(payin.address); // Send USDT TRC20 here
console.log(payin.paymentUrl); // Redirect your customer here
// Check your balance
const balance = await zyndpay.balances.get();
console.log(balance.balance); // e.g. "97.00"Configuration
const zyndpay = new ZyndPay({
apiKey: 'zyp_live_sk_...', // required
webhookSecret: 'whsec_...', // optional — needed for webhook verification
baseUrl: 'https://api.zyndpay.io/v1', // optional — override for self-hosted
timeout: 30_000, // optional — request timeout in ms (default: 30000)
maxRetries: 2, // optional — retries on network errors (default: 2)
});API key types
| Prefix | Type |
|---|---|
| zyp_live_sk_ | Live secret key |
| zyp_live_pk_ | Live publishable key |
| zyp_test_sk_ | Sandbox secret key |
| zyp_test_pk_ | Sandbox publishable key |
Payins
Create a payin
const payin = await zyndpay.payins.create({
amount: '100', // USDT amount (minimum 25)
externalRef: 'order_9f8e7d', // your internal order ID (optional)
expiresInSeconds: 3600, // 1 hour — default is 24h (optional)
metadata: { userId: 'usr_123' }, // stored as-is (optional)
successUrl: 'https://yoursite.com/success',
cancelUrl: 'https://yoursite.com/cancel',
});
console.log(payin.transactionId); // "uuid"
console.log(payin.address); // TRC20 deposit address
console.log(payin.paymentUrl); // hosted payment page URL
console.log(payin.qrCodeUrl); // QR code data URL
console.log(payin.amount); // "100"
console.log(payin.status); // "AWAITING_PAYMENT"
console.log(payin.expiresAt); // ISO timestampGet a payin
const payin = await zyndpay.payins.get('pay_abc123');List payins
const { items, total } = await zyndpay.payins.list({
status: 'CONFIRMED', // optional filter
page: 1,
limit: 20,
});Payin statuses
| Status | Description |
|---|---|
| PENDING | Just created |
| AWAITING_PAYMENT | Deposit address assigned, waiting for funds |
| CONFIRMING | Payment detected, waiting for confirmations |
| CONFIRMED | Payment confirmed — balance credited |
| EXPIRED | Payment window elapsed |
| OVERPAID | More than expected was sent |
| UNDERPAID | Less than expected was sent |
| FAILED | Processing failed |
Sandbox / Test Mode
Use your sandbox API key (zyp_test_sk_...) and pass sandbox: true when creating a payin. Then call simulate to instantly confirm it without real funds.
const zyndpay = new ZyndPay({ apiKey: 'zyp_test_sk_...' });
// Create a sandbox payin
const payin = await zyndpay.payins.create({
amount: '100',
sandbox: true,
});
// Instantly simulate confirmation
const confirmed = await zyndpay.payins.simulate(payin.transactionId);
console.log(confirmed.status); // "CONFIRMED"Withdrawals
Request a withdrawal
const withdrawal = await zyndpay.withdrawals.create(
{ amount: '50' }, // USDT amount
'idempotency-key-123' // optional idempotency key
);
console.log(withdrawal.status); // "PENDING_REVIEW"
console.log(withdrawal.fee); // "2.00" (flat $2 fee)
console.log(withdrawal.netAmount); // "48.00"Get / list withdrawals
const withdrawal = await zyndpay.withdrawals.get('wdr_abc123');
const { items, total } = await zyndpay.withdrawals.list({
status: 'CONFIRMED',
page: 1,
limit: 20,
});Cancel a withdrawal
await zyndpay.withdrawals.cancel('wdr_abc123'); // only while PENDING_REVIEWWithdrawal statuses
| Status | Description |
|---|---|
| PENDING_REVIEW | Awaiting admin approval |
| APPROVED | Approved, queued for processing |
| PROCESSING | Being broadcast to blockchain |
| BROADCAST | Transaction sent |
| CONFIRMED | On-chain confirmed |
| REJECTED | Rejected by admin |
| CANCELLED | Cancelled by merchant |
| FAILED | Broadcast failed |
Transactions
// Get a single transaction
const tx = await zyndpay.transactions.get('txn_abc123');
// List with filters
const { items, total } = await zyndpay.transactions.list({
type: 'PAYIN', // 'PAYIN' | 'PAYOUT'
status: 'CONFIRMED',
fromDate: '2026-01-01',
toDate: '2026-03-31',
page: 1,
limit: 50,
});Balances
const balance = await zyndpay.balances.get();
console.log(balance.currency); // "USDT_TRC20"
console.log(balance.balance); // current balanceWebhooks
ZyndPay sends signed webhook events to your endpoint. Always verify the signature before processing.
Verify a webhook
import express from 'express';
import { ZyndPay } from '@zyndpay/sdk';
const zyndpay = new ZyndPay({
apiKey: 'zyp_live_sk_...',
webhookSecret: 'whsec_...',
});
const app = express();
// IMPORTANT: use raw body — do not parse JSON before verifying
app.post('/webhooks/zyndpay', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-zyndpay-signature'] as string;
let event;
try {
event = zyndpay.webhooks.verify(req.body, signature);
} catch (err) {
return res.status(400).send('Webhook signature verification failed');
}
switch (event.type) {
case 'payin.confirmed':
console.log('Payment confirmed:', event.data);
break;
case 'withdrawal.confirmed':
console.log('Withdrawal confirmed:', event.data);
break;
}
res.status(200).json({ received: true });
});Webhook event types
| Event | Trigger |
|---|---|
| payin.created | Payin created |
| payin.confirming | Payment detected on-chain |
| payin.confirmed | Payment fully confirmed |
| payin.expired | Payin expired before payment |
| payin.overpaid | More than expected received |
| payin.underpaid | Less than expected received |
| payin.failed | Processing error |
| withdrawal.requested | Withdrawal created |
| withdrawal.approved | Approved by admin |
| withdrawal.rejected | Rejected by admin |
| withdrawal.broadcast | Sent to blockchain |
| withdrawal.confirmed | On-chain confirmed |
| withdrawal.failed | Broadcast failed |
Error Handling
All SDK errors extend ZyndPayError and include a statusCode and optional requestId.
import {
ZyndPayError,
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError,
} from '@zyndpay/sdk';
try {
const payin = await zyndpay.payins.create({ amount: '5' }); // below minimum
} catch (err) {
if (err instanceof ValidationError) {
console.error('Bad request:', err.message); // "amount must be >= 25"
} else if (err instanceof AuthenticationError) {
console.error('Invalid API key');
} else if (err instanceof NotFoundError) {
console.error('Resource not found');
} else if (err instanceof RateLimitError) {
console.error('Rate limited, retry after', err.retryAfter, 'seconds');
} else if (err instanceof ZyndPayError) {
console.error('API error', err.statusCode, err.message);
}
}TypeScript Support
The SDK is written in TypeScript and ships full type declarations. No @types package needed.
import type { Payin, Withdrawal, Transaction, Balance, WebhookEvent } from '@zyndpay/sdk';License
MIT — see LICENSE
