Skip to content

Webhooks -- Vue d'ensemble

Les webhooks permettent à votre application de recevoir des notifications en temps réel sur les événements de la plateforme Minha Konta. Quand un événement se produit, Minha Konta envoie un HTTP POST à l'URL enregistrée.

Comment ça fonctionne

  1. Enregistrez une URL de webhook dans votre compte
  2. Quand un événement se produit (ex. : PIX reçu), Minha Konta envoie un HTTP POST à votre URL
  3. Votre application traite la notification et répond avec un status 2xx (200, 201 ou 204)

Événements disponibles

Minha Konta livre des événements de PIX, TEF entre comptes Minha Konta et test opérationnel de webhook. D'autres produits (boleto, comptes et STA) ne sont pas dans le périmètre. Toute tentative d'abonnement à des événements hors du tableau ci-dessous est rejetée avec events: contains invalid events: ....

ÉvénementStatus bodyDescriptionDéclenchement
pix.charge.createdcreatedQR code généré ou cash-in initiéActif
pix.charge.paidpaidPIX reçu et liquidéActif
pix.charge.expiredexpiredQR code expire sans paiementActif
pix.charge.cancelledcancelledQR code annulé avant le paiementEnregistré, pas encore déclenché
pix.payout.queuedqueuedPIX envoye mis en file par limite operationnelle. Retry automatique avec TTL maximum 2hActif
pix.payout.processingprocessingPIX envoyé, en attente de confirmation BACENActif
pix.payout.heldprocessingPIX envoyé retenu pour analyse chez l'agent de règlement (autorisation/anti-fraude). Règle ou rejette ensuite — ne pas renvoyerActif
pix.payout.confirmedsettledPIX envoyé et confirmé (terminal)Actif
pix.payout.failedrejectedPIX envoyé rejeté par le SPI (terminal)Actif
pix.payout.returnedreturnedPIX envoyé rembourséActif
pix.refund.requestedrequestedDemande de remboursement reçue (infraction BACEN) ; blocage conservatoire créé sur le solde du clientActif
pix.refund.completedsettled / completedAnalyse de la défense finalisée et remboursement exécuté (ou libéré)Actif
pix.return.receivedsettledRemboursement PIX reçu (crédit)Actif
pix.infraction.createdACKNOWLEDGEDInfraction PIX signalee par la contrepartie via BACEN DICT ; peut exiger une analyse et une defense MEDActif
pix.infraction.resolvedCLOSED / CANCELLEDInfraction resolue par decision finale ou annulation de la contrepartieActif
pix.infraction.defense_submitteddefense_submittedDéfense soumise par le merchant (portail ou API) ; attend l'analyse BACENActif
tef.transfer.sentsettledTEF entre comptes Minha Konta liquidée pour le compte d'origineActif
tef.transfer.receivedsettledTEF entre comptes Minha Konta liquidée pour le compte de destinationActif
tef.transfer.failedfailedTEF entre comptes Minha Konta rejetée ou non liquidéeActif
webhook.testtestTest manuel. Disponible uniquement via Admin/Merchant portal - l'External API n'expose pas d'endpoint pour déclencher un testDéclenchement manuel (pas External API)

pix.charge.cancelled n'est pas encore déclenché

L'événement est dans l'enum et peut être souscrit, mais le système n'a pas de flux d'annulation de QR code aujourd'hui. Si vous vous abonnez, le POST /webhooks répond 201 normalement - mais aucune notification n'arrivera. Continuez à surveiller pix.charge.expired pour le cycle naturel de vie du QR.

Sécurité

Chaque notification inclut des headers de sécurité et d'identification pour la validation :

HeaderDescription
X-Minha Konta-SignatureSignature HMAC-SHA256 du payload (préfixe sha256=). Dans des cas rares (webhook enregistré sans secret), la valeur littérale est unsigned - voir note ci-dessous
X-Minha Konta-TimestampUnix timestamp en secondes de l'envoi
X-Minha Konta-Event-IdUUID unique de la delivery (pour déduplication)
X-Minha Konta-Event-TypeType de l'événement (ex. : pix.charge.paid)
Content-TypeToujours application/json
User-AgentToujours Minha Konta-Webhook/1.0 - utilisez pour le whitelisting dans firewalls/WAF. L'évolution future suivra le pattern Minha Konta-Webhook/{version} ; filtrez par préfixe Minha Konta-Webhook/ pour être immunisé aux nouvelles versions

Signature unsigned quand le webhook n'a pas de secret

Si le webhook a ete enregistre sans champ secret dans un enregistrement legacy, le header X-Minha Konta-Signature peut valoir unsigned. Cela desactive la validation HMAC de votre cote. Si vous recevez unsigned, enregistrez un nouveau webhook avec secret explicite et supprimez l'ancien.

SHA256 dans les webhooks vs SHA512 dans l'API

L'API utilise HMAC-SHA512 pour authentifier les requêtes que vous envoyez. Les webhooks envoyés par Minha Konta utilisent HMAC-SHA256 dans la signature X-Minha Konta-Signature. Ce sont des algorithmes différents -- chacun dans son contexte.

Validation de la signature

Validez la signature pour garantir que la notification a été envoyée par Minha Konta :

javascript
const crypto = require('crypto');

function validateWebhook(rawBody, timestamp, signature, secret) {
  // rawBody is the RAW request body string (before any JSON parse)
  // timestamp is unix seconds (e.g., 1712160000)
  const message = `${timestamp}.${rawBody}`;
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Utilisez le body RAW, pas re-sérialisé

Vous devez utiliser le corps exact de la requête HTTP tel que les octets sont arrivés dans votre application. Si vous faites JSON.parse puis JSON.stringify, les octets résultants ne seront pas identiques à ceux qu'Minha Konta a utilisé pour signer, et la validation échouera.

En Express/Node : utilisez express.raw({ type: 'application/json' }) ou gardez le body avant tout middleware de parse.

Dans d'autres frameworks : configurez pour capturer le raw body avant le middleware JSON.

Tri des clés dans les WEBHOOKS : PAS nécessaire

Pour la validation des webhooks (HMAC-SHA256) vous N'avez PAS besoin de trier les clés - utilisez le body raw tel que reçu dans le HTTP request d'Minha Konta.

⚠️ Attention - différence vs envoi de requêtes : Dans la signature HMAC-SHA512 des REQUÊTES que vous envoyez, le tri alphabétique des clés EST obligatoire (le serveur Minha Konta réordonne avant de valider). Ne confondez pas les deux scénarios :

  • Webhook reçu (HMAC-SHA256) : validez le body raw sans réordonner
  • Request envoyée (HMAC-SHA512) : triez vos clés alphabétiquement avant de signer

Validez toujours

Ne traitez jamais un webhook sans valider la signature. Cela protège contre les requêtes falsifiées.

De plus, validez que le X-Minha Konta-Timestamp est dans ± 5 minutes de l'heure actuelle (protection anti-replay - le serveur ne rejette pas les webhooks « anciens » par défaut ; cette vérification appartient à votre endpoint comme défense en profondeur) et dédupliquez les événements par X-Minha Konta-Event-Id (protection contre les retries).

Retry Policy

Si votre URL retourne un status différent de 2xx (ou timeout après 30 s), Minha Konta effectue jusqu'à 8 tentatives avec backoff exponentiel. Le total du temps entre la première et la huitième tentative est d'environ 7h45min :

TentativeDélai depuis la tentative précédenteTemps cumulé
1re- (immediat)~50-200 ms
2e30 secondes~30 s
3e2 minutes~2,5 min
4e10 minutes~12,5 min
5e30 minutes~42,5 min
6e1 heure~1,75 h
7e2 heures~3,75 h
8e4 heures~7,75 h

Après 8 tentatives sans succès, le webhook_delivery est marqué avec le status failed et n'est pas renvoyé automatiquement. Vous pouvez demander un replay manuel au support Minha Konta en fournissant le X-Minha Konta-Event-Id (ou avoir un opérateur avec accès admin qui replay via le portail).

Status d'une delivery

Chaque delivery passe par les status : pending (créée, en attente de livraison) → delivered (2xx reçu) OU failed (8 tentatives épuisées) OU expired (replay protection).

A propos d'expired : quand une tentative de livraison devient trop ancienne avant l'envoi, elle peut etre abandonnee et marquee comme expired. Cela empeche que des retraitements tardifs declenchent des notifications anciennes. Les replays manuels demandes au support Minha Konta suivent un flux controle et peuvent renvoyer l'evenement au client.

Durabilité

Avant de tenter la premiere livraison, l'evenement est persiste pour retry. En cas de defaillance pendant la livraison, le systeme reprend automatiquement au prochain retry - aucun evenement n'est perdu.

Idempotence

Votre application doit être idempotente : si elle reçoit le même événement plus d'une fois (identifié par X-Minha Konta-Event-Id), elle doit le traiter sans dupliquer les effets.

Replay manuel via admin

Si une delivery a échoué et que vous devez la renvoyer, l'équipe Minha Konta peut exécuter un replay manuel via le dashboard admin. Contactez le support avec le event_id de la delivery.

Livraisons dupliquées (race condition connue)

Le systeme peut utiliser plus d'un chemin de livraison pour accelerer la premiere notification et maintenir un retry durable. Dans les scenarios de forte concurrence, vous pouvez recevoir le meme payload 2 fois via HTTP, mais avec le meme X-Minha Konta-Event-Id - c'est le meme evenement, pas un retry.

Pour éviter l'impact dupliqué :

  • Dédupliquez par X-Minha Konta-Event-Id (recommandé - UUID unique par delivery, stable dans les retries et dans la race condition ci-dessus)
  • Ou alternativement dédupliquez par end_to_end_id + event_type quand cela a du sens pour l'événement

C'est un comportement attendu, pas une erreur. Les retries légitimes (après 5xx/timeout) réutilisent également le même X-Minha Konta-Event-Id.

External ID dans les webhooks

Quand une transaction a été créée avec external_id, ce champ est inclus dans le payload du webhook à l'intérieur de l'objet data. Utilisez-le pour corréler l'événement avec la commande dans votre système sans avoir besoin de faire une consultation supplémentaire.

Exigences de l'endpoint

  • L'URL doit utiliser HTTPS (sauf si allow_insecure: true dans l'enregistrement)
  • Doit repondre avec le status 2xx dans les 30 secondes
  • Le body de la réponse est ignoré
  • Recommandé de répondre rapidement (200 OK immédiat) et traiter l'événement de façon asynchrone de votre côté ; les délais longs réduisent le throughput et augmentent la chance de retries

Étapes suivantes

Minha Konta Instituição de Pagamento - ISPB 39929224