Ce que fait réellement l'API de paiement de masse en crypto
Un seul appel POST /v1/payout réserve les fonds pour l'ensemble du lot, valide chaque destinataire et le met en file d'attente pour signature. L'opérateur signe ensuite et diffuse à partir de clés hors ligne. C'est la véritable nature d'une API de paiement de masse en crypto construite sur une passerelle non-custodiale : l'API automatise la soumission, la validation, le statut et les webhooks — elle n'automatise pas la signature, car les clés privées ne résident jamais sur le serveur. Il n'y a pas de portefeuille chaud à vider, et pas d'envoi automatique silencieux. Si ce compromis semble acceptable, l'API transforme une paie manuelle ou un paiement d'affilié en deux ou trois lignes de code.
Ceci est un guide pour les développeurs. Il copie le contrat exact des docs de l'API afin que vous puissiez l'utiliser dès aujourd'hui : les points de terminaison, la signature HMAC, le Idempotency-Key, la validation stricte 422, le webhook payout.sent, et comment l'annulation libère le solde retenu. Si vous souhaitez d'abord un aperçu du produit, lisez la page des paiements de masse.
Pourquoi c'est semi-automatisé, et pourquoi c'est un gain de sécurité
Rien n'est diffusé par l'application web elle-même. Les adresses de réception dérivent de matériel de clé publique ; les clés privées qui autorisent une dépense restent sur votre matériel, hors ligne. Ainsi, le flux est délibérément en deux étapes. Lorsque vous soumettez un lot — depuis le cabinet ou via l'API — Payora réserve le total plus les frais de mouvement par article sur votre solde interne instantanément, de sorte que le lot ne puisse jamais être dépensé en trop. Ensuite, un humain (vous ou votre rotation d'opérations) signe les éléments en file d'attente hors ligne et les diffuse.
Une violation de serveur ne peut pas déplacer un seul coin, car la boîte qui reçoit l'appel API n'a rien avec quoi signer. Le coût est une étape de signature par lot. Pour les paies, les paiements d'affiliés et les règlements de fournisseurs, c'est un prix équitable, et c'est la même architecture décrite dans le paiement de centaines de portefeuilles sans portefeuille chaud. Ne modélisez jamais cela comme "appel API, pièces instantanément disparues" — ce serait un produit différent et plus risqué.
Authentification et signature de requête
L'API de paiement de masse en crypto utilise la même authentification que le reste de Payora. Chaque requête porte trois en-têtes : X-Payora-Key, X-Payora-Timestamp (secondes Unix, ±120s de décalage), et X-Payora-Signature. La signature est un HMAC-SHA256 sur le timestamp, un point littéral, et le corps brut exact de la requête :
X-Payora-Signature = hex(HMAC-SHA256(api_secret, timestamp + "." + raw_body))Signez les octets que vous envoyez réellement, avant toute re-sérialisation. Si votre client HTTP réencode le JSON, capturez d'abord le corps brut et hachez-le. C'est le même schéma utilisé pour vérifier les webhooks entrants, couvert dans la vérification de signature de webhook HMAC-SHA256.
POST /v1/payout : soumettre un lot
Envoyez une devise, jusqu'à 500 éléments, et une note optionnelle. Chaque élément est une adresse, un montant sous forme de chaîne, et un tag optionnel — le tag de destination XRP ou le mémo XLM lorsque l'actif en nécessite un.
curl -X POST https://api.payora.money/v1/payout \
-H "X-Payora-Key: pk_live_9f3c8a12" \
-H "X-Payora-Timestamp: 1753280400" \
-H "X-Payora-Signature: 7b1e0c4d9a55f2..." \
-H "Idempotency-Key: payroll-2026-07" \
-H "Content-Type: application/json" \
-d '{
"currency": "USDT",
"items": [
{"address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "amount": "250.00"},
{"address": "TXk9mP2v7wQ3nR5tYb1cD8eF4gH6jK0lMn", "amount": "1800.00", "tag": ""}
],
"note": "Contractants de juillet"
}'En cas de succès, vous obtenez 201 avec un lot que vous pouvez suivre. Le total est la somme des montants, les frais sont les frais de mouvement de votre plan (1,5 % sur Free) plus les frais de réseau de la pièce’, et les deux sont déjà retenus sur votre solde :
{
"batch_id": "po_7Qd2K8xM4b",
"status": "en attente",
"currency": "USDT",
"item_count": 2,
"total": "2050.00",
"fee": "20.50",
"items": [
{"index": 0, "address": "TR7NHqjeKQ...", "amount": "250.00", "status": "en attente"},
{"index": 1, "address": "TXk9mP2v7w...", "amount": "1800.00", "status": "en attente"}
]
}Accepter les paiements est toujours à 0 % ; les frais de mouvement ne s'appliquent que lorsque l'argent sort. Les frais de réseau sont séparés et payés sur la chaîne au moment de la diffusion.
Validation stricte : aucun destinataire silencieusement rejeté
La validation est tout ou rien par intention. Si une adresse est malformée pour le réseau choisi, ou si un montant comporte plus de décimales que la pièce ne le supporte, le lot entier est rejeté avec 422 et les index fautifs. Rien n'est mis en file d'attente, rien n'est retenu.
HTTP/1.1 422 Entité non traitable
{
"error": "validation_failed",
"invalid_items": [3, 17],
"message": "adresse invalide à l'index 3 ; le montant dépasse la précision de la pièce à l'index 17"
}C'est le comportement que vous souhaitez pour les paies. Une passerelle qui tronquait silencieusement 1800.123456789 ou sautait une mauvaise ligne sous-payerait ou laisserait tomber une personne, et vous ne le remarqueriez pas avant que quelqu'un ne se plaigne. Corrigez les index signalés et soumettez à nouveau l'ensemble du lot.
Idempotence : les réessais ne doublent jamais le paiement
Les réseaux expirent. Une demande de paiement qui échoue en cours de route est dangereuse à réessayer aveuglément, alors envoyez un en-tête Idempotency-Key — toute chaîne stable et unique pour ce lot logique (une période de paie, un groupe de factures). Si une demande avec la même clé arrive à nouveau, Payora renvoie le lot original au lieu d'en créer un second. Réutilisez la clé pour chaque réessai du même lot ; utilisez une nouvelle clé pour un lot réellement nouveau.
- Même clé, même lot — sûr de réessayer après un délai ; vous obtenez le premier résultat.
- Nouvelle clé — un nouveau lot, une nouvelle retenue sur votre solde.
- Stockez le
batch_idretourné dès que vous l'avez, afin que vous puissiez le rapprocher même si la réponse a été perdue.
Rapprochez-vous avec GET /v1/payout/{id}
Après que l'opérateur a signé, interrogez GET /v1/payout/{id} pour le statut actuel et un tx_hash par élément au fur et à mesure que chaque transaction est diffusée. GET /v1/payout liste les lots récents pour les tableaux de bord et les audits. Stockez le batch_id et chaque index d'élément par rapport à vos propres dossiers afin que chaque destinataire corresponde à un hachage sur la chaîne que vous pouvez leur montrer.
Besoin de retirer un avant qu'il ne soit signé ? POST /v1/payout/{id}/cancel annule un lot encore en attente et libère le solde retenu en totalité. Une fois les éléments diffusés, ils sont sur la chaîne et définitifs, comme toute transaction crypto — l'annulation ne fonctionne que tant que le lot est en attente.
Le webhook payout.sent
Plutôt que de sonder indéfiniment, abonnez-vous à payout.sent. Lorsque l'opérateur a diffusé chaque élément d'un lot, Payora déclenche un webhook signé en utilisant la même signature HMAC que invoice.paid. Vérifiez-le de la même manière — recomputez la signature sur le timestamp, le point, le corps brut et comparez en temps constant :
$expected = hash_hmac('sha256', $timestamp . '.' . $raw_body, $webhook_secret);
if (!hash_equals($expected, $signature_header)) { http_response_code(400); exit; }
// payload.event == "payout.sent", payload.batch_id, payload.items[].tx_hashCe n'est qu'après que cette vérification réussit que vous devez marquer la course de paie comme complète, envoyer des reçus par e-mail ou mettre à jour les livres. Un webhook non vérifié n'est qu'une requête HTTP non fiable.
Une liste de contrôle d'intégration minimale
- Créez un compte et générez des clés API à register ; financez le solde interne dans la devise que vous allez payer.
- Construisez le corps JSON brut, signez-le (timestamp + "." + body) avec HMAC-SHA256, attachez les trois en-têtes plus un
Idempotency-Key. POST /v1/payout; sur201conservez lebatch_id, sur422corrigez les index signalés et renvoyez.- Faites signer et diffuser le lot en file d'attente hors ligne par votre opérateur.
- Vérifiez le webhook
payout.sent, ou interrogezGET /v1/payout/{id}, et enregistrez chaquetx_hash.
C'est toute la boucle. L'API élimine la partie fastidieuse et sujette aux erreurs — construire, valider et suivre un lot de 500 lignes — tandis que la signature hors ligne garde ce qui compte vraiment, vos clés, hors de portée du serveur.
Commencez à construire
Lisez la section API de paiement de masse des docs, obtenez des clés à register, et voyez la fonctionnalité de bout en bout sur la page des paiements de masse. Vous pouvez automatiser le lot aujourd'hui et continuer à signer là où cela appartient — hors ligne.



Comments