{
  "openapi": "3.1.0",
  "info": {
    "title": "magot · API",
    "description": "L'API magot, telle qu'une banque l'intègre. Montants en **centimes**, entiers.\n\n## Trois familles d'appels\n\n| | Qui appelle | Où |\n|---|---|---|\n| **API app** | apps mobiles, SDK, app de la banque | cet hôte, `Authorization: Bearer` |\n| **banque → magot** | processeur carte, core banking | service d'autorisation (mTLS + HMAC) |\n| **magot → banque** | magot, vers le SI de la banque | webhooks CloudEvents signés |\n\n## Démarrage\n\n1. `POST /v1/identity/token` — échanger un jeton de la banque (JWT) contre une session magot (RFC 8693).\n2. `GET /v1/tenant` — marque, devise, langues, consentements attendus.\n3. `POST /v1/children` puis `POST /v1/children/{id}/card` — ouvrir un enfant, émettre sa carte.\n4. `POST /v1/children/{id}/topups` — première recharge (virement bancaire si le port de financement est branché).\n5. `GET /v1/state` une fois, puis `GET /v1/events?cursor=…` — synchronisation.\n\n## Règles communes\n\n- **Écritures idempotentes** : header `Idempotency-Key` obligatoire ; rejouer la même requête rend la même réponse ; réutiliser la clé pour une autre requête : `422`.\n- **Isolation** : un parent n'agit que sur son foyer, un appareil enfant que sur son enfant ; une ressource d'un autre foyer répond `404`.\n- **Consentements** : si l'établissement en exige un, `403` avec `code: consent_required` et ce qu'il manque.\n- Un refus de paiement ou d'autorisation est un **résultat** (`200`), pas une erreur HTTP.",
    "version": "1.0.0",
    "license": {
      "name": "Propriétaire — MCDev Sàrl",
      "url": "https://magot.ch"
    }
  },
  "components": {
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Session (échange de jeton bancaire, passkey) ou appareil enfant : `mgt_p_…`, `mgt_c_…`"
      },
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Clé de démonstration (sandbox uniquement)"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Erreur. Deux formes : erreur métier `{ error, code?, details? }` (`code: consent_required` quand un consentement manque), ou erreur de requête détectée avant le métier `{ statusCode, code, error, message }` (validation `FST_ERR_VALIDATION`, JSON illisible).",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Message métier, ou libellé HTTP pour une erreur de requête"
          },
          "message": {
            "type": "string",
            "description": "Détail d'une erreur de requête (champ fautif…)"
          },
          "statusCode": {
            "type": "integer"
          },
          "code": {
            "type": "string",
            "description": "`consent_required`, ou code d'erreur de requête (`FST_ERR_VALIDATION`…)"
          },
          "details": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string"
              },
              "version": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "description": "Erreur OAuth 2.0 (RFC 6749 §5.2)",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_grant",
              "unsupported_grant_type",
              "unsupported_token_type"
            ]
          },
          "error_description": {
            "type": "string"
          }
        }
      },
      "Child": {
        "type": "object",
        "required": [
          "id",
          "display_name",
          "mode",
          "wallet",
          "card"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_name": {
            "type": "string"
          },
          "birth_date": {
            "type": "string",
            "description": "Date de naissance (ISO 8601)"
          },
          "mode": {
            "type": "string",
            "enum": [
              "kids",
              "teens"
            ]
          },
          "wallet": {
            "type": "object",
            "properties": {
              "balance_cents": {
                "type": "integer",
                "description": "Solde disponible (hors pots)"
              },
              "round_ups_enabled": {
                "type": "boolean"
              }
            }
          },
          "card": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "none",
                  "active",
                  "frozen",
                  "replaced",
                  "closed"
                ]
              }
            }
          },
          "dream": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "image_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "target_cents": {
                    "type": "integer"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "pots": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "emoji": {
                  "type": "string"
                },
                "target_cents": {
                  "type": "integer"
                },
                "amount_cents": {
                  "type": "integer"
                },
                "is_round_up": {
                  "type": "boolean"
                },
                "sort_index": {
                  "type": "integer"
                }
              }
            }
          },
          "rules": {
            "type": "object",
            "description": "Dernière valeur de chaque règle, par type (daily_limit, txn_limit, category_block, …)",
            "additionalProperties": {
              "type": "object"
            }
          },
          "missions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "title": {
                  "type": "string"
                },
                "reward_cents": {
                  "type": "integer"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "open",
                    "pending",
                    "done"
                  ]
                }
              }
            }
          },
          "money_requests": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "amount_cents": {
                  "type": "integer"
                },
                "reason": {
                  "type": "string"
                },
                "emoji": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "approved",
                    "declined"
                  ]
                }
              }
            }
          },
          "transactions": {
            "type": "array",
            "description": "20 dernières",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "amount_cents": {
                  "type": "integer",
                  "description": "Négatif = dépense"
                },
                "label": {
                  "type": "string"
                },
                "category": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "occurred_at": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Event": {
        "type": "object",
        "description": "Entrée du journal. Types et charges utiles : voir les webhooks `ch.magot.*`.",
        "required": [
          "id",
          "type",
          "aggregateType",
          "aggregateId",
          "payload",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Position dans le journal (strictement croissante)"
          },
          "tenantId": {
            "type": "string",
            "format": "uuid"
          },
          "aggregateType": {
            "type": "string",
            "enum": [
              "child",
              "money_request",
              "mission",
              "pot"
            ]
          },
          "aggregateId": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "TopUpReceived",
              "TopUpPending",
              "TopUpRejected",
              "MilestoneReached",
              "PaymentSettled",
              "PaymentDeclined",
              "RoundUpSwept",
              "AuthorizationApproved",
              "AuthorizationDeclined",
              "RequestCreated",
              "RequestApproved",
              "RequestDeclined",
              "MissionCreated",
              "MissionCompleted",
              "MissionValidated",
              "PotCreated",
              "PotDeposit",
              "PotWithdraw",
              "PotGoalReached",
              "PotsReordered",
              "ChildCreated",
              "CardIssued",
              "CardFrozen",
              "CardUnfrozen",
              "RulesChanged",
              "BalanceMismatch",
              "BalanceReconciled"
            ]
          },
          "payload": {
            "type": "object"
          },
          "createdAt": {
            "type": "string"
          }
        }
      },
      "WriteResult": {
        "type": "object",
        "description": "Résultat d'une écriture ; rejouer la même Idempotency-Key rend exactement le même objet.",
        "properties": {
          "child_id": {
            "type": "string",
            "format": "uuid"
          },
          "balance_cents": {
            "type": "integer"
          },
          "funding_status": {
            "type": "string",
            "enum": [
              "settled",
              "pending"
            ],
            "description": "Si la banque a branché son port de financement"
          },
          "transfer_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "additionalProperties": true
      }
    }
  },
  "paths": {
    "/v1/tenant": {
      "get": {
        "operationId": "getTenant",
        "summary": "Configuration publique de l'établissement (marque, devise, langues, consentements)",
        "tags": [
          "lecture"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "OK",
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/state": {
      "get": {
        "operationId": "getState",
        "summary": "Bootstrap : état complet du foyer + curseur d'événements",
        "tags": [
          "lecture"
        ],
        "description": "Tout ce que l'app charge au premier lancement. Ensuite, elle ne suit plus que /v1/events avec le curseur retourné.",
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "household_id",
                    "children",
                    "cursor"
                  ],
                  "properties": {
                    "household_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "children": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Child"
                      }
                    },
                    "cursor": {
                      "type": "integer",
                      "description": "Position du journal à passer ensuite à /v1/events"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/events": {
      "get": {
        "operationId": "getEvents",
        "summary": "Sync delta : événements depuis un curseur",
        "tags": [
          "lecture"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "in": "query",
            "name": "cursor",
            "required": false
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "events",
                    "cursor"
                  ],
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      },
                      "description": "Au plus 500, du foyer (ou de l'enfant) de l'appelant"
                    },
                    "cursor": {
                      "type": "integer",
                      "description": "Nouveau curseur ; avance même si aucun événement ne concerne l'appelant"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/topups": {
      "post": {
        "operationId": "postChildrenTopups",
        "summary": "Recharger le solde de l'enfant",
        "tags": [
          "argent"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  },
                  "label": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "child_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "balance_cents": {
                      "type": "integer"
                    },
                    "milestones": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/payments": {
      "post": {
        "operationId": "postChildrenPayments",
        "summary": "Paiement simulé (même moteur de règles que le webhook émetteur)",
        "tags": [
          "argent"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents",
                  "merchant"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  },
                  "merchant": {
                    "type": "string",
                    "minLength": 1
                  },
                  "category": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "child_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "approved": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string",
                      "description": "Motif de refus (card_frozen, daily_limit_exceeded, …)"
                    },
                    "balance_cents": {
                      "type": "integer"
                    },
                    "round_up_cents": {
                      "type": "integer",
                      "description": "Petite monnaie balayée vers le pot Petite monnaie"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/requests": {
      "post": {
        "operationId": "postChildrenRequests",
        "summary": "L'enfant demande de l'argent",
        "tags": [
          "demandes"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents",
                  "reason"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 1
                  },
                  "emoji": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/requests/{requestId}/approve": {
      "post": {
        "operationId": "postRequestsApprove",
        "summary": "Le parent approuve : crédit immédiat",
        "tags": [
          "demandes"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "requestId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/requests/{requestId}/decline": {
      "post": {
        "operationId": "postRequestsDecline",
        "summary": "Le parent refuse",
        "tags": [
          "demandes"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "requestId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/missions": {
      "post": {
        "operationId": "postChildrenMissions",
        "summary": "Le parent crée une mission rémunérée",
        "tags": [
          "missions"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "reward_cents"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1
                  },
                  "reward_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/missions/{missionId}/complete": {
      "post": {
        "operationId": "postMissionsComplete",
        "summary": "L'enfant marque « C'est fait ! »",
        "tags": [
          "missions"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "missionId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/missions/{missionId}/validate": {
      "post": {
        "operationId": "postMissionsValidate",
        "summary": "Le parent valide : crédit automatique",
        "tags": [
          "missions"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "missionId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/pots": {
      "post": {
        "operationId": "postChildrenPots",
        "summary": "Créer un sous-magot",
        "tags": [
          "sous-magots"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "target_cents"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1
                  },
                  "emoji": {
                    "type": "string"
                  },
                  "target_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pots/{potId}/deposit": {
      "post": {
        "operationId": "postPotsDeposit",
        "summary": "Mettre de côté (solde → sous-magot)",
        "tags": [
          "sous-magots"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "potId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pots/{potId}/withdraw": {
      "post": {
        "operationId": "postPotsWithdraw",
        "summary": "Reprendre (sous-magot → solde)",
        "tags": [
          "sous-magots"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Montant en centimes"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "potId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/pots/order": {
      "put": {
        "operationId": "putChildrenPotsOrder",
        "summary": "Ordonner les sous-magots (glisser-déposer)",
        "tags": [
          "sous-magots"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pot_ids"
                ],
                "properties": {
                  "pot_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "maxItems": 100,
                    "uniqueItems": true
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/card/freeze": {
      "post": {
        "operationId": "postChildrenCardFreeze",
        "summary": "Geler la carte (parent, ou l'enfant pour lui-même)",
        "tags": [
          "carte"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/card/unfreeze": {
      "post": {
        "operationId": "postChildrenCardUnfreeze",
        "summary": "Dégeler la carte",
        "tags": [
          "carte"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children": {
      "post": {
        "operationId": "postChildren",
        "summary": "Ouvrir un enfant dans le foyer (portefeuille à zéro, sans carte)",
        "tags": [
          "enfants"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "display_name",
                  "birth_date"
                ],
                "properties": {
                  "display_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "birth_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "kids",
                      "teens"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/card": {
      "post": {
        "operationId": "postChildrenCard",
        "summary": "Émettre la carte de l'enfant",
        "tags": [
          "carte"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices": {
      "get": {
        "operationId": "getDevices",
        "summary": "Appareils du foyer (parents et enfants), sessions actives",
        "tags": [
          "identité"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "OK",
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{deviceId}/revoke": {
      "post": {
        "operationId": "postDevicesRevoke",
        "summary": "Révoquer un appareil du foyer",
        "tags": [
          "identité"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "deviceId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/consents": {
      "get": {
        "operationId": "getConsents",
        "summary": "Consentements du foyer (en vigueur et retirés)",
        "tags": [
          "identité"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "OK",
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/consents": {
      "post": {
        "operationId": "postChildrenConsents",
        "summary": "Donner un consentement parental pour un enfant",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kind",
                  "version"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "pattern": "^[a-z][a-z_]{2,39}$"
                  },
                  "version": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/consents/{consentId}/withdraw": {
      "post": {
        "operationId": "postConsentsWithdraw",
        "summary": "Retirer un consentement",
        "tags": [
          "identité"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "consentId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/rules": {
      "put": {
        "operationId": "putChildrenRules",
        "summary": "Modifier les règles de l'enfant",
        "tags": [
          "règles"
        ],
        "description": "Écriture idempotente : header `Idempotency-Key` requis. Rejouer la même clé rend la réponse d'origine sans réexécuter.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "minProperties": 1,
                "properties": {
                  "daily_limit_cents": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "txn_limit_cents": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "blocked_categories": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "round_ups_enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "childId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/register-options": {
      "post": {
        "operationId": "postIdentityRegisterOptions",
        "summary": "Options WebAuthn d'enrôlement parent",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "display_name"
                ],
                "properties": {
                  "display_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/register-verify": {
      "post": {
        "operationId": "postIdentityRegisterVerify",
        "summary": "Vérifie l'attestation, enrôle l'appareil parent",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge_id",
                  "response"
                ],
                "properties": {
                  "challenge_id": {
                    "type": "string"
                  },
                  "device_name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "response": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/login-options": {
      "post": {
        "operationId": "postIdentityLoginOptions",
        "summary": "Options WebAuthn de connexion (credential discoverable)",
        "tags": [
          "identité"
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/login-verify": {
      "post": {
        "operationId": "postIdentityLoginVerify",
        "summary": "Vérifie l'assertion, enrôle ce nouvel appareil parent",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge_id",
                  "response"
                ],
                "properties": {
                  "challenge_id": {
                    "type": "string"
                  },
                  "device_name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "response": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/children/{childId}/pairing-token": {
      "post": {
        "operationId": "postChildrenPairingToken",
        "summary": "Jeton d'appairage QR (parent, usage unique, TTL 10 min)",
        "tags": [
          "identité"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "childId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pairing/claim": {
      "post": {
        "operationId": "postPairingClaim",
        "summary": "Échange le jeton QR contre un token d'appareil enfant",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 200
                  },
                  "device_name": {
                    "type": "string",
                    "maxLength": 80
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pairing/device-code": {
      "post": {
        "operationId": "postPairingDeviceCode",
        "summary": "Montre : demande un code d'appairage à 6 chiffres (public, body { device_name? } optionnel)",
        "tags": [
          "identité"
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pairing/device-code/approve": {
      "post": {
        "operationId": "postPairingDeviceCodeApprove",
        "summary": "Parent : approuve le code affiché par la montre pour un enfant",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_code",
                  "child_id"
                ],
                "properties": {
                  "user_code": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20
                  },
                  "child_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pairing/device-code/token": {
      "post": {
        "operationId": "postPairingDeviceCodeToken",
        "summary": "Montre : sonde l'approbation, reçoit UNE fois le token d'appareil enfant (public)",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "device_code"
                ],
                "properties": {
                  "device_code": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/token": {
      "post": {
        "operationId": "postIdentityToken",
        "summary": "Échanger un jeton de la banque contre une session magot (RFC 8693)",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type",
                  "subject_token",
                  "subject_token_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string"
                  },
                  "subject_token": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16384
                  },
                  "subject_token_type": {
                    "type": "string"
                  },
                  "requested_token_type": {
                    "type": "string"
                  },
                  "device_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "device_name": {
                    "type": "string",
                    "maxLength": 60
                  }
                }
              }
            }
          }
        },
        "security": [],
        "responses": {
          "200": {
            "description": "Session magot ouverte",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Session magot ouverte",
                  "type": "object",
                  "required": [
                    "access_token",
                    "issued_token_type",
                    "token_type",
                    "expires_in"
                  ],
                  "properties": {
                    "access_token": {
                      "type": "string",
                      "description": "mgt_p_…"
                    },
                    "issued_token_type": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Secondes ; jamais au-delà du jeton bancaire"
                    },
                    "adult_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "household_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "device_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "À renvoyer au prochain échange (rotation de session)"
                    },
                    "provisioned": {
                      "type": "boolean",
                      "description": "Foyer créé à cette connexion"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Jeton refusé (RFC 6749 §5.2)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/federated-links": {
      "post": {
        "operationId": "postIdentityFederatedLinks",
        "summary": "Lier l'identité bancaire du parent connecté (passkey) à son compte magot",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject_token",
                  "subject_token_type"
                ],
                "properties": {
                  "subject_token": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16384
                  },
                  "subject_token_type": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/logout": {
      "post": {
        "operationId": "postIdentityLogout",
        "summary": "Révoquer le jeton de session présenté",
        "tags": [
          "identité"
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/push-token": {
      "post": {
        "operationId": "postDevicesPushToken",
        "summary": "Enregistre le token APNs de l'appareil (Bearer requis)",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 200
                  },
                  "bundle_id": {
                    "type": "string",
                    "enum": [
                      "fr.mc-dev.magot",
                      "fr.mc-dev.magot-watch"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/live-activity-start-token": {
      "post": {
        "operationId": "postDevicesLiveActivityStartToken",
        "summary": "Enregistre le jeton push-to-start Live Activity et la langue de l'appareil (Bearer requis)",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 400
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "fr",
                      "de",
                      "it",
                      "en"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/requests/{requestId}/live-activity-token": {
      "post": {
        "operationId": "postRequestsLiveActivityToken",
        "summary": "Enregistre le jeton de mise à jour de la Live Activity d'une demande (parent, Bearer requis)",
        "tags": [
          "identité"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 400
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "requestId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Résultat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Requête invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Identité absente ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Virement refusé par la banque",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Hors de la portée de l'appelant, ou consentement manquant (`code: consent_required`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Ressource inconnue dans le foyer de l'appelant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflit d'état (déjà fait, solde insuffisant…)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key déjà utilisée pour une autre requête",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Banque (émetteur, core banking) injoignable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/issuer/authorization": {
      "post": {
        "tags": [
          "banque → magot"
        ],
        "operationId": "authorizeCardTransaction",
        "summary": "Autorisation carte en temps réel",
        "description": "Appelé par le processeur à chaque autorisation d'une carte enfant. Réponse en quelques millisecondes ; un refus est un résultat (200), pas une erreur. Rejouer la même `idempotency_key` rend la même décision. Voir issuer-webhook.md.",
        "servers": [
          {
            "url": "https://{authzHost}",
            "description": "Service d'autorisation (mTLS)",
            "variables": {
              "authzHost": {
                "default": "authz.magot.example"
              }
            }
          }
        ],
        "security": [],
        "parameters": [
          {
            "name": "Magot-Key-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identifiant du credential de la banque"
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Secondes Unix ; ±300 s"
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps brut>`, clé = secret du credential"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "idempotency_key",
                  "amount_cents"
                ],
                "properties": {
                  "idempotency_key": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "card_ref": {
                    "type": "string",
                    "description": "Référence de la carte chez l'émetteur"
                  },
                  "child_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Alternative sandbox à card_ref"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000000
                  },
                  "mcc": {
                    "type": "string",
                    "pattern": "^[0-9]{4}$"
                  },
                  "merchant": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "category": {
                    "type": "string",
                    "maxLength": 64
                  },
                  "day": {
                    "type": "string",
                    "format": "date"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Décision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "approved",
                    "values"
                  ],
                  "properties": {
                    "approved": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "card_frozen",
                        "daily_limit_exceeded",
                        "txn_limit_exceeded",
                        "category_blocked",
                        "insufficient_funds",
                        "unknown_card",
                        "unknown_child"
                      ]
                    },
                    "values": {
                      "type": "object",
                      "description": "Règle et valeurs qui ont tranché (traçabilité)"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corps invalide"
          },
          "401": {
            "description": "Signature, horodatage ou certificat client invalide"
          },
          "403": {
            "description": "tenant_id différent de celui du credential"
          }
        }
      }
    },
    "/webhooks/funding/transfer": {
      "post": {
        "tags": [
          "banque → magot"
        ],
        "operationId": "notifyTransferOutcome",
        "summary": "Règlement ou rejet d'un virement parent → enfant",
        "description": "Le core banking notifie l'issue d'un virement demandé par magot. Idempotent : rejouer une notification est sans effet. Voir funding.md.",
        "servers": [
          {
            "url": "https://{authzHost}",
            "description": "Service d'autorisation (mTLS)",
            "variables": {
              "authzHost": {
                "default": "authz.magot.example"
              }
            }
          }
        ],
        "security": [],
        "parameters": [
          {
            "name": "Magot-Key-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identifiant du credential de la banque"
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Secondes Unix ; ±300 s"
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps brut>`, clé = secret du credential"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "transfer_id",
                  "status"
                ],
                "properties": {
                  "transfer_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Identifiant fixé par magot (TransferRequest.transferId)"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "settled",
                      "rejected"
                    ]
                  },
                  "provider_ref": {
                    "type": "string"
                  },
                  "reject_reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Appliqué, ou déjà résolu (`applied: false`)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transfer_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string"
                    },
                    "applied": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Signature invalide"
          },
          "404": {
            "description": "Virement inconnu de cet établissement"
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://api-staging.magot.ch",
      "description": "Sandbox (données de démonstration)"
    },
    {
      "url": "https://{apiHost}",
      "description": "Production de l'établissement",
      "variables": {
        "apiHost": {
          "default": "api.magot.example"
        }
      }
    }
  ],
  "webhooks": {
    "ch.magot.TopUpReceived.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onTopUpReceived",
        "summary": "TopUpReceived",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.TopUpReceived.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.TopUpPending.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onTopUpPending",
        "summary": "TopUpPending",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.TopUpPending.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.TopUpRejected.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onTopUpRejected",
        "summary": "TopUpRejected",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.TopUpRejected.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.MilestoneReached.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onMilestoneReached",
        "summary": "MilestoneReached",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.MilestoneReached.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PaymentSettled.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPaymentSettled",
        "summary": "PaymentSettled",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PaymentSettled.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PaymentDeclined.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPaymentDeclined",
        "summary": "PaymentDeclined",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PaymentDeclined.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.RoundUpSwept.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onRoundUpSwept",
        "summary": "RoundUpSwept",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.RoundUpSwept.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.AuthorizationApproved.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onAuthorizationApproved",
        "summary": "AuthorizationApproved",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.AuthorizationApproved.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.AuthorizationDeclined.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onAuthorizationDeclined",
        "summary": "AuthorizationDeclined",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.AuthorizationDeclined.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.RequestCreated.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onRequestCreated",
        "summary": "RequestCreated",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.RequestCreated.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.RequestApproved.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onRequestApproved",
        "summary": "RequestApproved",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.RequestApproved.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.RequestDeclined.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onRequestDeclined",
        "summary": "RequestDeclined",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.RequestDeclined.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.MissionCreated.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onMissionCreated",
        "summary": "MissionCreated",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.MissionCreated.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.MissionCompleted.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onMissionCompleted",
        "summary": "MissionCompleted",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.MissionCompleted.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.MissionValidated.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onMissionValidated",
        "summary": "MissionValidated",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.MissionValidated.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PotCreated.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPotCreated",
        "summary": "PotCreated",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PotCreated.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PotDeposit.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPotDeposit",
        "summary": "PotDeposit",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PotDeposit.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PotWithdraw.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPotWithdraw",
        "summary": "PotWithdraw",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PotWithdraw.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PotGoalReached.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPotGoalReached",
        "summary": "PotGoalReached",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PotGoalReached.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.PotsReordered.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onPotsReordered",
        "summary": "PotsReordered",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.PotsReordered.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.ChildCreated.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onChildCreated",
        "summary": "ChildCreated",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.ChildCreated.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.CardIssued.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onCardIssued",
        "summary": "CardIssued",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.CardIssued.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.CardFrozen.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onCardFrozen",
        "summary": "CardFrozen",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.CardFrozen.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.CardUnfrozen.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onCardUnfrozen",
        "summary": "CardUnfrozen",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.CardUnfrozen.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.RulesChanged.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onRulesChanged",
        "summary": "RulesChanged",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.RulesChanged.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.BalanceMismatch.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onBalanceMismatch",
        "summary": "BalanceMismatch",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.BalanceMismatch.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    },
    "ch.magot.BalanceReconciled.v1": {
      "post": {
        "tags": [
          "magot → banque"
        ],
        "operationId": "onBalanceReconciled",
        "summary": "BalanceReconciled",
        "description": "Livré au SI de la banque abonnée, dans l'ordre du journal, au moins une fois (dédoublonner par `id`). Répondre 2xx ; tout autre statut bloque l'abonnement et déclenche un nouvel essai (backoff jusqu'à 1 h).",
        "parameters": [
          {
            "name": "Magot-Subscription-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Magot-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Magot-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`v1=` + HMAC-SHA256 hex de `<timestamp>.<corps>`, clé = secret de l'abonnement"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/cloudevents+json": {
              "schema": {
                "type": "object",
                "required": [
                  "specversion",
                  "id",
                  "source",
                  "type",
                  "subject",
                  "time",
                  "magotsequence",
                  "data"
                ],
                "properties": {
                  "specversion": {
                    "const": "1.0"
                  },
                  "id": {
                    "type": "string",
                    "description": "`<tenant>:<séquence>` — clé de dédoublonnage"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "const": "ch.magot.BalanceReconciled.v1"
                  },
                  "subject": {
                    "type": "string",
                    "description": "`child/<id>`, `money_request/<id>`, `mission/<id>`, `pot/<id>`"
                  },
                  "time": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "datacontenttype": {
                    "const": "application/json"
                  },
                  "magotsequence": {
                    "type": "integer",
                    "description": "Ordre strict par établissement"
                  },
                  "data": {
                    "type": "object",
                    "description": "Charge utile du type (voir outbound-events.md)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Accusé de réception"
          }
        }
      }
    }
  },
  "security": [
    {
      "Bearer": []
    },
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "identité",
      "description": "Sessions, identité bancaire fédérée, appareils, consentements"
    },
    {
      "name": "lecture",
      "description": "Bootstrap, sync delta, configuration de l'établissement"
    },
    {
      "name": "enfants",
      "description": "Ouverture d'un enfant dans le foyer"
    },
    {
      "name": "carte",
      "description": "Émission, gel et dégel"
    },
    {
      "name": "argent",
      "description": "Recharges et paiements"
    },
    {
      "name": "demandes",
      "description": "Demandes d'argent enfant → parent"
    },
    {
      "name": "missions",
      "description": "Missions rémunérées"
    },
    {
      "name": "sous-magots",
      "description": "Tirelires multiples et arrondi"
    },
    {
      "name": "règles",
      "description": "Plafonds, catégories, arrondi"
    },
    {
      "name": "banque → magot",
      "description": "Appels du processeur carte et du core banking (service d'autorisation, mTLS + HMAC)"
    },
    {
      "name": "magot → banque",
      "description": "Événements poussés au SI de la banque (CloudEvents signés)"
    }
  ]
}
