API REST native

Ouvrir dans ChatGPTOuvrir dans Claude

L’API native est l’interface REST propre à blockwallets : des factures tarifées en cents américains, un ref idempotent par commande, des comptes de dépôt statiques couvrant tous les réseaux et des webhooks signés HMAC-SHA256. Elle crée les mêmes factures sur la même page de paiement hébergée que l’API compatible Cryptomus, avec les mêmes frais et le même solde.

Générez vos clés vous-même dans le tableau de bord, sous « Développeurs › Intégration et clés » : une clé Live et une clé Test avec leurs clés de signature de webhook. Chacune n’est affichée qu’une seule fois ; la liste n’en montre que le préfixe. Si la double authentification est activée sur votre compte, générer ou renouveler une clé Live demande un code. Pas encore de compte marchand ? Demandez l’accès. Vous êtes déjà sur Cryptomus ? Voyez l’API compatible Cryptomus (comment choisir).

Clés et requêtes

URL de base https://blockwallets.io. Les requêtes et les réponses sont en JSON. Chaque requête porte :

Les erreurs renvoient un statut HTTP et {"error": {"code": "…", "message": "…"}} : 400 invalid_request (un champ manquant ou mal formé), 401 unauthorized (clé manquante, inconnue ou désactivée), 404 not_found, 409 conflict (la requête entre en conflit avec l’état actuel de la facture), 422 currency_unsupported.

Endpoints

EndpointCe qu’il fait
GET /v1/networksRéseaux que vous pouvez accepter en ce moment dans le mode de cette clé : minimum, confirmations, délai d’arrivée typique et estimation des frais ; les cryptos cotées incluent le taux actuel
POST /v1/invoicesCrée une facture (201), ou renvoie l’existante pour le même ref (200)
GET /v1/invoices?ref=…Consulte une facture par votre ref
GET /v1/invoices/:idConsulte une facture par id
POST /v1/invoices/:id/networkChoisissez vous-même le réseau d’une facture (page de paiement en marque blanche) : renvoie l’address et le pay_amount à afficher
POST /v1/invoices/:id/closeFerme une facture en attente qui n’a reçu aucun transfert
POST /v1/deposit-accountsOuvre (201) ou récupère (200) le compte de dépôt d’un client : une adresse permanente sur chaque réseau
GET /v1/deposit-accounts?customer_ref=…Consulte un compte de dépôt par customer_ref
GET /v1/deposit-accounts/:idConsulte un compte de dépôt par id
GET /v1/depositsListe les dépôts d’un compte (account_id ou customer_ref, limit 1–200, 50 par défaut)
GET /v1/deposits/:idConsulte un dépôt
GET /v1/eventsEnvois de webhook pour une facture ou un dépôt (invoice_id ou deposit_id)
POST /v1/events/:id/redeliverRenvoie un webhook (202)

Ajoutez ?probe=1 à la consultation d’une facture ou d’un compte de dépôt pour vérifier la chaîne au passage (au plus une fois toutes les 10 secondes) ; sinon vous obtenez le dernier état de notre scanner, qui vérifie chaque minute.

Créer une facture POST /v1/invoices

Appelez POST /v1/invoices quand le client passe sa commande et redirigez-le vers la pay_url de la réponse.

curl
curl -X POST https://blockwallets.io/v1/invoices \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"ref":"order_1042","amount":4200,"title":"Order #1042",
       "return_url":"https://shop.example/cart","success_url":"https://shop.example/thanks?order=1042",
       "meta":{"user_id":42}}'
ChampObligatoireDescription
refOuiVotre numéro de commande : 1–64 caractères parmi lettres, chiffres et _ . : -. Unique par mode ; renvoyer le même ref avec les mêmes champs renvoie la même facture, avec des champs différents il renvoie 409
amountOuiMontant en cents américains, entier : 4200 = $42.00. Pas en dessous du minimum du réseau une fois celui-ci choisi
titleOuiCe que le client voit sur la page de paiement, 64 caractères au maximum
return_urlOuiOù mène « Retour » sur la page de paiement ; doit se trouver sur l’un des domaines de votre site
success_urlNonOù va le client après avoir payé ; par défaut return_url
networkNonPrésélectionne un id de réseau du tableau des réseaux ; omettez-le pour laisser le client choisir sur la page de paiement
customer_refNonL’identifiant de votre client, 64 caractères au maximum, renvoyé tel quel
lifetimeNonDurée de vie en secondes, 600 – 43200, 3600 par défaut
amount_ruleNon"any" = crédite tout ce qui arrive (recharges) : paid dès la confirmation. Omettez-le pour appliquer la « Règle de montant » de « Réglages › Règles d’encaissement et tarifs » du tableau de bord
accuracy_percentNonLe montant manquant encore accepté comme payé, 0 – 5 (pour cent), 0 par défaut
subtract_percentNonPart des frais de la plateforme payée par le client, 0 – 100 (pour cent), ajoutée à pay_amount ; omettez-la pour utiliser la valeur par défaut du tableau de bord
payment_multipleNonIndique si un paiement insuffisant peut être complété à la même adresse, valeur par défaut du tableau de bord (activé sauf si vous l’avez changé) ; false : le premier transfert insuffisant se termine en wrong_amount
metaNonN’importe quel objet JSON jusqu’à 2 Ko, renvoyé tel quel dans les consultations et les webhooks
currencyNonSeulement USD (la valeur par défaut) ; toute autre valeur renvoie 422

Chaque URL doit se trouver sur l’un des domaines de votre site (tableau de bord → « Développeurs › Intégration et clés »). La réponse est l’objet facture ci-dessous ; network, address et pay_amount sont renseignés une fois un réseau choisi.

L’objet facture

Les ids commencent par inv_. amount est en cents américains ; pay_amount et paid_amount sont des montants en crypto, sous forme de chaînes décimales, sur le réseau choisi.

json
{
  "id": "inv_01J8…",
  "ref": "order_1042",
  "mode": "live",
  "status": "pending",
  "amount": 4200,
  "currency": "USD",
  "title": "Order #1042",
  "meta": { "user_id": 42 },
  "network": null,
  "address": null,
  "pay_amount": null,
  "paid_amount": null,
  "payments": [],
  "pay_url": "https://blockwallets.io/pay/inv_01J8…",
  "return_url": "https://shop.example/cart",
  "success_url": "https://shop.example/thanks?order=1042",
  "created_at": "2026-11-03T08:00:00.000Z",
  "expires_at": "2026-11-03T09:00:00.000Z",
  "paid_at": null,
  "closed_at": null
}
statusSignificationCe que vous faites
pendingEn attente de paiement—
confirmingUn transfert a été vu et se confirme, ou il est arrivé incomplet et peut encore être complété—
paidPayéeExpédiez / créditez la commande
paid_overPayée, avec un trop-perçuPareil ; le surplus est sur votre solde
wrong_amountTerminée avec moins que le montant total (à l’expiration, ou au premier transfert insuffisant quand payment_multiple est false)Les activités de recharge peuvent créditer ce qui est arrivé (paid_amount ; les cryptos à taux ont aussi paid_cents) ; les boutiques demandent au client de payer le reste
closedExpirée sans rien recevoir, ou fermée par vous— (l’argent qui arrive plus tard est quand même crédité et notifié)

Autres champs : pay_url (la page de paiement hébergée), payments (chaque transfert avec txid, amount, confirmations et confirmed), expires_at, paid_at, closed_at ; BTC, LTC, DOGE, BCH et les cryptos natives portent aussi rate (dollars par crypto, verrouillé 30 minutes), rate_locked_until et paid_cents (ce qui est arrivé jusqu’ici, en cents américains).

Réseaux

Passez l’id comme network. GET /v1/networks renvoie ceux ouverts en ce moment dans votre mode ; un réseau peut être suspendu, mieux vaut donc le lire que le coder en dur.

networkCryptoChaîneMinimum
USDT_TRC20USDTTRON$1
USDT_BEP20USDTBNB Chain$1
USDC_BEP20USDCBNB Chain$1
USDT_ERC20USDTEthereum$5
USDC_ERC20USDCEthereum$5
USDC_BASEUSDCBase$1
USDT_POLYGONUSDTPolygon$1
USDC_POLYGONUSDCPolygon$1
USDT_ARBITRUMUSDTArbitrum$1
USDC_ARBITRUMUSDCArbitrum$1
USDT_OPTIMISMUSDTOptimism$1
USDC_OPTIMISMUSDCOptimism$1
USDT_AVALANCHEUSDTAvalanche$1
USDC_AVALANCHEUSDCAvalanche$1
USDT_XLAYERUSDTX Layer$1
USDC_XLAYERUSDCX Layer$1
USD1_BEP20USD1BNB Chain$1
FDUSD_BEP20FDUSDBNB Chain$1
DAI_ERC20DAIEthereum$5
DAI_ARBITRUMDAIArbitrum$1
DAI_BASEDAIBase$1
BTCBTCBitcoin$5
LTCLTCLitecoin$1
DOGEDOGEDogecoin$1
BCHBCHBitcoin Cash$1
TRXTRXTRON$1
BNBBNBBNB Chain$1
ETHETHEthereum$5
ETH_BASEETHBase$1
ETH_ARBITRUMETHArbitrum$1
ETH_OPTIMISMETHOptimism$1
POLPOLPolygon$1
AVAXAVAXAvalanche$1
OKBOKBX Layer$1
USDT_SOLUSDTSolana$1
USDC_SOLUSDCSolana$1
SOLSOLSolana$1
USDT_TONUSDTTON$1
TONTONTON$1

Comptes de dépôt (adresses statiques) POST /v1/deposit-accounts

POST /v1/deposit-accounts avec {"customer_ref": "user_42"} donne à ce client une adresse permanente sur chaque réseau (toutes les chaînes EVM partagent une adresse). Tout ce qu’il envoie est crédité en dollars américains, avec un webhook deposit.credited par transfert.

curl
curl -X POST https://blockwallets.io/v1/deposit-accounts \
  -H "Authorization: Bearer $BW_KEY" -H "Content-Type: application/json" \
  -d '{"customer_ref":"user_42"}'
json
{
  "id": "dac_01J8…",
  "mode": "live",
  "customer_ref": "user_42",
  "deposit_url": "https://blockwallets.io/deposit/dac_01J8…",
  "min_amount": 100,
  "currency": "USD",
  "networks": [
    { "id": "USDT_TRC20", "chain": "tron", "token": "USDT", "address": "TXy4…8kQ2", "min_amount": 100, "confirmations": 1, … },
    { "id": "USDC_BASE", "chain": "base", "token": "USDC", "address": "0x5aE1…", "min_amount": 100, "confirmations": 20, … }
  ]
}

Les transferts inférieurs au minimum (généralement $1, BTC $5) sont enregistrés comme below_min et ne sont pas crédités automatiquement ; contactez-nous pour les faire créditer.

Webhooks

Nous envoyons un POST JSON à l’URL de webhook du tableau de bord (« Développeurs › Intégration et clés » ; Live et Test ont chacun leur URL et leur secret). Le corps est l’événement :

http
POST /your/webhook
X-BW-Event: ev_01J8…
X-BW-Delivery: 1
X-BW-Signature: t=1793693052,v1=5f0c9b…

{"id":"ev_01J8…","type":"invoice.paid","created_at":"2026-11-03T08:04:12.000Z","invoice":{"id":"inv_01J8…","ref":"order_1042","status":"paid","amount":4200,…}}
ÉvénementQuand
invoice.paidLa facture est passée à paid ou paid_over (y compris l’argent arrivé après l’expiration)
invoice.wrong_amountLa facture s’est terminée en wrong_amount
invoice.closedLa facture a expiré sans rien recevoir, ou vous l’avez fermée
deposit.creditedUn transfert vers un compte de dépôt a été crédité

Vérifiez sur le corps brut avant de l’analyser, rejetez un t éloigné de plus de 300 secondes de votre horloge et comparez en temps constant. invoice / deposit dans le corps est le même objet que renvoie une consultation.

Node.js
import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), header: X-BW-Signature
function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return typeof parts.v1 === "string" && parts.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}

Une réponse 2xx compte comme livrée ; sinon nous réessayons après 1 minute, 5 minutes, 30 minutes, 2 heures, 12 heures, 24 heures et 24 heures (8 tentatives au total).

Événements et renvoi

GET /v1/events?invoice_id=inv_… (ou deposit_id=dep_…) liste les webhooks d’une facture ou d’un dépôt avec leur state, attempts, last_status et last_error. POST /v1/events/ev_…/redeliver le remet aussitôt en file, par exemple après correction de votre endpoint. La page « Développeurs › Journal des webhooks » du tableau de bord montre chaque tentative avec la requête et la réponse.

Mode test

Les factures créées avec une clé bw_test_ tournent sur les testnets et ne touchent jamais d’argent réel. La page de paiement hébergée affiche un bouton « Simuler un paiement » (complet / moitié / trop-perçu), pour suivre les statuts et les webhooks sans coins de testnet.