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) :
- appeler
POST /mcpsans jeton ; - le serveur répond avec un
WWW-Authenticateportantresource_metadataetscope; - récupérer l’URL des métadonnées de ressource pour découvrir les
authorization_serverset lesscopes_supportedde/mcp; - 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
- L’utilisateur donne des noms : vous appelez le prompt avec un nom de compte comme « Acme Corp » plutôt qu’un UUID
- L’agent résout les identifiants : le prompt lui demande d’utiliser
list-accountsetlist-organizationspour trouver les identifiants correspondants - L’agent collecte les données : il appelle plusieurs outils pour rassembler ce qui est pertinent
- 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 :
- utiliser
list-organizationspour trouver « My Company » ; - utiliser
list-customer-balancespour obtenir les encours ; - utiliser
list-invoicespour trouver les factures à échéance proche ; - 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.
| 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 enOU. - 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-JJet 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) etafter(curseur). - Réponse : un tableau
nodeset unpageInfo.endCursor. - Tri :
list-accounts,list-aging-balance-by-account,list-invoices,list-credit-notes,list-communicationsetlist-account-tasksprennentsortByetsortOrder(ascoudesc).sortByaccepte 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-communicationaccepte unmessageen markdown et de nouvelles pièces jointes dansfiles, 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.