ZyndPay API Reference
L'API ZyndPay est une passerelle de paiement RESTful pour accepter des USDT sur la blockchain TRON. Des URLs orientées ressources, des corps JSON et une enveloppe de réponse cohérente facilitent l'intégration dans n'importe quel environnement.
Tous les montants sont en USDT (TRC20). Le montant minimum est de 1 USDT. Frais marchand : 1% par transaction. Les clients paient des frais réseau de 1,00$ sur les paiements externes. Frais de retrait : 1% (min 1,50$). Frais de payout : 1% (min 1,50$, max 5$).
https://api.zyndpay.io/v1{
"success": true,
"data": { ... },
"meta": { "page": 1, "limit": 20, "total": 100 }
}Authentification
Incluez votre clé API dans l'en-tête X-Api-Key à chaque requête. Vous pouvez aussi la passer comme jeton Bearer dans l'en-tête Authorization.
curl https://api.zyndpay.io/v1/payments \
-H "X-Api-Key: zyp_live_sk_..."| Paramètre | Type | Requis | Description |
|---|---|---|---|
live_sk_* | string | requis | Clé secrète live — accès API complet. Ne jamais exposer côté client. |
live_pk_* | string | optionnel | Clé publiable live — accès lecture limité, sûre pour les navigateurs. |
test_sk_* | string | requis | Clé secrète sandbox — identique au live mais sans transactions réelles. |
test_pk_* | string | optionnel | Clé publiable sandbox. |
rk_* | string | optionnel | Clé restreinte — limitée à des opérations spécifiques. |
Démarrage Rapide
Acceptez votre premier paiement USDT en moins de 5 minutes. Sélectionnez votre langage ci-dessous — chaque exemple montre l'installation, la création d'un encaissement, la gestion du webhook et la vérification du statut.
// 1. Install
// npm install @zyndpay/sdk
// 2. Initialize
import { ZyndPay } from '@zyndpay/sdk';
const zyndpay = new ZyndPay({
apiKey: process.env.ZYNDPAY_API_KEY!,
webhookSecret: process.env.ZYNDPAY_WEBHOOK_SECRET,
});
// 3. Create a pay-in and get a payment URL
const payin = await zyndpay.payins.create({
amount: '100',
externalRef: 'order_' + Date.now(), // your order ID
successUrl: 'https://yoursite.com/success',
cancelUrl: 'https://yoursite.com/cancel',
});
console.log('Redirect customer to:', payin.paymentUrl);
// Or show payin.address if you want to display the TRON address directly
// 4. Handle the webhook (Express.js)
import express from 'express';
const app = express();
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 {
return res.status(400).send('Invalid signature');
}
switch (event.event) {
case 'payin.confirmed':
// Payment received — fulfill the order
console.log('Paid:', event.data.externalRef, event.data.amount, 'USDT');
break;
case 'payin.expired':
console.log('Expired:', event.data.externalRef);
break;
case 'payin.underpaid':
console.log('Underpaid:', event.data.externalRef,
'got', event.data.amount, 'expected', event.data.amountRequested);
break;
}
res.json({ received: true });
});
// 5. Poll / check status programmatically
const tx = await zyndpay.payins.get(payin.transactionId);
console.log('Status:', tx.status); // "CONFIRMED"Mise en Production
Avant d'accepter de vrais paiements, parcourez cette liste. La plupart des éléments prennent moins de 5 minutes chacun.
Créer un Encaissement
/v1/paymentsdocs.createPayinP
| Paramètre | Type | Requis | Description |
|---|---|---|---|
amount | string | requis | Montant en USDT sous forme de chaîne décimale (ex. « 100.00 »). Minimum : « 1.00 ». |
externalRef | string | optionnel | Votre ID de commande ou référence (optionnel). Doit être unique par marchand si fourni. |
expiresInSeconds | number | optionnel | Secondes avant l'expiration de l'adresse. Minimum : 900. Défaut : 1800 (30 minutes). |
successUrl | string | optionnel | URL de redirection du client après un paiement réussi. |
cancelUrl | string | optionnel | URL de redirection du client si le paiement expire ou est annulé. |
metadata | object | optionnel | Paires clé-valeur arbitraires stockées avec le paiement et incluses dans les webhooks. |
curl -X POST https://api.zyndpay.io/v1/payments \
-H "X-Api-Key: zyp_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"amount": "100.00",
"externalRef": "order_123",
"expiresInSeconds": 3600,
"successUrl": "https://yoursite.com/payment/success",
"cancelUrl": "https://yoursite.com/payment/cancel"
}'{
"success": true,
"data": {
"transactionId": "pay_abc123...",
"address": "TRXabc123def456ghi789jkl",
"paymentUrl": "https://checkout.zyndpay.io/pay_abc123...",
"qrCodeUrl": "data:image/png;base64,iVBOR...",
"amount": "100.00",
"amountExpected": "101.00",
"networkFee": "1",
"currency": "USDT_TRC20",
"chain": "TRON",
"status": "AWAITING_PAYMENT",
"expiresAt": "2026-03-06T12:00:00.000Z"
}
}Récupérer un Encaissement
/v1/payments/:id{
"success": true,
"data": {
"id": "f4b2cb0f-08ce-4408-88d4-0a678ca0aae2",
"address": "TRXabc123def456ghi789jkl",
"amount": "100",
"amountReceived": "100.00",
"zyndpayFee": "1.00",
"status": "CONFIRMED",
"txHash": "abc123def456...",
"externalRef": "order_123",
"currency": "USDT_TRC20",
"chain": "TRON",
"paymentUrl": "https://checkout.zyndpay.io/f4b2cb0f...",
"isSandbox": false,
"createdAt": "2026-03-06T11:00:00.000Z",
"updatedAt": "2026-03-06T11:01:02.000Z"
}
}PENDINGEn attente de paiementCONFIRMINGFonds reçus, en attente de 5 confirmationsCONFIRMED5+ confirmations — solde créditéUNDERPAIDMontant reçu inférieur à l'attenduOVERPAIDMontant reçu supérieur à l'attenduEXPIREDAdresse expirée sans paiementLister les Encaissements
/v1/payments| Paramètre | Type | Requis | Description |
|---|---|---|---|
page | number | optionnel | Numéro de page. Défaut : 1. |
limit | number | optionnel | Résultats par page. Défaut : 20. Max : 100. |
status | string | optionnel | Filtrer par statut : PENDING, CONFIRMING, CONFIRMED, EXPIRED, UNDERPAID ou OVERPAID. |
currency | string | optionnel | Filtrer par devise (ex. USDT_TRC20). |
{
"success": true,
"data": {
"items": [ ... ],
"meta": {
"page": 1,
"limit": 20,
"total": 134,
"totalPages": 7,
"hasNext": true,
"hasPrev": false
}
}
}Créer un Lien
/v1/paylinksdocs.createPaylinkP
| Paramètre | Type | Requis | Description |
|---|---|---|---|
type | string | requis | Type de lien : FIXED (défaut), VARIABLE ou RECURRING. |
products | array | requis | Tableau de produits. Au moins un produit est requis. |
products[].name | string | requis | Nom du produit affiché au client. |
products[].price | string | requis | Prix en USDT sous forme de chaîne décimale. |
products[].productType | string | requis | PHYSICAL (défaut) ou DIGITAL. |
products[].digitalUrl | string | optionnel | URL externe pour la livraison du produit numérique (Google Drive, Mega, etc.). |
collectEmail | string | optionnel | Collecte d'email client : HIDDEN (défaut), OPTIONAL ou REQUIRED. |
collectName | string | optionnel | Collecte du nom client : HIDDEN, OPTIONAL ou REQUIRED. |
brandColor | string | optionnel | Couleur hexadécimale pour la page de checkout personnalisée (ex. #635BFF). |
successUrl | string | optionnel | URL de redirection du client après un paiement réussi. |
recurringInterval | string | optionnel | Intervalle de facturation pour les liens récurrents : WEEKLY, MONTHLY ou YEARLY. |
curl -X POST https://api.zyndpay.io/v1/paylinks \
-H "X-Api-Key: zyp_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"type": "FIXED",
"products": [
{
"name": "Premium Course",
"price": "49.99",
"productType": "DIGITAL",
"digitalUrl": "https://drive.google.com/file/d/abc123"
}
],
"collectEmail": "REQUIRED",
"brandColor": "#635BFF"
}'{
"success": true,
"data": {
"id": "pl_cma1xyz8f0001yx5k",
"slug": "aB3dE6fG7hI9",
"type": "FIXED",
"status": "ACTIVE",
"paymentUrl": "https://dashboard.zyndpay.io/pay/link/aB3dE6fG7hI9",
"products": [
{
"id": "prod_abc123",
"name": "Premium Course",
"price": "49.990000000000000000",
"productType": "DIGITAL",
"digitalUrl": "https://drive.google.com/file/d/abc123"
}
],
"createdAt": "2026-03-08T10:00:00.000Z"
}
}Récupérer un Lien
/v1/paylinks/:id{
"success": true,
"data": {
"id": "pl_cma1xyz8f0001yx5k",
"slug": "aB3dE6fG7hI9",
"type": "FIXED",
"status": "ACTIVE",
"paymentUrl": "https://dashboard.zyndpay.io/pay/link/aB3dE6fG7hI9",
"products": [
{
"id": "prod_abc123",
"name": "Premium Course",
"price": "49.990000000000000000",
"productType": "DIGITAL",
"digitalUrl": "https://drive.google.com/file/d/abc123"
}
],
"createdAt": "2026-03-08T10:00:00.000Z"
}
}Lister les Liens
/v1/paylinks| Paramètre | Type | Requis | Description |
|---|---|---|---|
page | number | optionnel | Numéro de page. Défaut : 1. |
limit | number | optionnel | Résultats par page. Défaut : 20. Max : 100. |
{
"success": true,
"data": {
"items": [ ... ],
"meta": {
"page": 1,
"limit": 20,
"total": 134,
"totalPages": 7,
"hasNext": true,
"hasPrev": false
}
}
}Paiement
/v1/pay/link/:slug/checkoutEndpoint public (pas d'auth requise). Crée une commande et un encaissement à partir d'un lien de paiement. Le client reçoit une adresse TRON pour envoyer les USDT.
| Paramètre | Type | Requis | Description |
|---|---|---|---|
items | array | requis | Tableau d'IDs de produits et quantités à acheter. |
customerEmail | string | optionnel | Adresse email du client (requise pour RECURRING et produits numériques). |
customerName | string | optionnel | Nom du client (optionnel). |
curl -X POST https://api.zyndpay.io/v1/pay/link/aB3dE6fG7hI9/checkout \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "productId": "prod_abc123", "quantity": 1 }
],
"customerEmail": "[email protected]",
"customerName": "John Doe"
}'{
"success": true,
"data": {
"orderId": "ord_xyz789",
"transactionId": "cma2abc9g0002yz6l0def",
"address": "TRXabc123def456ghi789jkl",
"amount": "49.99",
"expiresAt": "2026-03-08T11:00:00.000Z"
}
}Créer un Paiement Sortant
/v1/payoutdocs.createPayoutP
| Paramètre | Type | Requis | Description |
|---|---|---|---|
amount | string | requis | Montant en USDT à envoyer (ex. « 50.00 »). Minimum : « 5.00 ». Des frais de 1% (min 1,50$, max 5$) sont déduits de votre solde en sus du montant. |
destinationAddress | string | requis | Adresse de portefeuille TRON (TRC20) du destinataire. Doit correspondre au format T suivi de 33 caractères base58. |
currency | string | optionnel | Devise à envoyer. Défaut : USDT_TRC20. |
chain | string | optionnel | Réseau blockchain. Défaut : TRON. |
externalRef | string | optionnel | Votre ID de référence interne pour ce paiement (ex. numéro de facture fournisseur). |
metadata | object | optionnel | Paires clé-valeur arbitraires stockées avec le paiement. |
curl -X POST https://api.zyndpay.io/v1/payout \
-H "X-Api-Key: zyp_live_sk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-d '{
"amount": "50.00",
"destinationAddress": "TXYZabc123def456ghi789jkl012mno345",
"externalRef": "payout_vendor_456"
}'{
"success": true,
"data": {
"transactionId": "cma2abc9g0002yz6l0def5678",
"status": "PROCESSING",
"processingFee": "1.50",
"requiresManualApproval": false,
"currentPayinFee": "1%",
"currentTier": "flat"
}
}Récupérer un Paiement Sortant
/v1/payout/:id{
"success": true,
"data": {
"transactionId": "cma2abc9g0002yz6l0def5678",
"status": "PROCESSING",
"processingFee": "1.50",
"requiresManualApproval": false,
"currentPayinFee": "1%",
"currentTier": "flat"
}
}PENDINGEn attente d'approbation manuelle (montant > 50 K $)PROCESSINGApprouvé, préparation de la diffusionBROADCASTSoumis au réseau TRONCONFIRMEDConfirmé on-chainFAILEDDiffusion échouée — solde rembourséCANCELLEDAnnulé avant diffusionLister les Paiements Sortants
/v1/payout{
"success": true,
"data": {
"items": [ ... ],
"meta": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
}
}Demander un Retrait
/v1/withdrawalsdocs.requestWithdrawalP
| Paramètre | Type | Requis | Description |
|---|---|---|---|
amount | string | requis | Montant en USDT à retirer (ex. « 500.00 »). Minimum : « 5.00 ». Des frais de 1% (min 1,50$) sont déduits de ce montant. |
whitelistAddressId | string | optionnel | ID de l'adresse de retrait enregistrée à utiliser. Utilise votre adresse principale si omis. |
curl -X POST https://api.zyndpay.io/v1/withdrawals \
-H "X-Api-Key: zyp_live_sk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-d '{
"amount": "500.00",
"whitelistAddressId": "addr_cma1xyz8f0001yx5k"
}'{
"success": true,
"data": {
"id": "wdr_cma1xyz8f0001yx5k",
"amount": "500.00",
"fee": "5.00",
"netAmount": "495.00",
"destinationAddress": "TRXabc123def456ghi789jkl",
"status": "PENDING",
"createdAt": "2026-03-06T11:00:00.000Z"
}
}Récupérer un Retrait
/v1/withdrawals/:id{
"success": true,
"data": {
"id": "wdr_cma1xyz8f0001yx5k",
"amount": "500.00",
"fee": "5.00",
"netAmount": "495.00",
"destinationAddress": "TRXabc123def456ghi789jkl",
"status": "PENDING",
"createdAt": "2026-03-06T11:00:00.000Z"
}
}PENDING_REVIEWEn attente de validation adminAPPROVEDApprouvé, en file d'attente pour traitementBROADCASTSoumis au réseau TRONCONFIRMEDConfirmé on-chainREJECTEDRejeté par la validation adminFAILEDDiffusion échouée — solde rembourséCANCELLEDAnnulé avant diffusionAnnuler un Retrait
/v1/withdrawals/:iddocs.cancelWithdrawalP
Vue d'ensemble
docs.webhooksOverviewP
{
"event": "payin.confirmed",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"status": "CONFIRMED",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"amount": "100.00",
"amountRequested": "100.00",
"txHash": "abc123def456...",
"confirmedAt": "2026-03-06T11:01:02.000Z"
},
"createdAt": "2026-03-06T11:01:03.000Z"
}Vérification de Signature
docs.webhookVerifyP1
t=1680000000,v1=5257a869e7ecebeda32af...docs.webhookSignatureNote
const crypto = require('crypto');
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-zyndpay-signature'];
const [tPart, v1Part] = sig.split(',');
const timestamp = tPart.split('=')[1];
const received = v1Part.split('=')[1];
// Reject events older than 5 minutes
const age = Math.abs(Date.now() / 1000 - parseInt(timestamp));
if (age > 300) return res.status(400).send('Webhook too old');
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(`${timestamp}.${req.body}`)
.digest('hex');
// Use timing-safe comparison to prevent timing attacks
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
return res.status(400).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Handle event...
res.json({ received: true });
});Événements
| Événement | Type | Requis | Description |
|---|---|---|---|
payin.created | event | requis | Déclenché quand un nouvel encaissement est créé et une adresse de dépôt est générée. |
payin.confirming | event | requis | Déclenché quand des fonds sont reçus et en attente de 5 confirmations de blocs. |
payin.confirmed | event | requis | Déclenché quand un encaissement atteint 5 confirmations on-chain. Le solde marchand est crédité. |
payin.expired | event | requis | Déclenché quand une adresse d'encaissement expire sans recevoir le montant attendu. |
payin.failed | event | requis | Déclenché quand un encaissement échoue en raison d'une erreur réseau ou de traitement. |
payin.underpaid | event | requis | Déclenché quand un encaissement reçoit moins que le montant demandé. |
payin.overpaid | event | requis | Déclenché quand un encaissement reçoit plus que le montant demandé. |
withdrawal.requested | event | requis | Déclenché quand un nouveau retrait est demandé et mis en file d'attente pour validation. |
withdrawal.approved | event | requis | Déclenché quand un retrait passe la validation et est approuvé pour diffusion on-chain. |
withdrawal.confirmed | event | requis | Déclenché quand un retrait est confirmé on-chain. |
withdrawal.failed | event | requis | Déclenché quand la diffusion d'un retrait échoue. Le montant est remboursé au solde. |
aml.flagged | event | requis | Déclenché quand une transaction est signalée par le moteur de filtrage AML pour examen manuel. |
Schémas de Charge Utile
Chaque webhook est un POST JSON avec la même enveloppe : event, data, createdAt. La forme de data dépend du type d'événement. Cliquez sur un événement ci-dessous pour voir sa charge utile exacte.
{
"event": "payin.confirmed",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"status": "CONFIRMED",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"amount": "100.00",
"amountRequested": "100.00",
"txHash": "abc123def456...",
"confirmedAt": "2026-03-06T11:01:02.000Z"
},
"createdAt": "2026-03-06T11:01:03.000Z"
}{
"event": "payout.confirmed",
"data": {
"transactionId": "tx_sample_payout123",
"status": "CONFIRMED",
"currency": "USDT_TRC20",
"chain": "TRON",
"amount": "50.00",
"fee": "1.50",
"destinationAddress": "TXyz1234567890AbCdEfGhIjKlMnOpQrSt",
"txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"externalRef": "vendor_invoice_456",
"confirmedAt": "2026-01-15T12:01:00.000Z"
},
"createdAt": "2026-01-15T12:01:05.000Z"
}{
"event": "withdrawal.confirmed",
"data": {
"transactionId": "wdr_sample_abc123",
"status": "CONFIRMED",
"currency": "USDT_TRC20",
"chain": "TRON",
"amount": "500.00",
"fee": "5.00",
"netAmount": "495.00",
"toAddress": "TXyz1234567890AbCdEfGhIjKlMnOpQrSt",
"txHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"confirmedAt": "2026-01-15T12:01:00.000Z"
},
"createdAt": "2026-01-15T12:01:05.000Z"
}Tester un Webhook
Envoyez un événement de test à l'un de vos endpoints webhook enregistrés. Utile pour vérifier que votre endpoint est accessible et que votre code de vérification de signature fonctionne correctement.
/v1/webhooks/test| Paramètre | Type | Requis | Description |
|---|---|---|---|
endpointId | string | requis | L'ID de l'endpoint webhook auquel envoyer l'événement de test. Obtenez-le via GET /webhooks/endpoints. |
eventType | string | requis | Le type d'événement à simuler (ex. payin.confirmed, payout.confirmed). Doit être un nom d'événement valide. |
curl -X POST https://api.zyndpay.io/v1/webhooks/test \
-H "X-Api-Key: zyp_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"endpointId": "your-endpoint-id",
"eventType": "payin.confirmed"
}'{
"success": true,
"data": {
"message": "Test event sent",
"deliveryId": "9270e4aa-8391-4e3f-a70b-23c431714b84"
}
}Schémas de Charge
Chaque livraison webhook partage la même enveloppe : une chaîne event, un objet data avec des champs spécifiques à l'événement, et un horodatage createdAt. Les exemples ci-dessous montrent les noms et types de champs exacts.
payin.createdDéclenché immédiatement lorsqu'un nouvel encaissement est créé et qu'une adresse TRON est assignée.
{
"event": "payin.created",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"address": "TRXabc123def456ghi789jkl",
"amount": "100.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"status": "AWAITING_PAYMENT",
"expiresAt": "2026-03-06T12:00:00.000Z",
"paymentUrl": "https://checkout.zyndpay.io/cma1xyz8f0001yx5k9abc1234"
},
"createdAt": "2026-03-06T11:00:00.000Z"
}payin.confirmedDéclenché lorsqu'un encaissement atteint 5 confirmations on-chain. Le solde marchand est crédité à ce moment.
{
"event": "payin.confirmed",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"address": "TRXabc123def456ghi789jkl",
"amount": "100.00",
"amountReceived": "100.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"txHash": "abc123def456...",
"status": "CONFIRMED",
"confirmedAt": "2026-03-06T11:01:02.000Z"
},
"createdAt": "2026-03-06T11:01:03.000Z"
}payin.expiredDéclenché lorsqu'une adresse d'encaissement expire sans avoir reçu le montant USDT attendu.
{
"event": "payin.expired",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"address": "TRXabc123def456ghi789jkl",
"amount": "100.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"status": "EXPIRED",
"expiredAt": "2026-03-06T12:00:00.000Z"
},
"createdAt": "2026-03-06T12:00:01.000Z"
}payin.failedDéclenché lorsqu'un encaissement échoue en raison d'une erreur réseau ou de traitement. Aucun fonds n'a été reçu.
{
"event": "payin.failed",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"address": "TRXabc123def456ghi789jkl",
"amount": "100.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"status": "FAILED",
"reason": "Network processing error"
},
"createdAt": "2026-03-06T11:05:00.000Z"
}payin.underpaidDéclenché lorsque le client envoie moins d'USDT que le montant demandé. Le champ shortfall indique le manque.
{
"event": "payin.underpaid",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"address": "TRXabc123def456ghi789jkl",
"amount": "100.00",
"amountReceived": "90.00",
"shortfall": "10.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"txHash": "abc123def456...",
"status": "UNDERPAID",
"confirmedAt": "2026-03-06T11:01:02.000Z"
},
"createdAt": "2026-03-06T11:01:03.000Z"
}payin.overpaidDéclenché lorsque le client envoie plus d'USDT que le montant demandé. Le champ surplus indique l'excédent.
{
"event": "payin.overpaid",
"data": {
"transactionId": "cma1xyz8f0001yx5k9abc1234",
"address": "TRXabc123def456ghi789jkl",
"amount": "100.00",
"amountReceived": "110.00",
"surplus": "10.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "order_123",
"txHash": "abc123def456...",
"status": "OVERPAID",
"confirmedAt": "2026-03-06T11:01:02.000Z"
},
"createdAt": "2026-03-06T11:01:03.000Z"
}payout.confirmedDéclenché lorsqu'un paiement sortant est confirmé on-chain. Le txHash est l'ID de transaction on-chain.
{
"event": "payout.confirmed",
"data": {
"transactionId": "cma2abc9g0002yz6l0def5678",
"destinationAddress": "TXYZabc123def456ghi789jkl012mno345",
"amount": "50.00",
"fee": "1.50",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "payout_vendor_456",
"txHash": "def456abc123...",
"status": "CONFIRMED",
"confirmedAt": "2026-03-06T11:05:00.000Z"
},
"createdAt": "2026-03-06T11:05:01.000Z"
}payout.failedDéclenché lorsque la diffusion d'un paiement sortant échoue. Le montant est automatiquement remboursé sur votre solde marchand.
{
"event": "payout.failed",
"data": {
"transactionId": "cma2abc9g0002yz6l0def5678",
"destinationAddress": "TXYZabc123def456ghi789jkl012mno345",
"amount": "50.00",
"currency": "USDT_TRC20",
"chain": "TRON",
"externalRef": "payout_vendor_456",
"status": "FAILED",
"reason": "Broadcast failed — balance refunded",
"failedAt": "2026-03-06T11:05:00.000Z"
},
"createdAt": "2026-03-06T11:05:01.000Z"
}withdrawal.approvedDéclenché lorsqu'une demande de retrait passe la révision administrateur et est mise en file pour la diffusion on-chain.
{
"event": "withdrawal.approved",
"data": {
"id": "wdr_cma1xyz8f0001yx5k",
"amount": "500.00",
"fee": "5.00",
"netAmount": "495.00",
"destinationAddress": "TRXabc123def456ghi789jkl",
"currency": "USDT_TRC20",
"chain": "TRON",
"status": "APPROVED",
"approvedAt": "2026-03-06T12:00:00.000Z"
},
"createdAt": "2026-03-06T12:00:01.000Z"
}withdrawal.confirmedDéclenché lorsqu'un retrait est confirmé on-chain. netAmount est ce que votre portefeuille a réellement reçu après frais.
{
"event": "withdrawal.confirmed",
"data": {
"id": "wdr_cma1xyz8f0001yx5k",
"amount": "500.00",
"fee": "5.00",
"netAmount": "495.00",
"destinationAddress": "TRXabc123def456ghi789jkl",
"currency": "USDT_TRC20",
"chain": "TRON",
"txHash": "ghi789abc123...",
"status": "CONFIRMED",
"confirmedAt": "2026-03-06T12:30:00.000Z"
},
"createdAt": "2026-03-06T12:30:01.000Z"
}withdrawal.failedDéclenché lorsque la diffusion d'un retrait échoue. Le montant est automatiquement remboursé sur votre solde.
{
"event": "withdrawal.failed",
"data": {
"id": "wdr_cma1xyz8f0001yx5k",
"amount": "500.00",
"destinationAddress": "TRXabc123def456ghi789jkl",
"currency": "USDT_TRC20",
"chain": "TRON",
"status": "FAILED",
"reason": "Broadcast failed — balance refunded",
"failedAt": "2026-03-06T12:30:00.000Z"
},
"createdAt": "2026-03-06T12:30:01.000Z"
}SDK Node.js
Le SDK TypeScript officiel avec typage complet et vérification de webhook intégrée.
npm install @zyndpay/sdkconst { ZyndPay } = require('@zyndpay/sdk');
const client = new ZyndPay({
apiKey: 'zyp_live_sk_...',
webhookSecret: process.env.ZYNDPAY_WEBHOOK_SECRET,
});
// Create a payment
const payment = await client.payins.create({
amount: '100.00',
externalRef: 'order_123',
});
console.log(payment.address);
// Verify a webhook (uses raw body, not parsed JSON)
const event = client.webhooks.verify(
rawBody,
req.headers['x-zyndpay-signature']
);Démarrage TypeScript
Acceptez votre premier paiement USDT en moins de 5 minutes. Cet exemple utilise Express — adaptez à votre framework.
import { ZyndPay } from '@zyndpay/sdk';
import express from 'express';
// 1. Initialize the SDK
const client = new ZyndPay({
apiKey: process.env.ZYNDPAY_API_KEY, // zyp_live_sk_...
webhookSecret: process.env.WEBHOOK_SECRET,
});
// 2. Create a pay-in (generates a TRON deposit address for your customer)
const payment = await client.payins.create({
amount: '100.00',
externalRef: 'order_123',
expiresInSeconds: 3600,
successUrl: 'https://yoursite.com/payment/success',
});
// Send payment.paymentUrl or payment.address to your customer
console.log('Deposit address:', payment.address);
console.log('Payment page:', payment.paymentUrl);
// 3. Handle webhook events
const app = express();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
// Always verify using the raw body — never parsed JSON
const event = client.webhooks.verify(
req.body,
req.headers['x-zyndpay-signature'] as string,
);
switch (event.event) {
case 'payin.confirmed':
console.log(`Payment confirmed: ${event.data.amount} USDT — ${event.data.externalRef}`);
// Fulfill the order, unlock access, send receipt, etc.
break;
case 'payin.expired':
console.log(`Payment expired: ${event.data.externalRef}`);
break;
}
res.json({ received: true });
});
// 4. Check payment status anytime
const status = await client.payins.get(payment.transactionId);
console.log('Status:', status.status); // AWAITING_PAYMENT → CONFIRMING → CONFIRMEDSDK Python
docs.pythonSdkP
pip install zyndpayfrom zyndpay import ZyndPay
client = ZyndPay(
api_key="zyp_live_sk_...",
webhook_secret=os.environ.get("ZYNDPAY_WEBHOOK_SECRET"),
)
payment = client.payins.create(
amount="100.00",
external_ref="order_123"
)
print(payment["address"])Démarrage Python
Acceptez votre premier paiement USDT en moins de 5 minutes. Cet exemple utilise Flask — adaptez à votre framework.
import os
from zyndpay import ZyndPay
from flask import Flask, request, jsonify
# 1. Initialize the SDK
client = ZyndPay(
api_key=os.environ["ZYNDPAY_API_KEY"], # zyp_live_sk_...
webhook_secret=os.environ["WEBHOOK_SECRET"],
)
# 2. Create a pay-in (generates a TRON deposit address for your customer)
payment = client.payins.create(
amount="100.00",
external_ref="order_123",
expires_in_seconds=3600,
success_url="https://yoursite.com/payment/success",
)
# Send payment["paymentUrl"] or payment["address"] to your customer
print("Deposit address:", payment["address"])
print("Payment page:", payment["paymentUrl"])
# 3. Handle webhook events
app = Flask(__name__)
@app.post("/webhook")
def handle_webhook():
# Always verify using the raw body — never parsed JSON
event = client.webhooks.verify(
request.get_data(),
request.headers.get("X-ZyndPay-Signature"),
)
if event["event"] == "payin.confirmed":
data = event["data"]
print(f"Payment confirmed: {data['amount']} USDT — {data['externalRef']}")
# Fulfill the order, unlock access, send receipt, etc.
elif event["event"] == "payin.expired":
print("Payment expired:", event["data"]["externalRef"])
return jsonify(received=True)
# 4. Check payment status anytime
status = client.payins.get(payment["transactionId"])
print("Status:", status["status"]) # AWAITING_PAYMENT → CONFIRMING → CONFIRMEDSDK PHP
Le SDK PHP officiel avec client HTTP basé sur cURL et vérification de webhook. Nécessite PHP 8.0+.
composer require zyndpay/zyndpay-php<?php
require_once 'vendor/autoload.php';
$client = new ZyndPay\ZyndPay('zyp_live_sk_...', [
'webhook_secret' => getenv('ZYNDPAY_WEBHOOK_SECRET'),
]);
// Create a payment
$payment = $client->payins->create([
'amount' => '100.00',
'externalRef' => 'order_123',
]);
echo $payment['address'];
// Verify a webhook
$event = $client->webhooks->verify(
$rawBody,
$_SERVER['HTTP_X_ZYNDPAY_SIGNATURE']
);Démarrage PHP
Acceptez votre premier paiement USDT en moins de 5 minutes. Cet exemple utilise du PHP simple — adaptez le gestionnaire webhook à votre framework.
<?php
require_once 'vendor/autoload.php';
// 1. Initialize the SDK
$client = new ZyndPay\ZyndPay(
getenv('ZYNDPAY_API_KEY'), // zyp_live_sk_...
['webhook_secret' => getenv('WEBHOOK_SECRET')]
);
// 2. Create a pay-in (generates a TRON deposit address for your customer)
$payment = $client->payins->create([
'amount' => '100.00',
'externalRef' => 'order_123',
'expiresInSeconds' => 3600,
'successUrl' => 'https://yoursite.com/payment/success',
]);
// Send $payment['paymentUrl'] or $payment['address'] to your customer
echo "Deposit address: " . $payment['address'] . "\n";
echo "Payment page: " . $payment['paymentUrl'] . "\n";
// 3. Handle webhook events (in your webhook endpoint file)
$rawBody = file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_X_ZYNDPAY_SIGNATURE'];
$event = $client->webhooks->verify($rawBody, $sigHeader);
switch ($event['event']) {
case 'payin.confirmed':
$data = $event['data'];
echo "Payment confirmed: {$data['amount']} USDT — {$data['externalRef']}\n";
// Fulfill the order, unlock access, send receipt, etc.
break;
case 'payin.expired':
echo "Payment expired: " . $event['data']['externalRef'] . "\n";
break;
}
http_response_code(200);
echo json_encode(['received' => true]);
// 4. Check payment status anytime
$status = $client->payins->get($payment['transactionId']);
echo "Status: " . $status['status'] . "\n"; // AWAITING_PAYMENT → CONFIRMING → CONFIRMEDImplémentation PHP brute sans le SDK. Produit la même vérification HMAC-SHA256 que les exemples Node.js et Python ci-dessus.
<?php
// IMPORTANT: read raw body before any JSON parsing
$payload = file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_X_ZYNDPAY_SIGNATURE'] ?? '';
function verifyWebhook(string $payload, string $sigHeader, string $secret): bool {
$parts = [];
foreach (explode(',', $sigHeader) as $part) {
[$k, $v] = explode('=', $part, 2);
$parts[$k] = $v;
}
if (empty($parts['t']) || empty($parts['v1'])) {
return false;
}
// Reject events older than 5 minutes
if (abs(time() - (int) $parts['t']) > 300) {
return false;
}
$expected = hash_hmac('sha256', $parts['t'] . '.' . $payload, $secret);
// Timing-safe comparison to prevent timing attacks
return hash_equals($expected, $parts['v1']);
}
if (!verifyWebhook($payload, $sigHeader, getenv('ZYNDPAY_WEBHOOK_SECRET'))) {
http_response_code(400);
echo 'Invalid signature';
exit;
}
$event = json_decode($payload, true);
// Handle $event['event'] ...Plugin WooCommerce
Acceptez des paiements USDT dans votre boutique WordPress / WooCommerce sans écrire une seule ligne de code. Le plugin génère des adresses de dépôt, surveille le statut de confirmation et exécute automatiquement les commandes.
Téléchargez le ZIP du plugin depuis le dépôt GitHub ZyndPay.
Dans l'administration WordPress, allez dans Extensions → Ajouter → Téléverser une extension.
Téléversez le ZIP et cliquez sur Activer.
Naviguez vers WooCommerce → Réglages → Paiements → ZyndPay.
Entrez votre clé API et votre secret webhook, puis sauvegardez.
Vue d'ensemble
docs.sandboxOverviewP
Guide de Test
Suivez ces étapes pour tester votre flux de paiement complet de bout en bout avant de passer en production.
# Using the sandbox API key (zyp_test_sk_...)
curl -X POST https://api.zyndpay.io/v1/payments \
-H "X-Api-Key: zyp_test_sk_..." \
-H "Content-Type: application/json" \
-d '{
"amount": "100",
"externalRef": "test_order_001",
"sandbox": true
}'import { ZyndPay } from '@zyndpay/sdk';
const zyndpay = new ZyndPay({ apiKey: 'zyp_test_sk_...' });
// 1. Create a sandbox payin
const payin = await zyndpay.payins.create({
amount: '100',
sandbox: true,
externalRef: 'test_order_001',
});
// 2. Instantly simulate confirmation (fires the payin.confirmed webhook)
const result = await zyndpay.payins.simulate(payin.transactionId);
console.log('Simulated status:', result.status); // "CONFIRMED"
// 3. Confirm the status
const tx = await zyndpay.payins.get(payin.transactionId);
console.log('Final status:', tx.status); // "CONFIRMED"# Reset all sandbox transactions (useful for clean test runs)
curl -X POST https://api.zyndpay.io/v1/sandbox/reset \
-H "X-Api-Key: zyp_test_sk_..."Simuler un Paiement
/v1/sandbox/payments/:id/simulatedocs.sandboxSimulateP
curl -X POST \
https://api.zyndpay.io/v1/sandbox/payments/{id}/simulate \
-H "X-Api-Key: zyp_test_sk_..."{
"success": true,
"data": {
"message": "Payin simulation triggered",
"transactionId": "f4b2cb0f-08ce-4408-88d4-0a678ca0aae2"
}
}Aperçu
docs.subsOverviewP
Configuration
Monétisez votre chaîne en 60 secondes :
Commandes du Bot
Commandes disponibles pour les propriétaires de chaînes :
| Commande | Type | Requis | Description |
|---|---|---|---|
/setup | command | requis | Configurer le prix d'abonnement, l'intervalle de facturation et les paramètres de la chaîne. |
/plan | command | requis | Voir votre plan actuel et vos revenus. |
/withdraw | command | requis | Retirer votre solde USDT vers une adresse portefeuille TRON. |
/help | command | requis | Afficher toutes les commandes disponibles et les informations d'utilisation. |
/revenue | command | requis | Voir les analyses de revenus — total gagné, abonnés actifs et tendances mensuelles. |
/subscribers | command | requis | Lister les abonnés actifs avec leur statut d'abonnement et dates de renouvellement. |
Codes d'Erreur
docs.errorCodesP
{
"success": false,
"error": {
"code": "AMOUNT_TOO_LOW",
"message": "Minimum payin amount is 1 USDT"
},
"statusCode": 400
}| Code | Statut HTTP | Requis | Description |
|---|---|---|---|
UNAUTHORIZED | 401 | requis | Clé API manquante ou invalide. Vérifiez que vous envoyez l'en-tête X-Api-Key et que la clé existe dans votre tableau de bord. |
FORBIDDEN | 403 | requis | La clé API n'a pas le scope requis pour cette opération. Utilisez une clé secrète (sk) et non une clé publiable (pk). |
NOT_FOUND | 404 | requis | La ressource demandée n'existe pas ou n'appartient pas à votre compte marchand. |
VALIDATION_ERROR | 400 | requis | Le corps de la requête a échoué à la validation. Le champ details liste chaque champ invalide et la raison. |
AMOUNT_TOO_SMALL | 400 | requis | Le montant est inférieur au minimum requis pour cette opération (1 USDT pour les encaissements, 5 USDT pour les paiements sortants et retraits). |
AMOUNT_TOO_LARGE | 400 | requis | Le montant dépasse le maximum autorisé pour cette opération ou votre niveau de conformité actuel. |
INVALID_ADDRESS | 400 | requis | L'adresse de portefeuille TRON est mal formée. Les adresses doivent commencer par T et faire 34 caractères au format base58. |
INVALID_TRANSACTION_STATUS | 400 | requis | L'opération n'est pas autorisée dans le statut actuel de la transaction (ex. tenter d'annuler un paiement sortant confirmé). |
DUPLICATE_EXTERNAL_REF | 409 | requis | Une transaction avec cet externalRef existe déjà pour votre compte. Utilisez une référence unique par requête, ou omettez-la. |
INSUFFICIENT_BALANCE | 400 | requis | Votre solde USDT est insuffisant pour le montant de paiement sortant ou retrait demandé. Vérifiez votre solde via GET /v1/wallets/balance. |
KYB_REQUIRED | 403 | requis | Cette opération nécessite une vérification KYB (Know Your Business) complète. Complétez le KYB dans votre tableau de bord pour débloquer les limites complètes. |
COMPLIANCE_LIMIT_REACHED | 403 | requis | Votre volume de transactions mensuel a atteint la limite de conformité de votre niveau actuel. Complétez le KYB pour augmenter vos limites. |
AML_BLOCKED | 403 | requis | Cette transaction a été signalée par notre moteur de filtrage AML et ne peut pas être traitée. Contactez [email protected]. |
ADDRESS_NOT_FOUND | 404 | requis | Le whitelistAddressId ne correspond à aucune adresse de retrait enregistrée sur votre compte. Ajoutez des adresses dans votre tableau de bord sous Adresses de Retrait. |
ADDRESS_NOT_WHITELISTED | 403 | requis | L'adresse de destination n'est pas sur votre liste blanche de marchand. Ajoutez-la dans votre tableau de bord avant d'y envoyer des fonds. |
CANNOT_CANCEL | 400 | requis | Cette ressource ne peut plus être annulée (elle a déjà été approuvée, diffusée ou complétée). |
MISSING_IDEMPOTENCY_KEY | 400 | requis | Cet endpoint nécessite un en-tête Idempotency-Key. Passez un UUID unique par requête. |
IDEMPOTENCY_CONFLICT | 409 | requis | Une requête existante avec la même Idempotency-Key a des paramètres différents. Utilisez une nouvelle clé pour une requête différente. |
DUPLICATE_RESOURCE | 409 | requis | Une ressource avec cette valeur unique existe déjà (ex. email, slug ou champ en doublon). |
LIVE_KEY_SANDBOX_REQUEST | 400 | requis | Vous avez envoyé sandbox: true avec une clé API live. Utilisez une clé zyp_test_sk_... pour les requêtes sandbox. |
SANDBOX_KEY_LIVE_REQUEST | 400 | requis | Vous avez envoyé une clé sandbox mais la ressource est une transaction live. Utilisez une clé zyp_live_sk_... pour les requêtes de production. |
RATE_LIMIT_EXCEEDED | 429 | requis | Trop de requêtes. Consultez l'en-tête de réponse Retry-After pour connaître le nombre de secondes à attendre avant de réessayer. |
FREEMIUM_LIMIT_EXCEEDED | 403 | requis | Limite de volume freemium mensuel (14 500$) atteinte. Complétez le KYB pour débloquer des limites plus élevées. |
INVALID_WEBHOOK_SIGNATURE | 400 | requis | La vérification de signature webhook a échoué. Vérifiez votre secret webhook et que vous utilisez le corps brut de la requête. |
INTERNAL_ERROR | 500 | requis | Erreur serveur inattendue. Incluez le requestId de la réponse lorsque vous contactez [email protected]. |
Limites de Taux
docs.rateLimitsP
| Point de terminaison | Limite de débit | Requis | Description |
|---|---|---|---|
Default | 100/60s | requis | Limite globale par clé API. |
POST /payments | 30/60s | requis | Création d'encaissement (POST /payments) par marchand. |
POST /payout | 10/60s | requis | Création de paiement sortant (POST /payout) par marchand. |
POST /withdrawals | 5/60s | requis | Demandes de retrait par marchand. |