Démarrage5 min

Démarrage

Introduction rapide à l'API Billabex : s'authentifier et faire son premier appel.

Bienvenue dans l’API Billabex 👋 Ce guide vous mène pas à pas de l’authentification à vos premiers appels réussis.

À la fin, vous aurez :

  • un client OAuth configuré ;
  • un jeton d’accès ;
  • l’identifiant de votre organisation ;
  • vos premiers appels en lecture et en écriture.

Qu’est-ce que Billabex ?

Billabex est une plateforme d’automatisation du suivi des paiements propulsée par l’IA, qui aide les entreprises à encaisser plus vite leurs créances.

Notre agent :

  • relance automatiquement les factures impayées ;
  • communique avec les clients en plusieurs langues ;
  • adapte son ton et son rythme avec tact et diplomatie.

Avec l’API Billabex, vous pouvez :

  • gérer les factures et les avoirs par programme ;
  • synchroniser les comptes clients et leurs contacts ;
  • suivre les communications et les soldes ;
  • intégrer Billabex à vos parcours de facturation.

Prérequis

Avant de commencer, assurez-vous d’avoir :

  1. un compte Billabex Créez-le sur https://next.billabex.com/auth/sign-up
  2. une organisation créée dans ce compte
  3. un client OAuth créé dans le portail développeur

Étape 1 : créer un client OAuth

Rendez-vous dans Portail développeur → Clients OAuth et créez un client.

Vous devrez fournir :

  • Nom du client : le nom de votre application
  • URI de redirection : votre URL de rappel OAuth Par exemple https://votreapp.com/callback
  • Scopes : les permissions dont votre application a besoin (voir le guide des scopes)

Une fois créé, vous recevez :

  • un client_id ;
  • un client_secret, affiché une seule fois.

Conservez le secret client en lieu sûr.

Étape 2 : implémenter l’authentification OAuth

Billabex utilise le flux OAuth 2.1 d’autorisation par code avec PKCE.

Sur le principe :

  • votre application prouve son identité par PKCE ;
  • l’utilisateur approuve l’accès ;
  • vous recevez des jetons à durée de vie courte pour appeler l’API.

Concrètement, vous allez :

  1. générer un vérificateur et un défi PKCE ;
  2. rediriger l’utilisateur vers la page d’autorisation ;
  3. recevoir un code d’autorisation ;
  4. échanger ce code contre un jeton d’accès et un jeton de rafraîchissement.

Générer les paramètres PKCE

Générez un code_verifier et le code_challenge correspondant. Gardez le vérificateur en mémoire : vous le réutiliserez à l’échange.

// Générer le vérificateur (chaîne aléatoire)
const codeVerifier = generateRandomString(128);

// Générer le défi (empreinte SHA256 du vérificateur, encodée en base64url)
const codeChallenge = base64UrlEncode(sha256(codeVerifier));

Rediriger vers la page d’autorisation

Construisez l’URL d’autorisation et redirigez l’utilisateur.

const authUrl = new URL('[baseURL]/api/oauth/authorize');
authUrl.searchParams.append('client_id', 'YOUR_CLIENT_ID');
authUrl.searchParams.append('redirect_uri', 'https://votreapp.com/callback');
authUrl.searchParams.append('response_type', 'code');
authUrl.searchParams.append('scope', 'invoices:read accounts:read');
authUrl.searchParams.append('code_challenge', codeChallenge);
authUrl.searchParams.append('code_challenge_method', 'S256');
authUrl.searchParams.append('state', generateRandomString(16));

// Rediriger l'utilisateur vers authUrl

Validez toujours le state renvoyé, pour vous protéger des attaques CSRF.

Échanger le code contre des jetons

Après approbation, votre URI de redirection reçoit un code d’autorisation. Échangez-le sur l’endpoint de jeton.

const response = await fetch('[baseURL]/api/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    code: authorizationCode,
    redirect_uri: 'https://votreapp.com/callback',
    code_verifier: codeVerifier,
    client_id: 'YOUR_CLIENT_ID',
    client_secret: 'YOUR_CLIENT_SECRET',
  }),
});

const tokens = await response.json();

Exemple de réponse :

{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "...",
  "scope": "invoices:read accounts:read"
}

Pour le détail, voyez le guide OAuth.

Étape 3 : récupérer l’identifiant de votre organisation

La plupart des endpoints exigent un organizationId.

Utilisez votre jeton d’accès pour lister les organisations auxquelles vous appartenez et choisir celle sur laquelle travailler.

const response = await fetch('[baseURL]/api/public/v1/organizations?first=10', {
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
});

const data = await response.json();
const organizationId = data.nodes?.[0]?.id;

Étape 4 : votre premier appel

Avec un jeton d’accès et un identifiant d’organisation, vous pouvez appeler l’API publique.

Exemple : lister les comptes de votre organisation.

const response = await fetch('[baseURL]/api/public/v1/accounts?organizationId=YOUR_ORG_ID&first=10', {
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
});

const data = await response.json();
console.log(data);

Avec cURL

curl -X GET "[baseURL]/api/public/v1/accounts?organizationId=YOUR_ORG_ID&first=10" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"

Étape 5 : gérer la pagination

L’API Billabex utilise une pagination par curseur.

  • Lisez pageInfo.endCursor dans la réponse
  • Passez-le en paramètre after pour obtenir la page suivante
  • Quand endCursor est absent, vous êtes au bout
const nextPageResponse = await fetch(`[baseURL]/api/public/v1/accounts?organizationId=YOUR_ORG_ID&first=10&after=${data.pageInfo.endCursor}`, {
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
});

Le guide de la pagination entre dans le détail.

Étape 6 : créer une facture

Créer une facture est une opération d’écriture, qui exige le scope invoices:all.

Cet endpoint attend :

  • du multipart/form-data ;
  • un fichier PDF ou image ;
  • les métadonnées et les montants de la facture ;
  • une adresse de facturation, dont les champs peuvent être vides mais doivent être présents.

Exemple :

const formData = new FormData();
formData.append('accountId', 'ACCOUNT_ID');
formData.append('number', 'INV-2024-001');
formData.append('issuedDate.year', '2024');
formData.append('issuedDate.month', '1');
formData.append('issuedDate.day', '15');
formData.append('dueDate.year', '2024');
formData.append('dueDate.month', '2');
formData.append('dueDate.day', '15');
formData.append('totalAmount', '1500.00');
formData.append('taxAmount', '300.00');
formData.append('paidAmount', '0');
formData.append('poNumber', 'PO-2024-001');
formData.append('billingAddress.street', '1 rue Exemple');
formData.append('billingAddress.city', 'Paris');
formData.append('billingAddress.postalCode', '75001');
formData.append('billingAddress.country', 'FR');
formData.append('file', fileBlob, 'facture.pdf');

const response = await fetch('[baseURL]/api/public/v1/invoices', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${accessToken}`,
  },
  body: formData,
});

const invoice = await response.json();

Les champs inconnus sont refusés

L’API répond 400 Bad Request quand le corps d’une requête porte un champ que l’endpoint ne déclare pas, en nommant le champ fautif :

{
  "statusCode": 400,
  "message": "property phone should not exist"
}

C’est délibéré. Accepter le champ et l’ignorer laisserait un champ renommé ou mal orthographié disparaître derrière un 201 Created, et vous ne le découvririez qu’au moment où la donnée manque. Un 400 échoue tout de suite, dans vos tests d’intégration plutôt qu’en production.

En pratique : envoyez exactement les champs documentés pour l’endpoint. Ne renvoyez pas un objet de réponse entier dans une requête d’écriture, les réponses portant des champs en lecture seule (id, createdAt, totaux calculés) qu’aucun endpoint d’écriture ne déclare.

Pour aller plus loin

Vous êtes prêt à intégrer Billabex 🎉

Lectures recommandées :

Support

Besoin d’aide, ou un retour sur ce guide ? Écrivez-nous via le formulaire de contact.