Aller au contenu

Lemonway — Webhooks

Webhooks serveur-à-serveur appelés par Lemonway pour notifier les changements de statut KYC/KYB, statut de documents, blocage temporaire, chargeback et changement de statut de compte/profil (onboarding V2). Source : hook.controller.ts.

Tous les endpoints sont sous le préfixe /customers/lemonway/webhook. Pas de JwtAuthGuard ni UserRoleGuard — la protection repose sur ApiAuthService.assertApiKeyInQueryParams(queryParams, 'lemonway') : la clé doit être passée en query param apiKey et est comparée en temps constant (crypto.timingSafeEqual) à getEnvConfig().lemonway.apiKeyInternalWebhook. Si la clé n'est pas configurée côté API, l'auth est désactivée (cas dev/test) — la valeur d'env est obligatoire en production. Voir api-auth.service.ts.

POST /webhook/customer-status-changed

Notification de changement de statut KYC/KYB (onboarding V1) sur un compte Lemonway investisseur ou SPV. Source : hook.controller.ts#L57.

Query params

  • apiKey — requis si lemonway.apiKeyInternalWebhook est configuré

Request body

LemonwayWebhookDtoRaw (voir parseLemonwayWebhookDto) — contient notamment ExtId (UUID investisseur ou external id SPV) et IntId (id Lemonway). Tous les champs numériques arrivent en string et sont convertis.

Effets

  • Si ExtId est un UUID valide → cherche l'investisseur.
  • Cherche toujours le SPV par lemonwayExternalId (lookup inconditionnel, indépendant du résultat investisseur).
  • Si ni l'un ni l'autre : log + 200 (no-op).
  • Si investisseur trouvé : CustomerLemonwayService.syncCustomerStatusOnboardingV1(customer.id).
  • Si SPV trouvé : specialPurposeVehiculeService.syncSpvLemonwayKYBStatusOnboardingV1(spv.id). Les deux blocs sont indépendants et peuvent s'exécuter dans le même appel.

Response

200 (pas de body).

Erreurs

Code Statut Cause
UnauthorizedException 401 apiKey query param manquante ou invalide
lemonway-webhook-payload-missing-ids 500 ExtId ou IntId absent du payload

POST /webhook/document-status-changed

Notification de changement de statut sur un document KYC (pièce d'identité, IBAN). Source : hook.controller.ts#L104.

Query params

  • apiKey — requis si configuré

Request body

Validé via lemonwayHookDocumentStatusPayload :

  • IntId, DocId (numbers from string)
  • ExtId (string)
  • DocType — type Lemonway (id pièce, IBAN, etc.)
  • NotifDate (ISO date)
  • NotifCategory9 (document status change)
  • Status — entier 0-8

Effets

  1. Cherche l'investisseur (par ExtId UUID) ; si SPV → ignore (non géré).
  2. Si pas d'investisseur : log et ignore (200).
  3. Re-fetch des documents Lemonway (lemonwayApi.getAccountDocuments) pour vérifier la cohérence — defense-in-depth car l'endpoint est public et n'importe qui pourrait poster.
  4. Si le statut Lemonway diffère de celui du payload : log + ignore.
  5. Si pièce d'identité (isLwDocumentIdentityType) : DocumentStatusHookUpdateService.patchInvestorIdentityDocument.
  6. Si IBAN (isLwDocumentIbanType) : PaymentMethodsService.syncLemonwayBankAccountStatusesFor(customer.id).
  7. Sinon : log d'erreur (type non géré).

Response

200 (pas de body).

Erreurs

Code Statut Cause
UnauthorizedException 401 API key manquante / invalide
BadRequestException (vide) 400 Payload invalide (validation idtt)
BadRequestException (vide) 400 Le DocId reçu n'existe pas chez Lemonway
customer-not-found 404 Investisseur de la pièce d'identité introuvable
InternalServerError 500 Erreur Lemonway lors du re-fetch

POST /webhook/customer-temporarily-blocked

Notification de blocage temporaire d'un compte (NotifCategory 13). Source : hook.controller.ts#L217.

Query params

  • apiKey — requis si configuré

Request body

Validé via customerBlockedHookValidator :

  • IntId, ExtId, NotifDate, Status (statut compte Lemonway)
  • NotifCategory doit être 13
  • Blocked0|1 mappé en booléen

Effets

  • Si investisseur trouvé : CustomerLemonwayService.syncAccountIsBlocked(customer.id).
  • Si SPV trouvé : specialPurposeVehiculeService.syncAccountIsBlockedAtLemonway(spv.id).
  • Sinon : no-op silencieux.

Response

200.

Erreurs

Code Statut Cause
UnauthorizedException 401 API key manquante / invalide
BadRequestException 400 Validation customerBlockedHookValidator échouée

POST /webhook/charge-back

Notification de chargeback sur une transaction money-out. Crée une alerte Slack puis freeze l'investisseur (best-effort, l'erreur du freeze ne casse pas le hook). Source : hook.controller.ts#L252.

Query params

  • apiKey — requis si configuré

Request body

{
  "ExtId": "uuid-customer",
  "Comment": "Raison du chargeback",
  "IdTransaction": "204"
}

Validé via object({ ExtId: string, Comment: string, IdTransaction: numberFromString }).

Effets

  1. lemonwayApi.getMoneyOut({ transactionId }) pour récupérer le détail.
  2. Alerte Slack envoyée (chargeBackAlertSlack) avant le contrôle d'erreur du fetch — pour ne pas la perdre si la suite échoue.
  3. Si transaction non trouvée chez Lemonway : log + 200 (no-op).
  4. CustomerFreezeService.freezeCustomer({ customerId, reason, source: 'webhook-chargeback', sendInternalNotification: true }) — erreur silencée.

Response

200.

Erreurs

Code Statut Cause
UnauthorizedException 401 API key manquante / invalide
BadRequestException 400 Validation payload échouée
BadRequestException (vide) 400 Erreur lors du fetch chargeback chez Lemonway

POST /webhook/account-status-changed

Notification de changement de statut de compte Lemonway (onboarding V2). Source : hook.controller.ts#L308.

Query params

  • apiKey — requis si configuré

Request body

{
  "AccountID": "uuid-lemonway-account-id"
}

Le payload complet est passé tel quel à LemonwayAccountService.onboardingStatusChangedHook.

Effets

LemonwayAccountService.onboardingStatusChangedHook({ lwAccountId, hookPayload: data }).

Response

200.

Erreurs

Code Statut Cause
UnauthorizedException 401 API key manquante / invalide
BadRequestException 400 AccountID absent / invalide

POST /webhook/profile-status-changed

Notification de changement de statut de profil Lemonway (onboarding V2). Mêmes signature et comportement que account-status-changed — appelle aussi LemonwayAccountService.onboardingStatusChangedHook. Source : hook.controller.ts#L332.

Query params / Request body / Response / Erreurs

Identiques à POST /webhook/account-status-changed.

Liens