magot developers

Webhook d'autorisation émetteur

À chaque autorisation carte d'un enfant, le processeur de la banque demande à magot s'il faut approuver. magot répond en quelques millisecondes à partir des règles parentales en mémoire (gel, plafonds, catégories, solde).

Point d'accès

POST https://<hôte-autorisation>/webhooks/issuer/authorization
Content-Type: application/json

En production, l'hôte n'est joignable qu'en mTLS : le processeur présente un certificat client émis par l'autorité convenue avec magot. Sans TLS configuré, le service n'écoute qu'en local (127.0.0.1).

Authentification

Chaque banque reçoit un credential, lié à un seul établissement :

ÉlémentExempleRemise
Identifiant de clémgt_ik_…en clair
Secret HMACmgt_is_…une seule fois, par canal sûr
Empreinte du certificat clientSHA-256fournie par la banque

Trois en-têtes sur chaque requête :

En-têteValeur
Magot-Key-Idl'identifiant de clé
Magot-Timestampsecondes Unix de l'envoi
Magot-Signaturev1= + HMAC-SHA256 hex de <timestamp>.<corps brut>, clé = secret (octets UTF-8)

Règles côté magot :

Exemple de signature (Node.js) :

import { createHmac } from "node:crypto";

const body = JSON.stringify(authorization);           // envoyé tel quel
const ts = Math.floor(Date.now() / 1000);
const signature = "v1=" + createHmac("sha256", secret).update(`${ts}.${body}`).digest("hex");
// en-têtes : Magot-Key-Id, Magot-Timestamp: ts, Magot-Signature: signature

Corps

ChampType
idempotency_keychaîne ASCII, 1–128obligatoire ; identifiant unique de l'autorisation chez le processeur
card_refchaîne, 1–128référence de la carte chez l'émetteur (voie normale)
child_idUUIDalternative sandbox à card_ref
amount_centsentier, 1–10 000 000obligatoire ; montant en centimes, jamais une chaîne
mcc4 chiffrescode catégorie commerçant
merchantchaîne ≤ 200libellé commerçant
categorychaîne ≤ 64catégorie magot si le processeur la connaît
dayYYYY-MM-DDjour local de la transaction (défaut : aujourd'hui)
tenant_idUUIDfacultatif ; s'il est présent, il doit être celui du credential (sinon 403)

card_ref ou child_id est obligatoire. Corps invalide : 400.

Réponse

200 dans tous les cas où une décision est prise — un refus est un résultat, pas une erreur :

{ "approved": false, "reason": "daily_limit_exceeded",
  "values": { "dailyLimitCents": 2000, "spentTodayCents": 1800, "amountCents": 300 } }
reasonSens
card_frozencarte gelée par le parent ou l'enfant
daily_limit_exceededplafond du jour atteint
txn_limit_exceededplafond par transaction dépassé
category_blockedcatégorie bloquée par le parent
insufficient_fundssolde insuffisant
unknown_cardcarte inconnue de cet établissement
unknown_childenfant inconnu de cet établissement (sandbox)

Idempotence

Rejouer la même idempotency_key rend la même décision sans débiter une seconde fois. Le processeur peut donc réessayer sans risque après un timeout.

Indisponibilité de magot

Si magot ne répond pas dans le budget convenu, le processeur applique sa politique de repli (stand-in). Les limites et le gel sont répliqués sur la carte chez l'émetteur pour que ce repli reste conforme aux règles parentales : magot appelle l'émetteur à chaque gel et dégel. Geler ne dépend jamais de l'émetteur (la carte est gelée chez magot immédiatement, la resynchronisation suit) ; dégeler exige son accord.

Mise en service (exploitation magot)

  1. MAGOT_SECRETS_KEY (32 octets en base64) dans l'environnement du service : les secrets sont scellés en base (AES-256-GCM), un dump seul ne suffit pas à forger une autorisation.
  2. tsx scripts/mint-issuer-credential.ts <tenant> <libellé> <empreinte-sha256> → identifiant + secret, affichés une fois.
  3. mTLS : AUTHZ_TLS_KEY, AUTHZ_TLS_CERT (certificat serveur) et AUTHZ_TLS_CA (autorité des certificats clients) ; le service écoute alors sur toutes les interfaces (AUTHZ_HOST pour forcer).
  4. Redémarrer le service (ou kill -HUP sur le process node) pour charger le nouveau credential. Révocation : revoked_at puis rechargement.