Documentation / Intégration

Factures

Une facture correspond à un achat : un prix en monnaie fiat ou en stablecoin, une durée de validité et, une fois le choix fait par le client, la devise de paiement et l’adresse de dépôt.

Création

POST/v1/invoices

En-têtes : Authorization (CP-HMAC), Idempotency-Key, Content-Type: application/json.

corps de la requête
{
  "order_id": "ORDER-1001",
  "price_amount": "49.99",
  "price_currency": "USD",
  "allowed_assets": ["USDT-TRON", "USDC-BASE", "BTC"],
  "return_url": "https://shop.example/orders/ORDER-1001",
  "expires_in_seconds": 1800,
  "metadata": { "user_id": "42", "plan": "pro" }
}
ChampObligatoireRègles
order_idoui1 à 128 caractères, unique par marchand (doublon : 409 duplicate_order)
price_amountouiChaîne décimale > 0, jusqu’à 18 chiffres après le point
price_currencyouiUSD, EUR, USDT ou USDC
allowed_assetsnonJusqu’à 30 identifiants d’actifs (GET /v1/assets). Vide : tous les actifs disponibles. La facture reçoit l’intersection avec les actifs disponibles ; si elle est vide : 422 invalid_allowed_assets
return_urlnonhttps://… : bouton « Retour à la boutique »
expires_in_secondsnon300 à 86 400, 1800 par défaut (30 minutes)
metadatanonJusqu’à 20 clés [A-Za-z0-9_.-]{1,64}, valeurs de 500 caractères maximum ; renvoyées dans la facture

Réponse 201 :

JSON
{
  "id": "inv_x7k2…",
  "order_id": "ORDER-1001",
  "status": "created",
  "price_amount": "49.99",
  "price_currency": "USD",
  "allowed_assets": ["USDT-TRON", "BTC"],
  "checkout_url": "https://pay.coinetic.money/pay/inv_x7k2…#t=…",
  "return_url": "https://shop.example/orders/ORDER-1001",
  "expires_at": "2026-10-12T15:30:00Z",
  "created_at": "2026-10-12T15:00:00Z",
  "quote": null,
  "paid_amount": "0", "outstanding_amount": "0", "overpaid_amount": "0",
  "refunded_amount": "0", "refundable_amount": "0",
  "payments": [],
  "metadata": { "user_id": "42", "plan": "pro" },
  "livemode": true
}
  • price_amount est renvoyé sous forme canonique, sans zéros finaux : pour "3.00", vous recevrez "3". Comparez les montants comme des décimaux, jamais comme des float ni octet par octet.
  • checkout_url contient le jeton de la page de paiement après le #. Ne le journalisez pas et ne le publiez pas.
  • livemode: false : facture sandbox. Votre boutique en production doit les rejeter.

Quels actifs figurent dans la facture

Un actif est disponible s’il est activé dans Coinetic, que vous disposez d’un portefeuille de réception actif sur ce réseau et que vous ne l’avez pas exclu dans le tableau de bord (« Paramètres » → « Actifs acceptés »). Chaque actif a un minimum (min_amount dans GET /v1/assets) : si le montant de la facture dans cet actif est inférieur, l’actif n’est pas proposé. Exemple : une facture de 3 USD avec un BTC à 60 000 USD représente 5 000 sats pour un minimum de 10 000 ; cette facture ne proposera que des stablecoins.

Le champ selectable_assets liste les actifs de allowed_assets sélectionnables à cet instant ; la page de paiement ne propose qu’eux.

Idempotence

  • Idempotency-Key : 8 à 128 caractères ASCII imprimables, sans espaces, ne commençant pas par d:. Le plus simple : le dériver du numéro de commande, order-ORDER-1001.
  • Même clé et même corps : même réponse (même facture).
  • Même clé avec un autre corps : 409 idempotency_conflict.
  • La première requête est encore en cours : 409 idempotency_in_progress, réessayez une seconde plus tard.
  • Un refus pour règle métier (par exemple 422) est lui aussi mémorisé.

Consultation

GET/v1/invoices/{id}

Dès que le client a choisi sa devise, la facture contient un quote :

quote
{
  "asset_id": "USDT-TRON", "network": "tron", "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "address": "TX…", "amount_due": "49990000", "decimals": 6, "display_amount": "49.99",
  "payment_uri": "tron:…", "rate": "1", "rate_valid_until": null,
  "network_warning": "Envoyez uniquement de l’USDT sur le réseau TRON (TRC-20)…"
}

payments : les paiements, avec tx_hash, amount (en unités minimales), confirmations, required_confirmations, state (mempool, included, confirmed, reorged, replaced, failed, dropped).

unmatched_payments : les transferts vers l’adresse de la facture qui ne sont pas comptabilisés, envoyés sur un autre réseau EVM (wrong_network) ou avec un token hors liste blanche (token_not_whitelisted). Ils ne modifient ni le statut ni paid_amount.

Liste

GET/v1/invoices?status=paid&from=…&to=…&limit=50&cursor=…

Réponse : { "items": [...], "next_cursor": "…" | null }, de la plus récente à la plus ancienne, limit de 1 à 200.

Statuts

StatutSignificationAction côté boutique
createdFacture créée, devise non choisieattendre
awaiting_paymentDevise choisie, adresse attribuéeattendre
detectedPaiement visible sur le réseau (mempool)afficher « paiement détecté », ne pas livrer
confirmingInclus dans un bloc, confirmations insuffisantesafficher la progression, ne pas livrer
paidPayée intégralement et confirméelivrer la commande
overpaidMontant payé supérieur au dûlivrer la commande ; excédent remboursé sur demande
underpaidMontant confirmé inférieur au dû (tolérance déduite)demander le complément sur la même adresse
expiredDélai écoulé sans paiementproposer une nouvelle facture (voir ci-dessous)
late_paymentPaiement reçu après l’expirationà vous de décider : livrer ou rembourser
manual_reviewPaiement en cours de contrôle AMLattendre la décision ; ne pas livrer
refunded, cancelledClôturéene pas livrer
Règle d’orNe livrez la commande que sur un statut paid ou overpaid obtenu via GET /v1/invoices/{id}.

Paiement en stablecoin après expiration

Pour une facture en USD, l’USDT ou l’USDC ne présentent aucun risque de change : un paiement tardif (jusqu’à 30 jours) est donc comptabilisé automatiquement. La facture qui avait déjà reçu invoice.expired passe à paid et vous recevez invoice.paid avec data.late: true. C’est pourquoi il ne faut pas clôturer définitivement une commande sur invoice.expired. Pour les actifs volatils, un tel paiement donne late_payment.

Montants et taux

  • Le prix est exprimé dans la devise de la facture. Coinetic fixe le montant en cryptomonnaie au moment où le client choisit sa devise.
  • Stablecoin dans sa propre devise (USDT pour une facture en USD) : 1:1, montant fixé jusqu’à la fin de la facture.
  • Actif volatil (BTC, ETH, etc.) : médiane des cours Kraken, Coinbase et Bitstamp, fixée pour 20 minutes.
  • amount_due est exprimé en unités minimales de l’actif (USDT sur TRON : 6 décimales, "49990000" = 49,99). display_amount donne la même valeur en notation usuelle.
  • La tolérance de sous-paiement (0,5 % par défaut) absorbe les arrondis des portefeuilles.

Taux de référence : GET /v1/rates?base=BTC&quote=USD. Ne vous en servez pas pour afficher au client un montant crypto « exact » : seule la facture fournit le montant qui fait foi.