Exposition crédit (credit_exposure)

Une credit_exposure mesure le crédit actuellement accordé et consommé par un acheteur auprès d'un marchand. C'est le pendant de la limite de crédit : la limite fixe le plafond autorisé, l'exposition trace ce qui est effectivement engagé.

Rôle

Là où le receivable agrège des factures existantes pour répondre à « combien me doit cet acheteur ? », la credit_exposure répond à « combien de crédit ai-je accordé à cet acheteur, et combien est encore ouvert ? »

L'exposition est un objet persisté — contrairement au receivable, elle n'est pas recalculée depuis les factures. Elle est construite explicitement par vos processus d'orchestration, mouvement après mouvement, à travers un journal immuable. Cela lui permet de couvrir des flux qui n'ont pas encore de facture émise (autorisation de crédit, financement d'une commande en cours) ou qui impliquent une entreprise financeur.

Il existe au plus une exposition par triplet (buyer_id, merchant_id, currency).

Identifiant et structure

Chaque exposition porte un identifiant stable préfixé par cex_. Chaque mouvement du journal porte le préfixe cem_.

JSON
"credit_exposure":{24 items
"object":"credit_exposure"
"id":"cex_2b4d1f8a9c3e7f5b"
"buyer_id":"cmp_3a8f1d9c2b4e7f6a"
"merchant_id":"mer_1a2b3c4d5e6f7a8b"
"currency":"eur"
"status":"active"
"authorized_amount_excluding_tax":500000
"authorized_amount_including_tax":600000
"consumed_amount_excluding_tax":100000
"consumed_amount_including_tax":120000
"released_amount_excluding_tax":0
"released_amount_including_tax":0
"settled_amount_excluding_tax":83334
"settled_amount_including_tax":100000
"cancelled_amount_excluding_tax":0
"cancelled_amount_including_tax":0
"expired_amount_excluding_tax":0
"expired_amount_including_tax":0
"outstanding_amount_excluding_tax":416666
"outstanding_amount_including_tax":500000
"movements":[2 items
0:{...}7 items
1:{...}7 items
]
"metadata":{}0 items
"created_at":"2026-06-17T10:00:00.000Z"
"updated_at":"2026-06-18T09:15:00.000Z"
}
{
  "object": "credit_exposure",
  "id": "cex_2b4d1f8a9c3e7f5b",
  "buyer_id": "cmp_3a8f1d9c2b4e7f6a",
  "merchant_id": "mer_1a2b3c4d5e6f7a8b",
  "currency": "eur",
  "status": "active",
  "authorized_amount_excluding_tax": 500000,
  "authorized_amount_including_tax": 600000,
  "consumed_amount_excluding_tax": 100000,
  "consumed_amount_including_tax": 120000,
  "released_amount_excluding_tax": 0,
  "released_amount_including_tax": 0,
  "settled_amount_excluding_tax": 83334,
  "settled_amount_including_tax": 100000,
  "cancelled_amount_excluding_tax": 0,
  "cancelled_amount_including_tax": 0,
  "expired_amount_excluding_tax": 0,
  "expired_amount_including_tax": 0,
  "outstanding_amount_excluding_tax": 416666,
  "outstanding_amount_including_tax": 500000,
  "movements": [
    {
      "id": "cem_1a2b3c4d5e6f7a8b",
      "type": "credit_granted",
      "amount_excluding_tax": 500000,
      "amount_including_tax": 600000,
      "source_type": "checkout_session",
      "source_id": "cs_5e2d8f1a9b3c4d7e",
      "created_at": "2026-06-17T10:00:00.000Z"
    },
    {
      "id": "cem_9f2e1a4b3c8d7e6f",
      "type": "credit_settled",
      "amount_excluding_tax": 83334,
      "amount_including_tax": 100000,
      "source_type": "payment",
      "source_id": "pay_4a7b2e9f1c3d8a5e",
      "created_at": "2026-06-18T09:15:00.000Z"
    }
  ],
  "metadata": {},
  "created_at": "2026-06-17T10:00:00.000Z",
  "updated_at": "2026-06-18T09:15:00.000Z"
}

Champs

ChampTypeDescription
idstringIdentifiant de l'exposition (préfixe cex_).
objectstringToujours "credit_exposure".
buyer_idstringEntreprise acheteuse (cmp_…).
merchant_idstringMarchand.
currencystringDevise ISO 4217 en minuscules (ex. eur). Avec (buyer_id, merchant_id) forme la clé unique.
statusenumactive ou closed.
basisenumBase utilisée par la projection amount : excluding_tax ou including_tax.
amountintegerEncours agrégé dans la base choisie par basis ; projection pratique de outstanding_amount_excluding_tax ou outstanding_amount_including_tax.
authorized_amount_excluding_taxintegerTotal du crédit accordé (HT).
authorized_amount_including_taxintegerTotal du crédit accordé (TTC).
consumed_amount_excluding_taxintegerMontant consommé à titre indicatif (HT). N'impacte pas l'encours.
consumed_amount_including_taxintegerMontant consommé à titre indicatif (TTC).
released_amount_excluding_taxintegerPortion libérée (HT). Réduit l'encours.
released_amount_including_taxintegerPortion libérée (TTC).
settled_amount_excluding_taxintegerMontant soldé après paiement (HT). Réduit l'encours.
settled_amount_including_taxintegerMontant soldé (TTC).
cancelled_amount_excluding_taxintegerMontant annulé (HT). Réduit l'encours.
cancelled_amount_including_taxintegerMontant annulé (TTC).
expired_amount_excluding_taxintegerMontant expiré (HT). Réduit l'encours.
expired_amount_including_taxintegerMontant expiré (TTC).
outstanding_amount_excluding_taxintegerEncours actif (HT). Champ calculé — voir formule.
outstanding_amount_including_taxintegerEncours actif (TTC). Champ calculé.
movementsarrayJournal immuable des mouvements (objets cem_…). Voir section Mouvements.
metadataobjectMap plate de scalaires `string | number | boolean`, selon la convention metadata de l’API.
created_atdatetimeDate de création.
updated_atdatetimeDate de dernière mise à jour.

Compteurs de montants

L'exposition accumule six paires de compteurs (HT + TTC). Chaque action sur l'exposition incrémente un compteur et peut réduire l'encours actif.

Action APIMouvement crééCompteur impactéEffet sur l'encours
grantcredit_grantedauthorized ↑outstanding ↑
consumecredit_consumedconsumed ↑inchangé
releasecredit_releasedreleased ↑outstanding ↓
settlecredit_settledsettled ↑outstanding ↓
cancelcredit_cancelledcancelled ↑outstanding ↓
expirecredit_expiredexpired ↑outstanding ↓

L'encours actif (outstanding_amount_*) est calculé en temps réel :

text
outstanding = max(0, authorized − released − settled − cancelled − expired)
consume n'impacte pas l'encours Le mouvement credit_consumed est purement indicatif — il trace qu'un crédit autorisé a été utilisé (par exemple, qu'une facture a été émise), mais il ne réduit pas outstanding. Seuls release, settle, cancel et expire réduisent l'encours actif.

Chaque compteur et le champ outstanding existent en deux bases (_excluding_tax et _including_tax). Lors d'une action, au moins une base doit être fournie.

Journal des mouvements

Le champ movements est un journal en ajout seul — chaque action sur l'exposition crée un mouvement immuable. C'est la trace complète de l'historique du crédit accordé à cet acheteur.

Champ du mouvementDescription
idIdentifiant unique du mouvement (préfixe cem_).
typeType de mouvement : credit_granted, credit_consumed, credit_released, credit_settled, credit_cancelled, credit_expired.
amount_excluding_taxMontant HT du mouvement en centimes. Optionnel selon le type.
amount_including_taxMontant TTC du mouvement en centimes. Optionnel selon le type.
source_typeType de l'objet source du mouvement (ex. checkout_session, payment, invoice).
source_idIdentifiant de l'objet source.
reasonRaison textuelle libre. Optionnel.
metadataMap plate de scalaires `string | number | boolean`. Optionnel.
created_atHorodatage du mouvement.

Statut

StatutSignification
activeL'exposition est ouverte et peut recevoir de nouveaux mouvements.
closedL'exposition est clôturée (outstanding = 0 ou annulation totale).

Interaction avec la limite de crédit

La limite de crédit définit le plafond autorisé ; l'exposition trace ce qui est effectivement engagé. Le crédit disponible est la différence entre les deux.

text
disponible = credit_limit.effective_amount − credit_exposure.outstanding_amount

Les nodes credit.evaluate_credit_availability et credit.check_credit_availability calculent automatiquement cette comparaison et produisent un objet credit_availability_check avec les champs suivants :

JSON
"credit_availability_check":{11 items
"object":"credit_availability_check"
"decision":"approved"
"reason":"within_limit"
"basis":"excluding_tax"
"currency":"eur"
"limit_amount":500000
"used_amount":416666
"requested_amount":50000
"available_amount":83334
"projected_used_amount":466666
"projected_available_amount":33334
}
{
  "object": "credit_availability_check",
  "decision": "approved",
  "reason": "within_limit",
  "basis": "excluding_tax",
  "currency": "eur",
  "limit_amount": 500000,
  "used_amount": 416666,
  "requested_amount": 50000,
  "available_amount": 83334,
  "projected_used_amount": 466666,
  "projected_available_amount": 33334
}

Lorsque decision est rejected, la raison est insufficient_available_credit. Le processus route alors vers un chemin de refus ou de demande de garantie supplémentaire.

Clé de recherche commune Limite de crédit et exposition partagent la même clé (buyer_id, merchant_id, currency). Le node credit.evaluate_credit_availability résout les deux en un seul appel.

Dans les processus

L'exposition est entièrement pilotée par des nodes de processus — il n'y a pas de mise à jour automatique déclenchée par d'autres objets.

NodeTypeDescription
credit.evaluate_credit_availabilityRouteurNode consolidé : résout la limite effective, récupère l'exposition courante et décide si le montant demandé est disponible. Sorties : effective_credit_limit, credit_exposure, credit_availability_check. Routes : approved / rejected.
credit.check_credit_availabilityRouteurVérifie uniquement la capacité à partir d'objets déjà chargés (effective_credit_limit + credit_exposure + requested_amount). Routes : approved / rejected.
credit.grant_creditHelperAugmente l'encours autorisé d'une company (POST /grant). Accepte un credit_availability_check optionnel — échoue si decision=rejected.
credit.fetch_credit_exposureHelperRécupère l'exposition courante d'une company (GET /current). Retourne une exposition vide (outstanding = 0) si aucune n'existe encore.
credit.consume_credit_exposureHelperEnregistre une consommation indicative (POST /consume). N'impacte pas l'encours.
credit.release_credit_exposureHelperLibère une portion non utilisée (POST /release). Réduit l'encours.
credit.settle_credit_exposureHelperSolde une portion après paiement (POST /settle). Réduit l'encours.
credit.cancel_credit_exposureHelperAnnule tout ou partie de l'encours restant (POST /cancel). Si aucun montant fourni, annule la totalité.

Flux typique : autorisation de crédit

Voici le schéma habituel d'un processus de décision crédit lors d'un checkout :

text
credit.evaluate_credit_availability (company, montant demandé)
  → approved → credit.grant_credit → créer checkout session / commande
  → rejected → notifier l'acheteur ou demander une garantie

Flux typique : clôture après paiement

text
payment.matched ou psp_payment.succeeded
  → credit.fetch_credit_exposure (company)
  → credit.settle_credit_exposure (montant encaissé)
  → [si outstanding = 0] credit.cancel_credit_exposure

Événements

Chaque action sur l'exposition émet un événement distinct. Le payload inclut l'état complet de l'exposition avant et après le mouvement (diff before/after), ainsi que le mouvement lui-même dans latest_movement.

ÉvénementDéclencheur
credit_exposure.grantedPOST /grant — nouvel encours accordé ou encours existant augmenté.
credit_exposure.consumedPOST /:id/consume — consommation indicative enregistrée.
credit_exposure.releasedPOST /:id/release — portion libérée.
credit_exposure.settledPOST /:id/settle — portion soldée.
credit_exposure.cancelledPOST /:id/cancel — portion annulée.
credit_exposure.expiredPOST /:id/expire — portion expirée.

L'événement credit_exposure.granted est émis à la fois à la création (première action grant) et lors de chaque augmentation ultérieure de l'encours autorisé.