magot developers

Événements sortants

Tout fait métier magot (paiement, recharge, gel de carte, demande, mission, règle modifiée, décision d'autorisation, écart de solde) est écrit dans un journal immuable. La banque s'y abonne : magot lui pousse chaque événement par webhook signé, pour son CRM, son anti-fraude ou son reporting.

Abonnement

Un abonnement = une URL HTTPS de la banque, un secret de signature, et optionnellement une liste de types. Créé par l'exploitation magot :

tsx scripts/add-event-subscription.ts <tenant> https://si.banque.example/magot [--types PaymentSettled,CardFrozen] [--from-start]

Par défaut, la livraison commence aux événements à venir ; --from-start livre tout l'historique de l'établissement.

Requête

POST https://si.banque.example/magot
Content-Type: application/cloudevents+json
Magot-Subscription-Id: <uuid>
Magot-Event-Id: <tenant>:<séquence>
Magot-Timestamp: <secondes Unix>
Magot-Signature: v1=<HMAC-SHA256 hex de "<timestamp>.<corps>", clé = secret>

Corps au format CloudEvents 1.0 :

{
  "specversion": "1.0",
  "id": "5f0c…:4812",
  "source": "https://api.magot.ch/tenants/5f0c…",
  "type": "ch.magot.PaymentSettled.v1",
  "subject": "child/9a41…",
  "time": "2026-09-27T14:02:11.482Z",
  "datacontenttype": "application/json",
  "magotsequence": 4812,
  "data": { "amountCents": 450, "merchant": "Kiosque", "category": "food", "balanceCents": 3200 }
}

La signature se vérifie exactement comme celle du webhook d'autorisation entrant (issuer-webhook.md) : même schéma, secret propre à l'abonnement. La banque rejette tout message hors d'une fenêtre de ±5 min.

Garanties

Catalogue (v1)

Montants en centimes, entiers. subject désigne l'enfant (child/<id>), la demande (money_request/<id>), la mission (mission/<id>) ou le pot (pot/<id>).

Typedata
TopUpReceivedamountCents, label, balanceCents — argent arrivé (recharge, demande, mission)
TopUpPendingtransferId, amountCents, label, purpose — virement demandé à la banque
TopUpRejectedtransferId, amountCents, label, purpose, reason
MilestoneReachedmilestoneCents, balanceCents
PaymentSettledamountCents, merchant, category, balanceCents
PaymentDeclinedamountCents, merchant, reason
RoundUpSweptamountCents, potId, potAmountCents, balanceCents
AuthorizationApproved / AuthorizationDeclinedidempotencyKey, amountCents, merchant, mcc, cardRef, reason
RequestCreatedchildId, amountCents, reason, emoji
RequestApprovedchildId, amountCents
RequestDeclinedchildId
MissionCreatedchildId, title, rewardCents
MissionCompletedchildId
MissionValidatedchildId, rewardCents
PotCreatedchildId, name, emoji, targetCents
PotDeposit / PotWithdrawchildId, amountCents, potAmountCents, balanceCents
PotGoalReachedchildId, targetCents
PotsReorderedchildId, potIds
ChildCreatedchildId, displayName, birthDate, mode
CardIssuedissuer (carte émise chez l'émetteur, ou registre interne)
CardFrozen / CardUnfrozenissuerSynced (si un émetteur est branché)
RulesChangedles règles modifiées (daily_limit_cents, txn_limit_cents, blocked_categories, round_ups_enabled)
BalanceMismatch / BalanceReconciledissuerBalanceCents, magotBalanceCents, differenceCents

Évolution : un champ peut être ajouté à un type v1 (la banque ignore les champs inconnus) ; tout retrait ou changement de sens crée un type v2, publié en parallèle pendant la transition.

Données personnelles : data contient des libellés saisis par la famille (motif d'une demande, nom d'un pot, titre de mission). La banque peut restreindre l'abonnement aux seuls types dont elle a besoin (--types).