{"openapi":"3.0.0","paths":{"/api/auth/introspect":{"post":{"operationId":"AuthController_introspect","summary":"Introspection d'un token (API key ou access token OAuth)","description":"Valide une API key (fk_live_/fk_test_) ou un access token JWT OAuth et retourne company_id, scopes et client_id. Réservé aux services internes.","parameters":[],"responses":{"200":{"description":""}},"tags":["Auth"]}},"/oauth/register":{"post":{"operationId":"OAuthController_register","summary":"Enregistrement dynamique d'un client OAuth (RFC 7591)","description":"Permet a un connecteur MCP (ex. Claude) de s'auto-enregistrer comme client OAuth public.\n\nVerrous de securite : redirect_uris limitees a une liste blanche (defaut : callbacks exacts\nhttps://claude.ai/api/mcp/auth_callback et https://claude.com/api/mcp/auth_callback), nom valide strictement, scopes plafonnes au set MCP (lecture seule par defaut),\nlimitation de debit par IP, desactivation des clients jamais autorises. Aucun acces a une entreprise\nsans login Finkare et consentement de l'utilisateur.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterClientDto"}}}},"responses":{"201":{"description":"Client enregistre"},"400":{"description":"Metadata invalide (redirect_uri hors allowlist, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthErrorDto"}}}},"429":{"description":"Trop d'enregistrements depuis cette IP"}},"tags":["OAuth"]}},"/oauth/token":{"post":{"operationId":"OAuthController_getToken","summary":"Obtenir un access token","description":"Endpoint unifié pour les 3 grant types OAuth 2.1 :\n\n- **client_credentials** : authentification serveur-à-serveur (M2M)\n- **authorization_code** : flow utilisateur avec PKCE (applications tierces)\n- **refresh_token** : renouvellement d'un access token expiré\n\nLes credentials peuvent être passés dans le body ou via le header `Authorization: Basic <base64(client_id:client_secret)>`.","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}},{"name":"Authorization","in":"header","description":"Basic Auth (base64 de client_id:client_secret)","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequestDto"}}}},"responses":{"200":{"description":"Access token généré avec succès","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponseDto"}}}},"400":{"description":"Requête invalide (paramètres manquants, grant_type non supporté)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthErrorDto"}}}},"401":{"description":"Authentification échouée (client_id ou client_secret invalide)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthErrorDto"}}}}},"tags":["OAuth"]}},"/oauth/authorize":{"get":{"operationId":"OAuthController_authorize","summary":"Initier le flow Authorization Code + PKCE","description":"Redirige l'utilisateur vers l'écran de consentement Finkare. Seule la méthode PKCE S256 est supportée (conformité OAuth 2.1).","parameters":[{"name":"response_type","required":true,"in":"query","description":"Doit etre \"code\"","schema":{"example":"code","type":"string"}},{"name":"client_id","required":true,"in":"query","description":"Client ID du partenaire","schema":{"example":"fk_client_abc123","type":"string"}},{"name":"redirect_uri","required":true,"in":"query","description":"URI de redirection","schema":{"example":"https://partner.com/callback","type":"string"}},{"name":"scope","required":true,"in":"query","description":"Scopes demandes (separes par espaces)","schema":{"example":"invoices:read debtors:read","type":"string"}},{"name":"state","required":true,"in":"query","description":"State anti-CSRF","schema":{"example":"random-state-123","type":"string"}},{"name":"code_challenge","required":true,"in":"query","description":"PKCE code challenge (SHA256)","schema":{"example":"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM","type":"string"}},{"name":"code_challenge_method","required":false,"in":"query","description":"Methode de challenge PKCE","schema":{"default":"S256","example":"S256","type":"string"}}],"responses":{"302":{"description":"Redirection vers l'écran de consentement Finkare"},"400":{"description":"Paramètres invalides (response_type, redirect_uri, etc.)"}},"tags":["OAuth"]}},"/oauth/authorize/consent":{"post":{"operationId":"OAuthController_consent","summary":"Valider le consentement et générer un code d'autorisation","description":"Appelé après que l'utilisateur a approuvé les scopes demandés. Requiert un access token Supabase (Authorization: Bearer) d'un company_admin actif et un second facteur de moins de 30 minutes (jeton aal2 pour un compte à MFA native, sinon jeton OTP signé du portail dans l'en-tête x-finkare-second-factor). Génère un code d'autorisation à échanger contre un access token.","parameters":[{"name":"x-finkare-second-factor","required":false,"in":"header","description":"Jeton OTP signé du portail client (comptes sans MFA native)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentDto"}}}},"responses":{"200":{"description":"Code d'autorisation généré"},"400":{"description":"Paramètres invalides"},"401":{"description":"Token Supabase manquant ou invalide"},"403":{"description":"user_id different de l'utilisateur authentifie, profil inactif, role company_admin absent ou second facteur trop ancien"}},"tags":["OAuth"],"security":[{"bearer":[]}]}},"/oauth/revoke":{"post":{"operationId":"OAuthController_revoke","summary":"Révoquer un token (RFC 7009)","description":"Révoque un access token ou refresh token. La signature et l'émetteur du token sont vérifiés avant révocation. L'opération est idempotente (200 même si le token est déjà révoqué ou invalide). Si le client s'authentifie (body ou Basic), il ne peut révoquer que ses propres tokens.","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}},{"name":"Authorization","in":"header","description":"Basic Auth optionnel (base64 de client_id:client_secret)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Token révoqué (ou déjà invalide)"},"400":{"description":"Paramètre token manquant"},"401":{"description":"Authentification client échouée (invalid_client)"}},"tags":["OAuth"]}},"/oauth/introspect":{"post":{"operationId":"OAuthController_introspectToken","summary":"Introspection de token (RFC 7662)","description":"Vérifie la validité d'un token et retourne ses métadonnées (client_id, scopes, etc.).","parameters":[],"responses":{"200":{"description":"Métadonnées du token (active: true/false)"},"400":{"description":"Paramètre token manquant"}},"tags":["OAuth"]}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"WellKnownController_getAuthorizationServerMetadata","summary":"OAuth 2.0 Authorization Server Metadata (RFC 8414)","description":"Retourne les métadonnées du serveur d'autorisation : endpoints, scopes supportés, grant types et méthodes d'authentification.","parameters":[],"responses":{"200":{"description":"Métadonnées du serveur d'autorisation OAuth 2.0"}},"tags":["OAuth Discovery"]}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"WellKnownController_getProtectedResourceMetadata","summary":"OAuth 2.0 Protected Resource Metadata (RFC 9728)","description":"Retourne les métadonnées de la ressource protégée : serveurs d'autorisation associés, scopes supportés et méthodes de présentation du bearer token.","parameters":[],"responses":{"200":{"description":"Métadonnées de la ressource protégée"}},"tags":["OAuth Discovery"]}},"/api/v1/invoices":{"get":{"operationId":"InvoicesController_listInvoices","summary":"Lister les factures","description":"Récupère la liste paginée des factures avec filtres optionnels","parameters":[{"name":"status","required":false,"in":"query","description":"Filtrer par statut de la facture","schema":{"example":"in_recovery","enum":["draft","imported","lrar_sent","in_recovery","paid","partial","disputed","written_off","judicial"],"type":"string"}},{"name":"debtorId","required":false,"in":"query","description":"Filtrer par ID du débiteur (UUID)","schema":{"example":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c","type":"string"}},{"name":"fromDate","required":false,"in":"query","description":"Date de début (émission, ISO 8601)","schema":{"example":"2026-01-01","type":"string"}},{"name":"toDate","required":false,"in":"query","description":"Date de fin (émission, ISO 8601)","schema":{"example":"2026-03-31","type":"string"}},{"name":"minAmount","required":false,"in":"query","description":"Montant minimum en centimes","schema":{"example":10000,"type":"number"}},{"name":"maxAmount","required":false,"in":"query","description":"Montant maximum en centimes","schema":{"example":500000,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Recherche textuelle (numéro de facture, nom du débiteur)","schema":{"example":"FAC-2026","type":"string"}},{"name":"page","required":false,"in":"query","description":"Numéro de page (commence à 1)","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Nombre de résultats par page (max 100)","schema":{"default":20,"example":20,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Champ de tri","schema":{"default":"created_at","example":"created_at","enum":["created_at","due_date","amount_cents","status"],"type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Ordre de tri","schema":{"default":"desc","example":"desc","enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"Liste paginée des factures avec métadonnées de pagination"},"401":{"description":"Non authentifié : API key manquante ou invalide"},"403":{"description":"Scope invoices:read requis"},"429":{"description":"Rate limit dépassé : consultez les headers X-RateLimit-*"}},"tags":["Invoices"],"security":[{"api-key":[]}]},"post":{"operationId":"InvoicesController_createInvoice","summary":"Créer une facture","description":"Crée une nouvelle facture à recouvrer et démarre automatiquement le workflow","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvoiceDto"}}}},"responses":{"201":{"description":"Facture créée. workflowStarted indique si le recouvrement a réellement démarré ; sinon workflowError en donne la raison (ex. coordonnées du débiteur incomplètes)","content":{"application/json":{"schema":{"example":{"success":true,"data":{"id":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","invoiceNumber":"FAC-2026-001","amountCents":150000,"currency":"EUR","status":"imported","workflowStarted":true,"createdAt":"2026-04-08T10:00:00Z"},"requestId":"req_abc123","timestamp":"2026-04-08T10:00:00Z"}}}}},"400":{"description":"Données invalides (champs manquants, format incorrect)"},"401":{"description":"Non authentifié"},"403":{"description":"Scope invoices:write requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Invoices"],"security":[{"api-key":[]}]}},"/api/v1/invoices/{id}":{"get":{"operationId":"InvoicesController_getInvoice","summary":"Récupérer une facture","description":"Récupère les détails d'une facture spécifique","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{"example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","type":"string"}}],"responses":{"200":{"description":"Détails complets de la facture incluant les informations du débiteur et le statut du workflow"},"401":{"description":"Non authentifié"},"403":{"description":"Scope invoices:read requis"},"404":{"description":"Facture non trouvée"},"429":{"description":"Rate limit dépassé"}},"tags":["Invoices"],"security":[{"api-key":[]}]},"put":{"operationId":"InvoicesController_updateInvoice","summary":"Mettre à jour une facture","description":"Met à jour les metadata et notes d'une facture.\n    \n**PROTECTION DES DONNÉES** : Les champs suivants sont **immuables** après import :\n- `amount` (montant)\n- `invoiceNumber` (référence)\n- `issueDate` (date d'émission)\n- `dueDate` (date d'échéance)\n- `currency` (devise)\n- `debtor` (informations débiteur)\n\nPour annuler un recouvrement, utilisez `POST /v1/invoices/{id}/cancel`","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{}}],"responses":{"200":{"description":"Facture mise à jour (metadata/notes uniquement)"},"403":{"description":"Tentative de modification de champs protégés"},"404":{"description":"Facture non trouvée"}},"tags":["Invoices"],"security":[{"api-key":[]}]},"delete":{"operationId":"InvoicesController_deleteInvoice","summary":"Supprimer une facture","description":"Supprime une facture **uniquement si le workflow n'est pas encore lancé**.\n    \nPour annuler un recouvrement en cours, utilisez `POST /v1/invoices/{id}/cancel`","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{}}],"responses":{"204":{"description":"Facture supprimée"},"400":{"description":"Workflow déjà lancé - utilisez /cancel"},"404":{"description":"Facture non trouvée"}},"tags":["Invoices"],"security":[{"api-key":[]}]}},"/api/v1/invoices/bulk":{"post":{"operationId":"InvoicesController_bulkImportInvoices","summary":"Import en masse","description":"Importe plusieurs factures en une seule requête (max 100)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkImportInvoicesDto"}}}},"responses":{"201":{"description":"Résultat par facture : created, id, workflowStarted (et workflowError ou error en cas d'échec), plus les totaux created / failed / workflowsStarted"},"400":{"description":"Données invalides ou plus de 100 factures dans la requête"},"401":{"description":"Non authentifié"},"403":{"description":"Scope invoices:write requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Invoices"],"security":[{"api-key":[]}]}},"/api/v1/invoices/{id}/cancel":{"post":{"operationId":"InvoicesController_cancelInvoice","summary":"Annuler un recouvrement","description":"Annule complètement un recouvrement en cours.\n\n**Actions effectuées :**\n- Arrêt du workflow de recouvrement\n- Annulation des emails, SMS, LRAR planifiés\n- Annulation des appels vocaux IA en attente\n- Mise à jour des statuts (facture + dette → cancelled)\n- Notification optionnelle au débiteur\n- Log de l'événement pour audit\n\n**Scopes requis :** `invoices:write` + `workflow:trigger`","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{}}],"responses":{"200":{"description":"Recouvrement annulé avec succès","content":{"application/json":{"schema":{"example":{"success":true,"data":{"invoiceId":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","reference":"FAC-2026-001","previousStatus":"in_recovery","newStatus":"cancelled","cancelledAt":"2026-01-22T15:30:00Z","summary":{"actionsCancelled":5,"voiceCallsCancelled":1,"debtorNotified":false}}}}}}},"400":{"description":"Facture déjà annulée ou payée"},"403":{"description":"Scopes insuffisants"},"404":{"description":"Facture non trouvée"}},"tags":["Invoices"],"security":[{"api-key":[]}]}},"/api/v1/invoices/stats/summary":{"get":{"operationId":"InvoicesController_getStats","summary":"Statistiques des factures","description":"Récupère un résumé statistique des factures","parameters":[],"responses":{"200":{"description":"Résumé statistique des factures","content":{"application/json":{"schema":{"example":{"success":true,"data":{"totalInvoices":342,"totalAmountCents":4850000,"byStatus":{"in_recovery":45,"paid":280,"partial":12,"disputed":5},"recoveryRate":87.4},"requestId":"req_s1t2u3","timestamp":"2026-04-08T10:00:00Z"}}}}},"401":{"description":"Non authentifié"},"403":{"description":"Scope reports:read requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Invoices"],"security":[{"api-key":[]}]}},"/api/v1/workflow/invoice/{invoiceId}":{"get":{"operationId":"WorkflowController_getWorkflowStatus","summary":"Statut du workflow","description":"Récupère le statut actuel du workflow de recouvrement pour une facture","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{"example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","type":"string"}}],"responses":{"200":{"description":"Statut actuel du workflow de recouvrement","content":{"application/json":{"schema":{"example":{"success":true,"data":{"invoiceId":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","status":"in_recovery","currentStep":"relance_email_2","startedAt":"2026-02-20T09:00:00Z","actionsCompleted":3,"nextActionAt":"2026-04-10T08:00:00Z"},"requestId":"req_w1x2y3","timestamp":"2026-04-08T10:00:00Z"}}}}},"401":{"description":"Non authentifié"},"403":{"description":"Scope workflow:read requis"},"404":{"description":"Facture ou workflow non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Workflow"],"security":[{"api-key":[]}]}},"/api/v1/workflow/invoice/{invoiceId}/history":{"get":{"operationId":"WorkflowController_getWorkflowHistory","summary":"Historique du workflow","description":"Récupère l'historique complet des actions de recouvrement","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{"example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","type":"string"}}],"responses":{"200":{"description":"Historique chronologique de toutes les actions de recouvrement"},"401":{"description":"Non authentifié"},"403":{"description":"Scope workflow:read requis"},"404":{"description":"Facture non trouvée"},"429":{"description":"Rate limit dépassé"}},"tags":["Workflow"],"security":[{"api-key":[]}]}},"/api/v1/workflow/invoice/{invoiceId}/trigger":{"post":{"operationId":"WorkflowController_triggerWorkflowAction","summary":"Déclencher une action","description":"Déclenche une action sur le workflow. Seule l'action start (lancement du recouvrement) est disponible ; pause, resume, cancel et escalate renvoient 501.","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{"example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerWorkflowDto"}}}},"responses":{"200":{"description":"Recouvrement lancé (workflowStarted: true)"},"400":{"description":"Action invalide pour le statut actuel du workflow"},"401":{"description":"Non authentifié"},"403":{"description":"Scope workflow:trigger requis, ou refus métier : error.code = sandbox, mandate_not_signed ou company_blocked"},"404":{"description":"Facture non trouvée"},"409":{"description":"Refus métier : error.code = recovery_stopped, debt_closed, already_launched ou legal_step_already_sent"},"429":{"description":"Rate limit dépassé"}},"tags":["Workflow"],"security":[{"api-key":[]}]}},"/api/v1/workflow/stats":{"get":{"operationId":"WorkflowController_getWorkflowStats","summary":"Statistiques des workflows","description":"Récupère les statistiques globales des workflows de recouvrement","parameters":[],"responses":{"200":{"description":"Statistiques globales des workflows actifs, terminés et en attente"},"401":{"description":"Non authentifié"},"403":{"description":"Scope reports:read requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Workflow"],"security":[{"api-key":[]}]}},"/api/v1/workflow/invoice/{invoiceId}/next-action":{"get":{"operationId":"WorkflowController_getNextAction","summary":"Prochaine action planifiée","description":"Récupère la prochaine action de recouvrement planifiée par l'IA","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{"example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab"}}],"responses":{"200":{"description":"Prochaine action de recouvrement planifiée par l'IA","content":{"application/json":{"schema":{"example":{"success":true,"data":{"invoiceId":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","nextAction":"sms_reminder","scheduledAt":"2026-04-10T08:00:00Z","channel":"sms","reason":"Aucune réponse aux 2 emails de relance précédents"},"requestId":"req_n1a2b3","timestamp":"2026-04-08T10:00:00Z"}}}}},"401":{"description":"Non authentifié"},"403":{"description":"Scope workflow:read requis"},"404":{"description":"Facture ou workflow non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Workflow"],"security":[{"api-key":[]}]}},"/api/v1/payments":{"get":{"operationId":"PaymentsController_listPayments","summary":"Lister les paiements","description":"Récupère la liste paginée des paiements reçus","parameters":[],"responses":{"200":{"description":"Liste paginée des paiements reçus"},"401":{"description":"Non authentifié : API key manquante ou invalide"},"403":{"description":"Scope payments:read requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Payments"],"security":[{"api-key":[]}]}},"/api/v1/payments/{id}":{"get":{"operationId":"PaymentsController_getPayment","summary":"Récupérer un paiement","description":"Récupère les détails d'un paiement spécifique","parameters":[{"name":"id","required":true,"in":"path","description":"ID du paiement (UUID)","schema":{"example":"d4e5f6a7-b1c2-8901-def0-234567890abc"}}],"responses":{"200":{"description":"Détails du paiement","content":{"application/json":{"schema":{"example":{"success":true,"data":{"id":"d4e5f6a7-b1c2-8901-def0-234567890abc","invoiceId":"c3d4e5f6-a1b2-7890-cdef-1234567890ab","amountCents":75000,"currency":"EUR","status":"completed","method":"card","paidAt":"2026-03-10T14:22:00Z"},"requestId":"req_x1y2z3","timestamp":"2026-04-08T10:00:00Z"}}}}},"401":{"description":"Non authentifié"},"403":{"description":"Scope payments:read requis"},"404":{"description":"Paiement non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Payments"],"security":[{"api-key":[]}]}},"/api/v1/payments/invoice/{invoiceId}":{"get":{"operationId":"PaymentsController_getPaymentsByInvoice","summary":"Paiements d'une facture","description":"Récupère tous les paiements associés à une facture","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"ID de la facture (UUID)","schema":{"example":"c3d4e5f6-a1b2-7890-cdef-1234567890ab"}}],"responses":{"200":{"description":"Liste des paiements associés à la facture"},"401":{"description":"Non authentifié"},"403":{"description":"Scope payments:read requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Payments"],"security":[{"api-key":[]}]}},"/api/v1/payments/stats/summary":{"get":{"operationId":"PaymentsController_getPaymentStats","summary":"Statistiques des paiements","description":"Récupère un résumé statistique des paiements","parameters":[{"name":"period","required":false,"in":"query","description":"Période d'agrégation","schema":{"enum":["day","week","month","year"],"type":"string"}}],"responses":{"200":{"description":"Statistiques agrégées des paiements"},"401":{"description":"Non authentifié"},"403":{"description":"Scope reports:read requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Payments"],"security":[{"api-key":[]}]}},"/api/v1/debtors":{"get":{"operationId":"DebtorsController_listDebtors","summary":"Lister les débiteurs","description":"Récupère la liste paginée des débiteurs","parameters":[],"responses":{"200":{"description":"Liste paginée des débiteurs"},"401":{"description":"Non authentifié : API key manquante ou invalide"},"403":{"description":"Scope debtors:read requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Debtors"],"security":[{"api-key":[]}]},"post":{"operationId":"DebtorsController_createDebtor","summary":"Créer un débiteur","description":"Crée un nouveau débiteur dans la base","parameters":[],"responses":{"201":{"description":"Débiteur créé avec succès"},"400":{"description":"Données invalides (email, SIRET, etc.)"},"401":{"description":"Non authentifié"},"403":{"description":"Scope debtors:write requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Debtors"],"security":[{"api-key":[]}]}},"/api/v1/debtors/{id}":{"get":{"operationId":"DebtorsController_getDebtor","summary":"Récupérer un débiteur","description":"Récupère les détails d'un débiteur spécifique avec ses factures","parameters":[{"name":"id","required":true,"in":"path","description":"ID du débiteur (UUID)","schema":{"example":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c"}}],"responses":{"200":{"description":"Détails du débiteur avec ses factures associées"},"401":{"description":"Non authentifié"},"403":{"description":"Scope debtors:read requis"},"404":{"description":"Débiteur non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Debtors"],"security":[{"api-key":[]}]},"put":{"operationId":"DebtorsController_updateDebtor","summary":"Mettre à jour un débiteur","description":"Met à jour les informations d'un débiteur","parameters":[{"name":"id","required":true,"in":"path","description":"ID du débiteur (UUID)","schema":{"example":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c"}}],"responses":{"200":{"description":"Débiteur mis à jour avec succès"},"400":{"description":"Données invalides"},"401":{"description":"Non authentifié"},"403":{"description":"Scope debtors:write requis"},"404":{"description":"Débiteur non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Debtors"],"security":[{"api-key":[]}]}},"/api/v1/debtors/{id}/invoices":{"get":{"operationId":"DebtorsController_getDebtorInvoices","summary":"Factures d'un débiteur","description":"Récupère toutes les factures d'un débiteur","parameters":[{"name":"id","required":true,"in":"path","description":"ID du débiteur (UUID)","schema":{"example":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c"}}],"responses":{"200":{"description":"Liste des factures associées au débiteur"},"401":{"description":"Non authentifié"},"403":{"description":"Scopes debtors:read et invoices:read requis"},"404":{"description":"Débiteur non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Debtors"],"security":[{"api-key":[]}]}},"/api/v1/debtors/{id}/score":{"get":{"operationId":"DebtorsController_getDebtorScore","summary":"Score de solvabilité","description":"Récupère le score de solvabilité calculé par l'IA","parameters":[{"name":"id","required":true,"in":"path","description":"ID du débiteur (UUID)","schema":{"example":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c"}}],"responses":{"200":{"description":"Score de solvabilité calculé par l'IA","content":{"application/json":{"schema":{"example":{"success":true,"data":{"debtorId":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c","score":72,"riskLevel":"medium","factors":["Historique de paiement irrégulier","Ancienneté du compte > 2 ans"],"lastUpdated":"2026-03-15T08:30:00Z"},"requestId":"req_a1b2c3d4","timestamp":"2026-04-08T10:00:00Z"}}}}},"401":{"description":"Non authentifié"},"403":{"description":"Scope debtors:read requis"},"404":{"description":"Débiteur non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Debtors"],"security":[{"api-key":[]}]}},"/api/v1/webhooks":{"get":{"operationId":"WebhooksController_listWebhooks","summary":"Lister les webhooks","description":"Récupère la liste des webhooks configurés pour votre compte","parameters":[],"responses":{"200":{"description":"Liste des webhooks configurés pour votre compte"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]},"post":{"operationId":"WebhooksController_createWebhook","summary":"Créer un webhook","description":"Configure un nouveau webhook pour recevoir des événements","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookDto"}}}},"responses":{"201":{"description":"Webhook créé : le secret de signature est retourné une seule fois","content":{"application/json":{"schema":{"example":{"success":true,"data":{"id":"e5f6a7b8-c1d2-9012-ef01-345678901bcd","url":"https://api.example.com/webhooks/finkare","events":["invoice.created","payment.received"],"enabled":true,"secret":"whsec_a1b2c3d4e5f6...","createdAt":"2026-04-08T10:00:00Z"},"message":"Webhook created. Save the secret - it will not be shown again.","requestId":"req_w1h2k3","timestamp":"2026-04-08T10:00:00Z"}}}}},"400":{"description":"URL invalide (HTTPS requis) ou événements inconnus"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"429":{"description":"Rate limit dépassé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]}},"/api/v1/webhooks/{id}":{"get":{"operationId":"WebhooksController_getWebhook","summary":"Récupérer un webhook","description":"Récupère les détails d'un webhook","parameters":[{"name":"id","required":true,"in":"path","description":"ID du webhook (UUID)","schema":{"example":"e5f6a7b8-c1d2-9012-ef01-345678901bcd","type":"string"}}],"responses":{"200":{"description":"Détails du webhook (sans le secret)"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"404":{"description":"Webhook non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]},"put":{"operationId":"WebhooksController_updateWebhook","summary":"Mettre à jour un webhook","description":"Modifie la configuration d'un webhook","parameters":[{"name":"id","required":true,"in":"path","description":"ID du webhook (UUID)","schema":{"example":"e5f6a7b8-c1d2-9012-ef01-345678901bcd","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookDto"}}}},"responses":{"200":{"description":"Webhook mis à jour avec succès"},"400":{"description":"URL invalide ou événements inconnus"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"404":{"description":"Webhook non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]},"delete":{"operationId":"WebhooksController_deleteWebhook","summary":"Supprimer un webhook","description":"Supprime un webhook configuré","parameters":[{"name":"id","required":true,"in":"path","description":"ID du webhook (UUID)","schema":{"example":"e5f6a7b8-c1d2-9012-ef01-345678901bcd","type":"string"}}],"responses":{"204":{"description":"Webhook supprimé avec succès"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"404":{"description":"Webhook non trouvé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]}},"/api/v1/webhooks/{id}/rotate-secret":{"post":{"operationId":"WebhooksController_rotateSecret","summary":"Régénérer le secret","description":"Génère un nouveau secret pour la signature des webhooks","parameters":[{"name":"id","required":true,"in":"path","description":"ID du webhook (UUID)","schema":{"example":"e5f6a7b8-c1d2-9012-ef01-345678901bcd","type":"string"}}],"responses":{"200":{"description":"Nouveau secret généré : retourné une seule fois"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"404":{"description":"Webhook non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]}},"/api/v1/webhooks/events/available":{"get":{"operationId":"WebhooksController_listAvailableEvents","summary":"Événements disponibles","description":"Liste tous les types d'événements webhook disponibles","parameters":[],"responses":{"200":{"description":"Liste de tous les types d'événements disponibles avec leurs descriptions"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"}},"tags":["Webhooks"],"security":[{"api-key":[]}]}},"/api/v1/webhooks/{id}/deliveries":{"get":{"operationId":"WebhooksController_getDeliveries","summary":"Historique des deliveries","description":"Récupère l'historique des tentatives de livraison pour un webhook","parameters":[{"name":"id","required":true,"in":"path","description":"ID du webhook (UUID)","schema":{"example":"e5f6a7b8-c1d2-9012-ef01-345678901bcd","type":"string"}}],"responses":{"200":{"description":"Historique des tentatives de livraison (succès et échecs)"},"401":{"description":"Non authentifié"},"403":{"description":"Scope webhooks:manage requis"},"404":{"description":"Webhook non trouvé"},"429":{"description":"Rate limit dépassé"}},"tags":["Webhooks"],"security":[{"api-key":[]}]}},"/api/v2/agent/chat":{"post":{"operationId":"AgentController_chat","summary":"Chat avec l'agent IA Bob","description":"Envoie un message à Bob, l'assistant IA Finkare.\nBob peut consulter les dossiers, analyser les situations et déclencher\ndes actions de recouvrement dans le respect des contraintes anti-harcèlement.\n\n**Scope requis :** `agent:chat`. Les actions d'écriture exigent en plus\nleur scope d'écriture (`debtors:write` ou `workflow:trigger`, même table que le MCP) ;\nsans ce scope, Bob ne propose ni n'exécute l'action.\n\n**Limites de débit :**\n- Starter : 60 req/min\n- Pro : 300 req/min\n- Enterprise : 1000 req/min","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentChatDto"}}}},"responses":{"200":{"description":"Réponse de Bob","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentChatResponse"}}}},"400":{"description":"Requête invalide (message manquant, conversationId invalide)"},"401":{"description":"Non authentifié","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Scope agent:chat requis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit dépassé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporairement indisponible"}},"tags":["Agent"],"security":[{"api-key":[]}]}},"/api/v2/agent/conversations":{"get":{"operationId":"AgentController_listConversations","summary":"Lister les conversations","description":"Récupère l'historique des conversations Bob pour votre compte.\n\n**Scope requis :** `agent:chat`","parameters":[{"name":"limit","required":false,"in":"query","description":"Nombre de résultats (max 100)","schema":{"default":20,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Offset pour pagination","schema":{"default":0,"type":"number"}}],"responses":{"200":{"description":"Liste des conversations"}},"tags":["Agent"],"security":[{"api-key":[]}]}},"/api/v2/agent/conversations/{id}":{"get":{"operationId":"AgentController_getConversation","summary":"Détails d'une conversation","description":"Récupère les messages d'une conversation spécifique.\n\n**Scope requis :** `agent:chat`","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la conversation (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"Détails de la conversation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationSummary"}}}},"400":{"description":"Identifiant de conversation invalide (UUID attendu)"},"404":{"description":"Conversation non trouvée"}},"tags":["Agent"],"security":[{"api-key":[]}]}},"/api/v1/api-keys":{"post":{"operationId":"ApiKeysController_createKey","summary":"Créer une API key","description":"Génère une clé dont les scopes et le tier sont au plus ceux de la clé appelante. Le secret est retourné UNE SEULE FOIS.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyDto"}}}},"responses":{"201":{"description":"API key créée"},"403":{"description":"Scope api_keys:manage requis ou escalade de privilèges refusée"}},"tags":["API Keys"],"security":[{"api-key":[]}]},"get":{"operationId":"ApiKeysController_listKeys","summary":"Lister les API keys","description":"Retourne les clés masquées de votre entreprise","parameters":[],"responses":{"200":{"description":"Liste des API keys"}},"tags":["API Keys"],"security":[{"api-key":[]}]}},"/api/v1/api-keys/{id}/rotate":{"post":{"operationId":"ApiKeysController_rotateKey","summary":"Rotation de clé","description":"Génère un nouveau secret pour une clé au plus aussi privilégiée que la clé appelante","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la clé à faire tourner","schema":{"type":"string"}}],"responses":{"200":{"description":"Nouvelle clé générée"}},"tags":["API Keys"],"security":[{"api-key":[]}]}},"/api/v1/api-keys/{id}":{"delete":{"operationId":"ApiKeysController_revokeKey","summary":"Révoquer une API key","description":"Désactive une clé (soft delete)","parameters":[{"name":"id","required":true,"in":"path","description":"ID de la clé à révoquer","schema":{"type":"string"}}],"responses":{"200":{"description":"Clé révoquée"}},"tags":["API Keys"],"security":[{"api-key":[]}]}},"/health":{"get":{"operationId":"HealthController_healthCheck","summary":"Health check","parameters":[],"responses":{"200":{"description":"Service is healthy"}},"tags":["Health"]}},"/health/detailed":{"get":{"operationId":"HealthController_detailedHealthCheck","summary":"Detailed health check (authentification requise)","parameters":[],"responses":{"200":{"description":"Detailed health information"},"401":{"description":"Non authentifié"}},"tags":["Health"]}},"/ready":{"get":{"operationId":"HealthController_readyCheck","summary":"Readiness check","parameters":[],"responses":{"200":{"description":"Service is ready"}},"tags":["Health"]}},"/webhooks/ar24":{"post":{"operationId":"WebhookProxyController_ar24","summary":"Webhook AR24 (proxy → lrar-service)","description":"Réception des notifications AR24 sur les LRAR (URL-encoded). La gateway vérifie l'IP source AR24 (liste blanche) avant de relayer (403 sinon) ; lrar-service re-vérifie l'IP et le schéma.","parameters":[],"responses":{"200":{"description":"Webhook traité par lrar-service"},"403":{"description":"IP source hors liste blanche AR24"}},"tags":["webhooks-inbound"]}},"/webhooks/smsfactor":{"post":{"operationId":"WebhookProxyController_smsfactor","summary":"Webhook SMSFactor (proxy → notification-service)","description":"Réception des rapports de livraison SMSFactor (DLR JSON). Forward vers notification-service. L'IP whitelist (51.159.7.123, 51.159.21.54) et le mapping status sont gérés par notification-service.","parameters":[],"responses":{"200":{"description":"DLR traité par notification-service"}},"tags":["webhooks-inbound"]}},"/webhooks/smsfactor/inbound":{"post":{"operationId":"WebhookProxyController_smsfactorInbound","summary":"Webhook SMSFactor : SMS entrant / réponse (proxy → notification-service)","description":"Réception des réponses SMS (JSON { from, message, ... }). Forward vers notification-service /webhooks/sms/smsfactor/inbound. IP whitelist + détection STOP/START (→ debtors.sms_opt_out) gérées par notification-service.","parameters":[],"responses":{"200":{"description":"Réponse traitée par notification-service"}},"tags":["webhooks-inbound"]}},"/webhooks/meta-whatsapp":{"post":{"operationId":"WebhookProxyController_metaWhatsApp","summary":"Webhook Meta WhatsApp (proxy → channel-service)","description":"Inbound DLR + messages from Meta Cloud API. Forward to channel-service, preserving X-Hub-Signature-256 for downstream HMAC verification.","parameters":[],"responses":{"200":{"description":"Webhook traité par channel-service"}},"tags":["webhooks-inbound"]},"get":{"operationId":"WebhookProxyController_metaWhatsAppVerify","summary":"Meta webhook verification challenge (GET)","parameters":[{"name":"hub.mode","required":true,"in":"query","schema":{"type":"string"}},{"name":"hub.verify_token","required":true,"in":"query","schema":{"type":"string"}},{"name":"hub.challenge","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["webhooks-inbound"]}},"/api/v1/gdpr/export":{"get":{"operationId":"GdprController_exportData","summary":"Exporter les données","description":"Exporte les données de votre entreprise au format JSON (RGPD Art. 20). Exclut les colonnes internes de scoring/ML.","parameters":[],"responses":{"200":{"description":"Export JSON"}},"tags":["GDPR"],"security":[{"api-key":[]}]}},"/api/v1/gdpr/erase":{"delete":{"operationId":"GdprController_requestErasure","summary":"Demander la suppression des données d'un débiteur","description":"Crée un ticket RGPD (Art. 17) et pseudonymise le débiteur ciblé si tous ses dossiers sont clôturés (sinon conservé : intérêt légitime). Scope d'administration gdpr:erase requis (jamais par défaut, jamais délégable, jamais via OAuth).","parameters":[{"name":"debtor_id","required":true,"in":"query","description":"UUID du débiteur à effacer","schema":{"type":"string"}}],"responses":{"202":{"description":"Demande de suppression traitée"},"400":{"description":"debtor_id absent ou invalide"},"403":{"description":"Scope gdpr:erase manquant"}},"tags":["GDPR"],"security":[{"api-key":[]}]}}},"info":{"title":"Finkare API","description":"\n# API de Recouvrement Intelligent\n\nBienvenue sur l'API Finkare, la plateforme de recouvrement amiable et judiciaire propulsée par l'intelligence artificielle.\n\nFinkare automatise l'intégralité du cycle de recouvrement : import des factures, orchestration multi-canal (email, SMS, LRAR, appels vocaux IA), négociation assistée, et suivi en temps réel via webhooks. L'IA garantit le respect des contraintes légales anti-harcèlement et optimise les taux de recouvrement.\n\n## Authentification\n\nDeux modes d'authentification sont supportés :\n\n### API Key (recommandé pour les intégrations serveur-à-serveur)\n\nIncluez votre clé dans le header `X-API-Key` :\n\n```bash\ncurl -H \"X-API-Key: fk_live_xxx\" https://api.finkare.io/api/v1/invoices\n```\n\n### OAuth 2.1 (recommandé pour les applications tierces)\n\nSupporté avec les grant types `client_credentials`, `authorization_code` (+ PKCE) et `refresh_token`. Consultez la section **OAuth** pour les détails.\n\n## Rate Limiting\n\nLes limites varient selon votre tier de souscription :\n\n| Tier | Requêtes/min | Requêtes/jour | Import en masse |\n|------|-------------|---------------|-----------------|\n| Starter | 60 | 10 000 | 100 factures/requête |\n| Pro | 300 | 100 000 | 100 factures/requête |\n| Enterprise | 1 000+ | Illimité | 100 factures/requête |\n\nLes headers de réponse `X-RateLimit-Limit`, `X-RateLimit-Remaining` et `X-RateLimit-Reset` indiquent votre consommation en temps réel.\n\n## Idempotence\n\nLes endpoints de création (POST) supportent le header `Idempotency-Key` pour éviter les doublons en cas de retry réseau.\n\n## Format des réponses\n\nToutes les réponses suivent un format standardisé :\n\n```json\n{\n  \"success\": true,\n  \"data\": { ... },\n  \"requestId\": \"req_abc123\",\n  \"timestamp\": \"2026-04-08T10:30:00Z\"\n}\n```\n\nEn cas d'erreur, le champ `error` contient un code machine et un message lisible :\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"AUTH_002\",\n    \"message\": \"Invalid API key. Please check your credentials.\"\n  },\n  \"requestId\": \"req_abc123\",\n  \"timestamp\": \"2026-04-08T10:30:00Z\"\n}\n```\n\n## Webhooks\n\nRecevez des notifications en temps réel pour tous les événements de recouvrement (paiements, changements de statut, actions IA). Les payloads sont signés via HMAC-SHA256 pour garantir l'authenticité.\n\n## Support\n\n- **Documentation complète** : [docs.finkare.io](https://docs.finkare.io)\n- **Email** : support@finkare.io\n- **Statut de la plateforme** : [status.finkare.io](https://finkare.openstatus.dev)\n    ","version":"1.0.0","contact":{"name":"Finkare Support","url":"https://finkare.io","email":"support@finkare.io"},"license":{"name":"Proprietary","url":"https://finkare.io/terms"}},"tags":[{"name":"Invoices","description":"Création, import et suivi des factures à recouvrer. Supporte l'import unitaire et en masse (jusqu'à 100 factures par requête)."},{"name":"Workflow","description":"Pilotage du workflow de recouvrement IA : démarrage, pause, reprise, escalade et consultation de l'historique des actions."},{"name":"Payments","description":"Consultation des paiements reçus (totaux et partiels), avec filtres par statut, période et facture associée."},{"name":"Debtors","description":"Gestion des débiteurs : création, mise à jour, consultation du score de solvabilité IA et des factures associées."},{"name":"Webhooks","description":"Configuration des webhooks pour recevoir des notifications en temps réel sur les événements de recouvrement (paiements, changements de statut, actions IA)."},{"name":"Agent","description":"Interface conversationnelle avec Bob, l'assistant IA Finkare. Permet de piloter le recouvrement en langage naturel."},{"name":"API Keys","description":"Gestion du cycle de vie des clés API : création, rotation, révocation et listing."},{"name":"OAuth","description":"Authentification OAuth 2.1 avec support Client Credentials, Authorization Code + PKCE et Refresh Token."},{"name":"OAuth Discovery","description":"Endpoints de découverte OAuth (RFC 8414, RFC 9728) pour l'intégration automatique avec les outils IA et MCP."},{"name":"Health","description":"Endpoints de santé, readiness et métriques pour le monitoring de la plateforme."}],"servers":[{"url":"https://api.finkare.io","description":"Production"},{"url":"https://api-sandbox.finkare.io","description":"Sandbox"},{"url":"http://localhost:3000","description":"Local Development"}],"components":{"securitySchemes":{"api-key":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Votre API key Finkare (préfixe fk_live_ en production, fk_test_ en sandbox)"},"oauth2":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Access token JWT obtenu via le endpoint OAuth /oauth/token"}},"schemas":{"RegisterClientDto":{"type":"object","properties":{"client_name":{"type":"string","description":"Nom lisible du client","example":"Claude"},"redirect_uris":{"description":"URIs de redirection (doivent appartenir aux hotes autorises)","example":["https://claude.ai/api/mcp/auth_callback"],"type":"array","items":{"type":"string"}},"grant_types":{"description":"Grant types souhaites","example":["authorization_code","refresh_token"],"type":"array","items":{"type":"string"}},"response_types":{"description":"Response types souhaites","example":["code"],"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","description":"Methode d auth au token endpoint","example":"none","enum":["none","client_secret_basic","client_secret_post"]},"scope":{"type":"string","description":"Scopes demandes (separes par espaces)","example":"debtors:read invoices:read"},"client_uri":{"type":"string","description":"URL de la home page du client"},"logo_uri":{"type":"string","description":"URL du logo du client"}},"required":["redirect_uris"]},"OAuthErrorDto":{"type":"object","properties":{"error":{"type":"string","description":"Code erreur OAuth","example":"invalid_client"},"error_description":{"type":"string","description":"Description","example":"Client authentication failed"}},"required":["error","error_description"]},"TokenRequestDto":{"type":"object","properties":{"grant_type":{"type":"string","description":"Grant type OAuth 2.0","example":"client_credentials","enum":["client_credentials","authorization_code","refresh_token"]},"client_id":{"type":"string","description":"Client ID (si non fourni via Basic Auth)","example":"fk_client_abc123"},"client_secret":{"type":"string","description":"Client Secret (si non fourni via Basic Auth)","example":"fk_secret_xyz789"},"scope":{"type":"string","description":"Scopes demandés (séparés par espaces)","example":"invoices:read payments:read workflow:read"},"code":{"type":"string","description":"Code d'autorisation (requis pour grant_type=authorization_code)","example":"auth_code_abc123xyz"},"redirect_uri":{"type":"string","description":"URI de redirection (requis pour grant_type=authorization_code)","example":"https://partner.com/callback"},"code_verifier":{"type":"string","description":"PKCE code verifier (requis pour grant_type=authorization_code)","example":"dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"},"refresh_token":{"type":"string","description":"Refresh token (requis pour grant_type=refresh_token)","example":"fk_rt_abc123xyz789"}},"required":["grant_type"]},"TokenResponseDto":{"type":"object","properties":{"access_token":{"type":"string","description":"Access token JWT","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."},"token_type":{"type":"string","description":"Type de token (toujours Bearer)","example":"Bearer"},"expires_in":{"type":"number","description":"Durée de validité en secondes","example":3600},"scope":{"type":"string","description":"Scopes accordés (séparés par espaces)","example":"invoices:read payments:read"},"refresh_token":{"type":"string","description":"Refresh token (retourné pour les grants authorization_code et refresh_token)","example":"fk_rt_abc123xyz789"}},"required":["access_token","token_type","expires_in","scope"]},"ConsentDto":{"type":"object","properties":{"client_id":{"type":"string","description":"Client ID du partenaire","example":"fk_client_abc123"},"redirect_uri":{"type":"string","description":"URI de redirection enregistrée","example":"https://partner.com/callback"},"scope":{"type":"string","description":"Scopes approuvés par l'utilisateur","example":"invoices:read debtors:read"},"state":{"type":"string","description":"State anti-CSRF (retourné tel quel)","example":"random-state-123"},"code_challenge":{"type":"string","description":"PKCE code challenge (SHA-256)","example":"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"},"user_id":{"type":"string","description":"ID de l'utilisateur qui accorde le consentement","example":"usr_a1b2c3d4"},"company_id":{"type":"string","description":"ID de l'entreprise de l'utilisateur","example":"comp_x1y2z3w4"}},"required":["client_id","redirect_uri","scope","state","code_challenge","user_id","company_id"]},"DebtorInfoDto":{"type":"object","properties":{"id":{"type":"string","description":"ID débiteur existant (si connu)","example":"b7e3c2a1-8f4d-4e6a-9c1b-2d3e4f5a6b7c"},"name":{"type":"string","description":"Nom ou raison sociale du débiteur","example":"Dupont & Fils SARL"},"email":{"type":"string","description":"Email de contact principal","example":"comptabilite@dupont-fils.fr"},"phone":{"type":"string","description":"Numéro de téléphone (format international)","example":"+33612345678"},"siret":{"type":"string","description":"Numéro SIRET (14 chiffres)","example":"44306184100047"},"address":{"type":"string","description":"Adresse postale","example":"12 rue de la Paix"},"city":{"type":"string","description":"Ville","example":"Paris"},"postalCode":{"type":"string","description":"Code postal","example":"75002"},"country":{"type":"string","description":"Code pays ISO 3166-1 alpha-2","example":"FR","default":"FR"}},"required":["name","email"]},"CreateInvoiceDto":{"type":"object","properties":{"invoiceNumber":{"type":"string","description":"Numéro de facture","example":"FAC-2026-001"},"amountCents":{"type":"number","description":"Montant total TTC en centimes","example":150000},"currency":{"type":"string","description":"Devise","example":"EUR","default":"EUR"},"issueDate":{"type":"string","description":"Date d'émission","example":"2026-01-15"},"dueDate":{"type":"string","description":"Date d'échéance","example":"2026-02-15"},"description":{"type":"string","description":"Description","example":"Prestation de conseil janvier 2026"},"debtor":{"description":"Informations du débiteur","allOf":[{"$ref":"#/components/schemas/DebtorInfoDto"}]},"metadata":{"type":"object","description":"Metadata personnalisées"}},"required":["invoiceNumber","amountCents","issueDate","dueDate","debtor"]},"BulkImportInvoicesDto":{"type":"object","properties":{"invoices":{"description":"Liste des factures à importer","type":"array","items":{"$ref":"#/components/schemas/CreateInvoiceDto"}},"autoStartWorkflow":{"type":"boolean","description":"Démarrer automatiquement le workflow","default":true}},"required":["invoices"]},"TriggerWorkflowDto":{"type":"object","properties":{"action":{"type":"string","description":"Action à déclencher sur le workflow","enum":["start","pause","resume","cancel","escalate"],"example":"pause"},"reason":{"type":"string","description":"Motif de l'action (recommandé pour la traçabilité)","example":"Négociation en cours avec le débiteur"}},"required":["action"]},"CreateWebhookDto":{"type":"object","properties":{"url":{"type":"string","description":"URL de destination","example":"https://api.example.com/webhooks/finkare"},"events":{"type":"array","description":"Événements à écouter","items":{"type":"string","enum":["invoice.created","invoice.updated","invoice.status_changed","payment.received","payment.failed","workflow.started","workflow.action_triggered","workflow.completed","lrar.sent","lrar.delivered","debtor.contacted","debt.paid","cascade.action","judicial.started","anr.created"]}},"description":{"type":"string","description":"Description","example":"Webhook principal production"},"enabled":{"type":"boolean","description":"Actif","default":true}},"required":["url","events"]},"UpdateWebhookDto":{"type":"object","properties":{"url":{"type":"string","description":"URL de destination"},"events":{"description":"Événements à écouter","type":"array","items":{"type":"string"}},"description":{"type":"string","description":"Description"},"enabled":{"type":"boolean","description":"Actif"}}},"AgentChatDto":{"type":"object","properties":{"message":{"type":"string","description":"Message à envoyer à Bob","example":"Combien de factures impayées ai-je en ce moment ?"},"conversationId":{"type":"string","description":"ID de conversation pour continuer un échange","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"context":{"type":"object","description":"Contexte additionnel pour l'agent","example":{"page":"dashboard","locale":"fr"}}},"required":["message"]},"AgentChatResponseData":{"type":"object","properties":{"text":{"type":"string","description":"Réponse de Bob","example":"Vous avez 5 factures impayées pour un total de 12 500 €."},"toolsCalled":{"description":"Outils utilisés","example":["list_invoices","get_company_dashboard"],"type":"array","items":{"type":"string"}},"conversationId":{"type":"string","description":"ID de conversation","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"}},"required":["text"]},"AgentChatResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/AgentChatResponseData"},"requestId":{"type":"string","example":"req_abc123"},"timestamp":{"type":"string","example":"2026-04-03T10:00:00.000Z"}},"required":["success","data","requestId","timestamp"]},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","example":{"code":"AUTH_002","message":"Scope agent:chat required"}}},"required":["success","error"]},"ConversationSummary":{"type":"object","properties":{"id":{"type":"string","description":"ID de la conversation"},"lastMessage":{"type":"string","description":"Dernier message"},"messageCount":{"type":"number","description":"Nombre de messages"},"createdAt":{"type":"string","description":"Date de création"},"updatedAt":{"type":"string","description":"Dernière mise à jour"}},"required":["id","lastMessage","messageCount","createdAt","updatedAt"]},"CreateApiKeyDto":{"type":"object","properties":{"name":{"type":"string","description":"Nom de la clé","example":"Production Key"},"scopes":{"description":"Scopes autorisés (sous-ensemble des scopes de la clé appelante)","example":["invoices:read","payments:read"],"type":"array","items":{"type":"string"}},"ipWhitelist":{"description":"Liste blanche d'IPs","example":["203.0.113.0/24"],"type":"array","items":{"type":"string"}},"tier":{"type":"string","description":"Tier de tarification (au plus celui de la clé appelante)","enum":["starter","pro","enterprise"],"default":"starter"}},"required":["name","scopes"]}}}}