Authentification16 min

Serveur MCP Billabex

Connecter un outil IA à Billabex par le Model Context Protocol (MCP), avec OAuth 2.1.

Billabex expose un serveur Model Context Protocol (MCP), pour qu’un outil IA accède aux données Billabex avec OAuth 2.1. Ce guide décrit la découverte, l’autorisation, les outils et ressources disponibles, et la façon de s’y connecter.

L’endpoint MCP

Le serveur MCP utilise le transport Streamable HTTP, sans état :

POST [baseURL]/mcp

Le parcours de découverte OAuth

Un client MCP suit la RFC 9728 (métadonnées de ressource protégée) et la RFC 8414 (métadonnées du serveur d’autorisation OAuth) :

  1. appeler POST /mcp sans jeton ;
  2. le serveur répond avec un WWW-Authenticate portant resource_metadata et scope ;
  3. récupérer l’URL des métadonnées de ressource pour découvrir les authorization_servers et les scopes_supported de /mcp ;
  4. récupérer les métadonnées du serveur d’autorisation pour localiser les endpoints d’autorisation et d’enregistrement.

Exemple de réponse 401

Le serveur MCP renvoie :

WWW-Authenticate: Bearer resource_metadata="[baseURL]/.well-known/oauth-protected-resource", scope="mcp:read mcp:write"

Métadonnées de ressource protégée, par chemin

Pour /mcp, demandez :

[baseURL]/.well-known/oauth-protected-resource/mcp

La réponse contient :

{
  "resource": "[baseURL]",
  "authorization_servers": ["[baseURL]"],
  "scopes_supported": ["mcp:read", "mcp:write"],
  "bearer_methods_supported": ["header"]
}

Métadonnées du serveur d’autorisation

GET [baseURL]/.well-known/oauth-authorization-server

Renvoie l’authorization_endpoint, le token_endpoint et le registration_endpoint nécessaires à OAuth 2.1 avec PKCE.

Scopes

MCP utilise deux scopes :

Scope Accès Description
mcp:read Lecture Lister et consulter factures, comptes et communications.
mcp:write Écriture Créer, modifier et supprimer.

Consentement

Si une requête d’autorisation omet le paramètre scope, Billabex applique par défaut mcp:read mcp:write aux clients MCP.

Détails du protocole

  • Transport : Streamable HTTP, en mode sans état.
  • Authentification : en-tête Authorization: Bearer <jeton>, obligatoire.
  • Limite de débit : 300 requêtes par minute et par jeton, en fenêtre glissante.
  • En-tête CORS : un client peut envoyer l’en-tête Mcp-Protocol-Version.

Ressources

Les ressources MCP fournissent des métadonnées qu’un outil IA peut lire pour comprendre ce que Billabex sait faire.

URI Description
billabex://about Présentation de la plateforme, proposition de valeur, fonctions clés
billabex://concepts Entités, statuts, relations et règles métier
billabex://workflow Le parcours de suivi des paiements pas à pas, tâches comprises

Elles aident un agent IA à comprendre :

  • About : ce qu’est Billabex, et comment il aide une entreprise à encaisser ses créances ;
  • Concepts : le modèle de domaine, factures, comptes, soldes clients, communications et tâches ;
  • Workflow : le parcours standard, de la facture échue jusqu’à l’encaissement.

Prompts

Les prompts MCP sont des modèles orientés métier, pour les tâches courantes d’un agent IA. Contrairement aux outils, ils utilisent des paramètres lisibles par un humain (nom de compte, nom d’organisation) plutôt que des identifiants techniques.

Prompt Paramètres Cas d’usage
financial-snapshot organizationName?, period? (7/30/tous les jours) Vue des encours, principaux comptes, trésorerie
account-360 accountName, organizationName? Synthèse complète d’un compte : factures, communications, tâches
daily-plan organizationName? Plan d’action du jour : tâches, rappels, suivis
daily-digest organizationName? Résumé de l’activité et des évolutions du jour
communication-intelligence accountName?, organizationName? Réponses récentes, promesses de paiement, comptes ayant répondu sans payer
risk-report organizationName? Comptes à risque, comptes silencieux, comptes sans contact
silent-accounts organizationName?, period? (30/90/tous) Comptes n’ayant jamais répondu à une relance par email
blocked-accounts organizationName? Comptes dont les emails rebondissent ou sont signalés comme indésirables
inbound-email-digest organizationName?, period? (7/30/90 jours) Synthèse des emails entrants sur une période récente

Comment fonctionne un prompt

  1. L’utilisateur donne des noms : vous appelez le prompt avec un nom de compte comme « Acme Corp » plutôt qu’un UUID
  2. L’agent résout les identifiants : le prompt lui demande d’utiliser list-accounts et list-organizations pour trouver les identifiants correspondants
  3. L’agent collecte les données : il appelle plusieurs outils pour rassembler ce qui est pertinent
  4. L’agent présente le résultat : formaté naturellement, sans exposer d’identifiant technique

Exemple : financial-snapshot

{
  "name": "financial-snapshot",
  "arguments": {
    "organizationName": "My Company",
    "period": "30days"
  }
}

L’agent va :

  1. utiliser list-organizations pour trouver « My Company » ;
  2. utiliser list-customer-balances pour obtenir les encours ;
  3. utiliser list-invoices pour trouver les factures à échéance proche ;
  4. présenter une vue d’ensemble formatée de votre situation financière.

Référence des outils

Les outils sont groupés par domaine. Les outils de lecture exigent mcp:read, ceux d’écriture mcp:write.

Les sorties portent des champs lisibles par un humain, comme displayName et summary quand ils existent. Préférez-les pour vos réponses à l’utilisateur, et gardez les identifiants pour les appels d’outils suivants.

Tous les outils portent des annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) qui aident l’agent à comprendre leur comportement.

Facturation

Outil Accès Description
list-invoices Lecture Lister les factures avec le mode de paiement du compte (paginé).
get-aging-balance Lecture Totaux nets de la balance âgée par devise.
list-aging-balance-by-account Lecture Ventilation nette et paginée par compte et par devise.
get-invoice Lecture Consulter une facture par identifiant, ou par numéro dans un compte ou une organisation.
create-invoice Écriture Créer une facture avec un fichier en base64 et un sourceId facultatif.
update-invoice-paid-amount Écriture Modifier le montant payé d’une facture.
update-invoice-payment-schedule Écriture Remplacer ou retirer l’échéancier d’une facture.
update-invoice-due-date Écriture Corriger la date d’échéance d’une facture déjà émise.
delete-invoice Écriture Supprimer une facture.
list-accounts Lecture Lister les comptes avec leur type, mode de paiement et identifiant source.
get-account Lecture Consulter le type, les détails et les contacts d’un compte.
get-account-financial-overview Lecture Expliquer le solde d’un compte et lister chaque échéance de facture.
create-account Écriture Créer un compte, avec type et mode de paiement facultatifs.
update-account Écriture Modifier type, nom, devise, adresse ou mode de paiement d’un compte.
delete-account Écriture Supprimer un compte client.
list-contacts Lecture Lister les contacts d’un compte.
get-contact Lecture Consulter un contact précis.
create-contact Écriture Ajouter un contact à un compte.
update-contact Écriture Modifier un contact.
delete-contact Écriture Retirer un contact.
upsert-contact Écriture Créer ou mettre à jour un contact par correspondance email ou nom.
set-contact-enabled Écriture Activer ou désactiver un contact sur un compte.
list-credit-notes Lecture Lister les avoirs avec le mode de paiement du compte (paginé).
get-credit-note Lecture Consulter un avoir, par identifiant ou par numéro.
create-credit-note Écriture Créer un avoir, avec un sourceId facultatif.
update-credit-note-refunded-amount Écriture Enregistrer un remboursement partiel ou total.
delete-credit-note Écriture Supprimer un avoir.
apply-credit-allocation Écriture Imputer un avoir sur une facture.
remove-credit-allocation Écriture Retirer une imputation d’avoir.
add-account-tags Écriture Attacher des étiquettes existantes à un compte.
remove-account-tag Écriture Détacher une étiquette d’un compte.
link-account-source Écriture Relier une source externe à un compte.
update-account-source Écriture Mettre à jour la date de dernière synchronisation d’une source.
unlink-account-source Écriture Délier une source externe.
check-account-bodacc Écriture Vérifier les procédures collectives et proposer des SIREN candidats.

update-invoice-payment-schedule reçoit l’UUID d’une facture, le tableau complet installments et un skipConfirmation facultatif. Chaque échéance porte une date calendaire et un montant positif. Envoyez un tableau vide pour retirer l’échéancier. La confirmation est demandée par défaut ; un client automatisé peut poser skipConfirmation: true.

update-invoice-due-date reçoit l’UUID d’une facture, une date dueDate et un skipConfirmation facultatif. L’échéance ne peut pas précéder la date d’émission. Réécrire la même date ne change rien : un script de correction après import peut donc être rejoué sans risque. Déplacer l’échéance recalcule le retard et replanifie les relances à venir ; une relance déjà modifiée à la main reste intacte.

Un contact désactivé n’est jamais sollicité spontanément par l’agent. Le réactiver est une décision humaine : set-contact-enabled ne devrait donc pas servir à annuler une désactivation que le client a demandée.

create-contact, update-contact et upsert-contact prennent une liste phones d’objets { number, countryCode? }. Un numéro commençant par + ou 00 porte son propre indicatif ; tout autre numéro est national et exige countryCode (ISO 3166-1 alpha-2), Billabex ne devinant jamais un pays. Les contacts sont renvoyés avec phones: [{ number, type, country, origin }], où type (Mobile, Landline ou Unknown) et country sont déduits du numéro lui-même et en lecture seule. Écrire phones ne remplace que ce qu’une personne a saisi, jamais les numéros apportés par un connecteur (origin: "Connector") ; omettez le champ pour ne rien toucher, envoyez [] pour effacer les numéros manuels. Seul un mobile de France (FR) ou de Guyane (GF) peut recevoir un SMS. Voyez Contacts pour le modèle complet.

Les documents créés par create-invoice et create-credit-note portent le canal Mcp, distinct du PublicApi que pose l’API REST. Ils peuvent vivre dans une organisation par ailleurs synchronisée avec un ou plusieurs connecteurs : voyez Sources de compte pour comprendre pourquoi la source d’un compte ne dit jamais d’où vient l’un de ses documents.

Les deux outils de création prennent aussi un sourceId facultatif, votre propre identifiant pour le document. Il est figé à la création, renvoyé sur les factures et les avoirs aux côtés de connectionId, unique dans l’organisation (une recréation avec la même valeur est refusée plutôt que dupliquée), et filtrable sur list-invoices et list-credit-notes avec is, isAnyOf, isEmpty et isNotEmpty uniquement, parce qu’il est sensible à la casse. Les numéros de documents, eux, sont uniques par compte : get-invoice et get-credit-note répondent exactement quand on leur donne accountId plus number, tandis qu’une recherche par organizationId plus number peut répondre n’importe lequel de plusieurs homonymes.

create-contact, update-contact et upsert-contact peuvent renvoyer un tableau warnings à côté du contact quand une partie de l’écriture n’a pas été retenue : un fullName ou une language qu’une personne possède et qu’une synchronisation automatisée a tenté d’écraser (MANUALLY_SET), ou un numéro qu’une synchronisation a envoyé sans qu’il puisse être normalisé (UNPARSEABLE). Le reste de l’écriture a bien été appliqué. Lisez le tableau plutôt que de vous fier à un succès nu.

list-invoices et list-credit-notes renvoient accountPaymentMethod valant DIRECT_DEBIT, BANK_TRANSFER ou null. La valeur est lue sur le compte au moment de la requête : modifier le compte ne demande donc pas de mettre à jour chaque document.

Pour un compte relié à un connecteur, list-accounts renvoie la référence client du connecteur dans source.sourceId. Le même champ reste disponible sur lastUnlinkedSource après un détachement. Aucun appel à get-account n’est nécessaire pour rapprocher un compte listé du client externe.

list-accounts, list-credit-notes, get-account, get-invoice et get-credit-note renvoient readOnlyReason : null quand l’enregistrement accepte les écritures, sinon le connecteur qui les écraserait. Lisez-le plutôt que de déduire un verdict de channel ou de source. list-invoices ne le porte pas, sa projection ne pouvant pas distinguer une facture historique ; appelez get-invoice quand vous avez besoin du verdict pour l’une de ces lignes.

Les outils de compte exposent accountType valant Professional, Consumer ou Unknown. create-account et update-account acceptent le même champ. L’omettre à la création fait déduire Professional d’un identifiant légal ; sinon le compte reste Unknown. Un connecteur standard contrôle la valeur et ne peut pas être surchargé par MCP ; une source Custom reste modifiable. Les comptes Consumer ne sont pas vérifiés au BODACC, tandis que leur SIREN et leur numéro de TVA, s’ils existent, restent accessibles par l’API.

Les deux outils acceptent aussi paymentMethod valant DIRECT_DEBIT, BANK_TRANSFER ou null. L’omettre ou envoyer null à la création laisse le mode de paiement inconnu.

Un compte sous procédure collective porte aussi ce dont un créancier a besoin pour agir : bodaccNoticeDate (date de publication de l’annonce, point de départ du délai de deux mois pour déclarer sa créance), bodaccJudgmentDate (le jugement lui-même, généralement quelques jours plus tôt), bodaccPractitioner et bodaccNoticeUrl. Pour tout délai, lisez bodaccNoticeDate : c’est la date de publication qui compte, pas celle du jugement.

bodaccPractitioner est le mandataire auprès duquel déclarer la créance, sous forme d’une ligne de texte libre citée de l’annonce : un cabinet, souvent une personne, et une adresse postale. Le BODACC ne porte aucun champ structuré pour cela et ne publie jamais d’email ni de téléphone : rien de plus précis ne peut donc être renvoyé, et le champ est nul quand l’annonce formule la désignation d’une façon qui ne peut pas être analysée. bodaccNoticeUrl pointe l’annonce elle-même et sert de repli dans ce cas. Les deux sont nuls tant qu’aucune procédure n’est ouverte, et pour une société radiée après une liquidation clôturée pour insuffisance d’actif, où plus aucune créance ne peut être déclarée.

check-account-bodacc exige mcp:write et prend un accountId plus un siren facultatif (SIREN à 9 chiffres ou SIRET à 14). Sans identifiant confirmé, il renvoie les candidats proposés sans en adopter aucun : une recherche élargie n’établit jamais une identité à elle seule. Confirmez l’identifiant sur un document qui nomme le débiteur, ou sur sa fiche client, avant de l’envoyer.

L’équivalent REST est POST /api/public/v1/accounts/{accountId}/bodacc-check, avec le scope accounts:all et un corps valant {} ou {"siren":"482309382"}. La vérification est aussi disponible pour les comptes gérés par connecteur.

La réponse porte siren, status, checkedAt, companyName, noticeUrl et candidates, une liste d’objets {siren,name,address}. Le statut est nul quand le compte sort du périmètre des sociétés françaises. L’appel peut enregistrer une vérification, suspendre les relances et ouvrir une tâche : ce n’est pas une lecture. Une suspension légale ou manuelle reste en place, même quand l’identification change.

Quand une procédure a été signalée mais que le SIREN reste inconnu, une tâche le demande. Elle se lit et se traite par les outils de tâches habituels. Clore cette tâche ne renseigne pas le SIREN et ne lève pas la suspension légale.

Suivi des paiements

Outil Accès Description
list-customer-balances Lecture Lister les encours clients (paginé).
get-customer-balance Lecture Détail d’un solde, avec ses factures et ses avoirs.
list-communications Lecture Lister emails entrants et sortants d’un coup, filtrables côté serveur.
list-silent-accounts Lecture Lister les comptes relancés au moins une fois et qui n’ont jamais répondu.
list-outgoing-communications Lecture Lister les emails de relance sortants (paginé).
get-outgoing-communication Lecture Détail d’une communication sortante.
list-outgoing-communications-by-account Lecture Lister les communications sortantes d’un compte.
update-outgoing-communication Écriture Modifier un email sortant planifié.
send-outgoing-communication Écriture Envoyer un email immédiatement au nom de l’agent, à des destinataires libres.
preview-outgoing-message Lecture Prévisualiser et chiffrer un SMS ou un courrier, sans renvoyer de PDF.
send-outgoing-message Écriture Envoyer un message payant, avec une clé d’idempotence obligatoire.
get-outgoing-message Lecture Consulter un SMS ou un courrier envoyé et son état de livraison.
preview-outgoing-letter Lecture Alias déprécié pour la prévisualisation de courrier.
send-outgoing-letter Écriture Alias déprécié pour l’envoi de courrier.
list-incoming-communications Lecture Lister les communications entrantes, c’est-à-dire les réponses.
get-incoming-communication Lecture Détail d’une communication entrante.
list-incoming-communications-by-account Lecture Lister les communications entrantes d’un compte.
get-account-dunning-status Lecture Savoir si un compte est relancé, et l’unique raison pour laquelle il ne l’est pas.
pause-account-dunning Écriture Suspendre les relances avec un motif factuel, ou jusqu’à une date.
resume-account-dunning Écriture Lever les suspensions levables par un humain, et renvoyer les protections restantes.

get-account-dunning-status répond à la question « pourquoi rien ne part sur ce compte ». Son silenceReason nomme l’unique cause, classée une seule fois côté serveur, de sorte que la réponse soit la même que celle de la webapp et que celle de GET /accounts/{accountId}/dunning sur l’API REST : suspended, puis blocking-task, puis below-minimum-amount, puis connector-sync-stale, puis first-reminder-delay, et null quand rien ne retient le compte. Lisez-le plutôt que de classer vous-même les indicateurs individuels.

La même réponse renvoie collectionStatus : Open, Settled, WrittenOff ou NoInvoice. resume-account-dunning accepte un reason facultatif ; passez written-off pour rouvrir un compte passé en perte sans lever aucune autre suspension. list-accounts peut filtrer sur collectionStatus, même si ce champ dérivé n’est pas ajouté à chaque élément de la liste.

list-communications lit une projection déjà jointe, et filtre, trie et pagine côté serveur. Préférez-le à la pagination séparée des listes entrantes et sortantes. Au-delà de ses propres arguments accountId, type et de date, il prend les conditions filters décrites plus bas dans Filtrer les listes : direction, status, deliveryStatus, accountName, contactName, subject et date.

Une communication survit au compte auquel elle appartenait. Quand ce compte a été supprimé, l’élément porte encore son accountId et son accountFullName, et accountDeletedAt donne l’instant de la suppression. Traitez un accountDeletedAt non nul comme « ne pas tenter de lire ce compte » : les outils de compte répondent comme s’il n’avait jamais existé. Il vaut null sur tout compte encore présent.

Email

Outil Accès Description
list-emails Lecture Lister tous les emails, entrants et sortants.
list-incoming-emails Lecture Lister les emails entrants (paginé).
get-incoming-email Lecture Consulter un email entrant, corps simplifié.
list-outgoing-emails Lecture Lister les emails sortants (paginé).
get-outgoing-email Lecture Consulter un email sortant, corps simplifié.

Plateforme

Outil Accès Description
list-organizations Lecture Lister les organisations de l’utilisateur, avec leurs crédits.
get-organization Lecture Détail d’une organisation, solde de crédits compris.
update-organization Écriture Modifier le nom ou le domaine email d’une organisation.
update-organization-settings Écriture Modifier les délais de relance et le seuil de relance.
set-organization-logo Écriture Poser ou retirer le logo de l’organisation (image en base64).
list-organization-members Lecture Lister les membres et les métadonnées de leur photo de profil.
remove-organization-member Écriture Retirer un membre d’une organisation.
set-my-avatar Écriture Poser ou remplacer la photo de profil de l’utilisateur authentifié.
remove-my-avatar Écriture Retirer la photo de profil de l’utilisateur authentifié.
get-my-notification-preferences Lecture Lire les préférences de notification de l’utilisateur authentifié.
set-my-notification-preferences Écriture Modifier la fréquence du digest ou l’abonnement à la newsletter.
create-organization-invitation Écriture Inviter un utilisateur. Une invitation expire au bout de 7 jours.
cancel-organization-invitation Écriture Annuler une invitation en attente.
list-tags Lecture Lister les étiquettes de l’organisation et les étiquettes standard.
create-tag Écriture Créer une étiquette appartenant à l’organisation.

Les deux outils d’organisation renvoient credits, le solde prépayé qui paie les relances par SMS et par courrier. Voyez Crédits plus bas.

Ils renvoient aussi les deux règles effectives de première relance, firstReminderDelayForDirectDebit et firstReminderDelayForBankTransfer, chacune { days, direction } avec direction valant BEFORE ou AFTER l’échéance, ou null quand ni surcharge ni firstReminderDelayDays n’est posé. update-organization-settings les écrit sous les mêmes noms : une clé absente laisse ce mode tel quel, un null explicite enregistre que le mode n’a pas de règle propre et retombe sur firstReminderDelayDays. Un compte dont le mode de paiement est inconnu suit firstReminderDelayDays seul, jamais l’une de ces deux règles.

Les emails générés regroupent les montants par facture strictement inférieurs au seuil converti dans la devise du compte. Le total et les pièces justificatives restent inchangés. Lorsque le total du groupe reste sous le seuil, il ne durcit pas le ton de la relance. Cette règle utilise le même réglage depuis la webapp, l’API publique et le MCP.

Ils renvoient aussi le seuil de relance sous forme de paire, minimumDunningAmount et minimumDunningAmountCurrency : un compte est encore relancé quand son solde égale le montant, et ne l’est plus quand il est strictement en dessous, le solde étant d’abord converti dans la devise du seuil. Une nouvelle organisation démarre à 2 EUR. Une devise null à côté d’un montant non nul est un réglage historique, écrit avant l’existence des devises : le montant est alors comparé dans la devise propre à chaque compte.

update-organization-settings écrit la paire :

{ "minimumDunningAmount": 5, "minimumDunningAmountCurrency": "USD" }
  • les deux clés ensemble posent la paire ;
  • le montant seul conserve la devise déjà posée, ou conserve la comparaison historique s’il n’y en a pas ;
  • { "minimumDunningAmount": null, "minimumDunningAmountCurrency": null } retire le seuil ;
  • une devise sans son montant est refusée, comme un montant non nul avec une devise explicitement null.

Ils renvoient aussi logo, l’image téléversée pour l’organisation, ou null. null ne signifie pas qu’aucun logo n’est affiché : sans image téléversée, un logo est dérivé du domaine email de l’organisation à l’affichage, et rien n’est stocké. set-organization-logo prend un PNG, un JPEG ou un WebP en base64 jusqu’à 2 Mo, ou file: null pour le retirer. C’est la vraie signature du fichier qui est vérifiée, pas le type déclaré : un SVG est donc refusé.

Tâches

Outil Accès Description
list-account-tasks Lecture Rechercher les tâches de l’organisation (paginé).
get-account-task Lecture Détail d’une tâche et format de réponse attendu.
cancel-account-task Écriture Annuler une tâche, avec un reason facultatif.
set-pending-account-task Écriture Mettre une tâche de côté, avec une date pendingUntil facultative. Sans elle, elle revient au bout de 30 jours.
add-account-task-text-interaction Écriture Ajouter une réponse texte à une tâche.
add-account-task-structured-interaction Écriture Ajouter une réponse structurée à une tâche.

Le contrat de list-account-tasks a changé. Il exigeait autrefois un accountId, renvoyait d’un coup toutes les tâches actives de ce compte et ne paginait jamais. Il prend désormais organizationId, accountId devenant facultatif, renvoie les tâches de tout statut par défaut, et pagine. Son ancien argument type est devenu une condition de filtre type. Les éléments gardent leur forme complète, fil d’interactions thread compris : la projection sélectionne la page, puis chaque ligne est réhydratée depuis son agrégat.

Filtrer les listes

list-accounts, list-invoices, list-credit-notes, list-communications et list-account-tasks prennent un argument filters : un tableau de conditions, chacune { field, operator, value } ou { field, operator, values }.

{
  "organizationId": "123e4567-e89b-12d3-a456-426614174000",
  "filters": [
    {
      "field": "status",
      "operator": "isAnyOf",
      "values": ["Overdue", "Issued"]
    },
    { "field": "dueDate", "operator": "before", "value": "2026-01-01" },
    { "field": "remainingBalance", "operator": "greaterThan", "value": "1000" }
  ],
  "first": 50
}
  • Les conditions se combinent en ET ; les valeurs d’une même condition en OU.
  • Un champ ne porte qu’une condition, et il y a au plus 20 conditions par appel.
  • Les champs et les opérateurs viennent d’une liste blanche par outil, donnée dans la description de chacun. Un champ inconnu, ou un opérateur que le champ n’accepte pas, est refusé, jamais ignoré.
  • Les dates s’écrivent AAAA-MM-JJ et se comparent par jour entier. La comparaison de texte ignore la casse et les accents.
Outil Champs
list-accounts accountName, tags, dunningPaused, collectionStatus, daysOverdue, overdueInvoiceCount, overdueBalance, remainingBalance, hasPaymentSchedule, paymentMethod, collectiveProceeding, source
list-aging-balance-by-account accountName, tags, dunningPaused, paymentMethod, collectiveProceeding, source, notDue, d0_30, d31_60, d61_90, d90Plus, totalOutstanding, overdueOutstanding, overdueRate
list-invoices number, accountName, tags, status, dueDate, paymentSchedule, paymentMethod, totalAmount, remainingBalance, channel
list-credit-notes number, accountName, tags, status, issuedDate, paymentMethod, totalAmount, remainingAmount, channel
list-communications direction, status, deliveryStatus, accountName, contactName, subject, date
list-account-tasks title, accountName, status, type, tags, balance, createdAt, updatedAt

Sur list-invoices et list-credit-notes, tags porte sur les étiquettes du compte auquel le document appartient, pas sur des étiquettes du document, qui n’en a aucune. Il prend des identifiants d’étiquettes, ceux que renvoie list-tags, jamais leur libellé. C’est ainsi qu’un groupe de sociétés se lit en un appel : étiquetez les comptes une fois, puis { "field": "tags", "operator": "containsAny", "values": ["<identifiant d'étiquette>"] } renvoie toutes les factures ouvertes du groupe entier, au lieu d’un appel par compte.

Les mêmes conditions existent sur l’API REST publique, où elles voyagent dans une seule chaîne de requête. Voyez Pagination et filtres pour le tableau des opérateurs et la sémantique exacte.

Crédits

get-organization et list-organizations renvoient un champ credits : le solde prépayé qui paie les relances par SMS et par courrier que Billabex envoie pour votre compte, ainsi que les recherches de contact. Les emails sont gratuits et ne le consomment jamais.

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "Acme Corporation",
  "credits": 250,
  "creditLots": [
    {
      "grantedAt": "2026-01-12T09:30:00.000Z",
      "expiresAt": "2027-01-12T09:30:00.000Z",
      "remaining": 100
    },
    {
      "grantedAt": "2026-02-12T09:30:00.000Z",
      "expiresAt": "2027-02-12T09:30:00.000Z",
      "remaining": 150
    }
  ]
}

À zéro, les SMS et les courriers cessent de partir ; les relances par email continuent. Rien d’autre dans l’API ne le signale, et c’est pourquoi le solde mérite d’être lu si vous construisez un tableau de bord ou une alerte au-dessus de Billabex.

Les crédits expirent douze mois après leur chargement, et chaque recharge court sur sa propre horloge. C’est ce que rapporte creditLots, l’échéance la plus proche d’abord : le solde ci-dessus annonce 250 crédits, mais 100 d’entre eux disparaissent en janvier. Un envoi dépense toujours d’abord les crédits les plus proches de leur expiration : une alerte fondée sur le seul solde manquera donc la chute. Il n’existe aucune notification d’expiration : lisez creditLots.

Ces champs sont en lecture seule, mais send-outgoing-message dépense le solde après avoir rendu les factures et les avoirs sélectionnés, tout comme search-contact-candidates et enrich-contact. Appelez d’abord preview-outgoing-message pour obtenir le prix exact au segment ou à la page sans rien dépenser, puis passez cette valeur en maxCredits. Réutilisez la même idempotencyKey à chaque nouvelle tentative. send-outgoing-communication envoie toujours un email gratuit. La recharge n’est pas en libre-service : Billabex la traite manuellement.

Pagination

Les outils qui renvoient une liste paginent par curseur :

  • Paramètres : first (éléments par page, 20 par défaut, 100 au maximum) et after (curseur).
  • Réponse : un tableau nodes et un pageInfo.endCursor.
  • Tri : list-accounts, list-aging-balance-by-account, list-invoices, list-credit-notes, list-communications et list-account-tasks prennent sortBy et sortOrder (asc ou desc). sortBy accepte les mêmes valeurs que la liste REST correspondante, énumérées dans la description de chaque outil.

Sur une liste filtrée, un endCursor appartient à l’ensemble exact de filtres et au tri pour lesquels il a été émis. Renvoyez-le tel quel pour obtenir la page suivante ; dès qu’une condition ou le tri change, abandonnez-le et relisez la liste depuis sa première page, faute de quoi l’appel est refusé.

Remarques

  • OAuth est obligatoire pour tout accès MCP.
  • Les jetons doivent être envoyés dans l’en-tête Authorization: Bearer <jeton>.
  • La limitation de débit s’applique aux requêtes MCP : 300 par minute et par jeton.
  • update-outgoing-communication accepte un message en markdown et de nouvelles pièces jointes dans files, en base64. Un appel portant des fichiers n’est pas idempotent. N’incluez pas de signature : la plateforme produit le HTML et le texte, et ajoute la signature de l’agent automatiquement.

Promesse de paiement

get-account-payment-promise, record-account-payment-promise et cancel-account-payment-promise donnent les mêmes capacités que la webapp et l’API publique (GET, POST et DELETE sur /accounts/{accountId}/payment-promise). La lecture demande mcp:read, les écritures mcp:write et les droits du compte.

Une promesse est un engagement à payer, lu dans ce que le client a dit : elle ne change aucune écriture comptable, c’est ce que la relance suivante ne doit pas contredire et ce que lit la prévision d’encaissement. Un compte n’en porte qu’une à la fois, donc enregistrer la suivante remplace la précédente : c’est aussi le chemin de modification. Une date déjà passée est refusée, un paiement que le client dit déjà fait est une déclaration de paiement.

invoiceNumbers porte les factures que l’engagement nomme, jamais celles devinées du solde. Sans montant, la promesse est estimée à ce que ces factures doivent encore, et au solde entier quand l’engagement n’en nomme aucune ; amountIsEstimated le signale. La portée reste par défaut toute facture échue au jour de l’enregistrement : les numéros la précisent, ils ne la remplacent pas.

Paiements annoncés et rapprochement

list-account-payment-declarations, record-account-payment-declaration et resolve-account-payment-declaration donnent les mêmes capacités que la webapp et l’API. La lecture demande mcp:read, les écritures mcp:write et les droits du compte. Une annonce se déduplique par sourceRef. declaredStage reprend ce que le client a dit de son paiement sans le monter en grade, parmi authorized, processed, sent et paid : seul paid affirme le paiement lui-même, les trois autres annoncent une étape qui peut encore ne rien produire, et la relance demande alors où en est cette étape. proofDocumentAttached signale que le client a joint un justificatif de ce règlement : il ne prouve pas la réception et ne change pas le stade, il dit que le rapprochement part d’une référence. Résoudre demande une décision explicite et sa note ; ne jamais déduire PaymentNotReceived d’une facture ouverte. PaymentReceived confirme la réception mais conserve la protection si les factures ne sont pas encore rapprochées. La clôture de la tâche seule ne résout rien.

Pour aller plus loin