Aller au contenu

Développeurs

API REST

Lisez et écrivez la comptabilité d’une société depuis votre propre code, et soyez prévenu des changements par des webhooks signés. Cette page décrit les règles communes à tous les points d’accès ; le guide d’utilisation explique les notions.

Sur cette page

Vue d’ensemble

Chaque requête s’adresse à https://balancelyne.slimbennasrallah.com/api/v1, en HTTPS, avec des corps et des réponses JSON. Une clé donne accès à une seule société.

L’API est incluse dans les offres Plus et Advanced. Sur les autres offres, chaque appel répond 402 avec le code plan_feature.

curl https://balancelyne.slimbennasrallah.com/api/v1/company \
  -H "Authorization: Bearer bal_…"

Authentification

Les propriétaires et administrateurs créent des clés dans Paramètres → API. Une clé commence par bal_ et ne s’affiche qu’une fois : conservez-la dans un coffre à secrets, jamais dans du code front-end ni dans un dépôt.

Envoyez-la dans l’en-tête Authorization : Authorization: Bearer bal_…. Une clé agit avec le rôle de l’utilisateur qui l’a créée ; s’il quitte la société ou perd ce rôle, les appels échouent en 403. Révoquez une clé à tout moment depuis la même page.

Conventions

  • Les montants sont des entiers en millimes : 1191000 vaut 1 191,000 DT. Les autres devises utilisent aussi le millième d’unité. N’envoyez jamais de nombres à virgule.
  • Les taux sont en points de base : 1900 vaut 19 %.
  • Les dates des pièces comptables sont au format AAAA-MM-JJ (2026-11-13) ; les horodatages sont en ISO 8601, en UTC (2026-11-13T09:42:07Z).
  • Les identifiants sont des chaînes opaques. Les numéros de pièces (FAC-2026-0042) sont faits pour les humains ; utilisez id dans votre code.
  • Les mises à jour sont partielles : n’envoyez que les champs modifiés.
  • Les noms de champs sont en camelCase ; un champ inconnu est refusé en 400.
curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/<resource> \
  -H "Authorization: Bearer bal_…" \
  -H "Content-Type: application/json" \
  -d '{ "…": "…" }'

Pagination

Les listes acceptent page (à partir de 1) et limit (50 par défaut, 250 au plus) et renvoient le total, pour savoir quand s’arrêter.

{
  "data": [ { "id": "cm3…", "…": "…" } ],
  "page": 1,
  "limit": 50,
  "total": 214
}

Erreurs

Une erreur renvoie un code HTTP et un corps JSON avec un message lisible error, et un code lorsque votre programme doit réagir.

CodeSignification
400Données invalides ; le message nomme le champ.
401Clé absente, invalide ou révoquée.
402plan_feature : l’offre n’inclut pas cette fonction. plan_limit : une limite de l’offre est atteinte (utilisateurs, documents de vente par mois, salariés). Également renvoyé lorsque l’abonnement a expiré et que la société est en lecture seule.
403Le rôle du propriétaire de la clé ne le permet pas, ou il n’appartient plus à la société.
404Point d’accès ou pièce inconnu (les pièces des autres sociétés ne sont jamais visibles).
409Conflit, par exemple une période close par la date de clôture.
423La société est suspendue.
429Limite de débit atteinte.
5xxErreur de notre côté. Réessayez plus tard avec la même requête.
HTTP/1.1 402 Payment Required
{ "error": "The Essentials plan does not include this. Contact Balancelyne to upgrade.", "code": "plan_feature", "feature": "api" }

Limites de débit

Chaque clé peut faire 120 requêtes par minute. Au-delà, les appels répondent 429 jusqu’à la fin de la minute ; attendez quelques secondes et réessayez. Regroupez vos lectures avec limit=250 plutôt que de lire les pièces une par une.

Nouvelles tentatives et idempotence

Les erreurs réseau arrivent. GET, PUT et DELETE peuvent être relancés sans risque. Avant de relancer un POST qui crée un document, vérifiez s’il existe déjà (par exemple grâce à votre référence enregistrée dans son mémo) pour qu’un délai dépassé ne crée jamais deux factures. Les pièces comptables sont numérotées en continu : un doublon s’annule, il ne se supprime pas.

Webhooks

Dans Paramètres → API, ajoutez une adresse HTTPS et choisissez les événements qu’elle reçoit. Chaque envoi est un POST avec un corps JSON et ces en-têtes :

  • x-balancelyne-topic : le nom de l’événement.
  • x-balancelyne-delivery : un identifiant d’envoi unique ; ignorez un envoi déjà traité.
  • x-balancelyne-hmac-sha256 : le HMAC-SHA256 hexadécimal du corps brut, avec le secret whsec_… du webhook comme clé.

Répondez par un 2xx en moins de 10 secondes. Les autres réponses et les délais dépassés sont relancés jusqu’à 5 fois, après 1, 2, 4 puis 8 minutes. Les derniers envois et leur statut s’affichent sous chaque webhook, avec un bouton d’envoi de test.

{
  "event": "invoice.paid",
  "company": { "id": "cm3…", "handle": "atlas-sarl", "name": "Atlas SARL" },
  "sentAt": "2026-11-13T09:42:07.512Z",
  "data": { "id": "cm3…", "number": "FAC-2026-0042", "total": 1191000, "balance": 0, "currency": "TND" }
}

Vérifiez la signature avant de faire confiance au corps :

import { createHmac, timingSafeEqual } from "node:crypto";

// raw = the request body exactly as received (a string or Buffer), before JSON.parse
export function verify(raw: string, header: string, secret: string) {
  const expected = createHmac("sha256", secret).update(raw).digest("hex");
  const a = Buffer.from(expected), b = Buffer.from(header ?? "");
  return a.length === b.length && timingSafeEqual(a, b);
}
ÉvénementQuand
documents/createUn document de vente ou d'achat a été créé.
documents/updateUn document a été modifié.
documents/deleteUn document a été supprimé.
documents/voidUn document a été annulé.
documents/sentUn document a été envoyé par e-mail.
invoices/createUne facture a été créée.
invoices/updateUne facture a été modifiée.
estimates/acceptedUn devis a été accepté.
estimates/declinedUn devis a été refusé.
payments/createUn paiement a été enregistré.
payments/updateUn paiement a été modifié.
payments/deleteUn paiement a été supprimé.
customers/createUn client a été ajouté.
customers/updateUn client a été modifié.
vendors/createUn fournisseur a été ajouté.
vendors/updateUn fournisseur a été modifié.
products/createUn produit ou service a été ajouté.
products/updateUn produit ou service a été modifié.
products/deleteUn produit ou service a été supprimé.
journal/createUne écriture manuelle a été passée.
bank/importedDes lignes bancaires ont été importées d'un relevé.
payroll/approvedUne paie a été validée.
imports/completedUn import de données (QuickBooks, tableur) est terminé.

Ressources

Chaque écriture suit les mêmes règles que l’application : contrôles, numérotation, passation au grand livre, date de clôture, limites de l’offre, piste d’audit et webhooks. Après une création ou une modification, l’objet revient sous la forme { "data": { … } }.

PUT (ou PATCH) ne change que les champs envoyés ; envoyer lines ou applications les remplace toutes.

Filtres

  • page, limit : pagination (voir plus haut).
  • updated_since=2026-11-01T00:00:00Z : enregistrements modifiés depuis (paiements : créés depuis).
  • from=2026-01-01&to=2026-03-31 : période sur la date comptable (documents, paiements, journal).
  • contact_id=… : documents, paiements ou écritures d’un client ou fournisseur.
  • q= : recherche sur les noms, numéros, références.

Société et listes

Des listes en lecture seule pour trouver les identifiants dont vos documents ont besoin (codes de taxe, conditions, modes de paiement…).

HTTPPoint d’accès
GET/company
GET/tax-codes
GET/tax-rates
GET/withholding-rates
GET/payment-terms
GET/payment-methods
GET/classes
GET/locations
GET/warehouses
curl https://balancelyne.slimbennasrallah.com/api/v1/tax-codes -H "Authorization: Bearer bal_…"

Comptes

Le plan comptable (SCE tunisien). type vaut asset, liability, equity, income ou expense ; detailType détermine le comportement (bank, receivable, payable, tax_payable…). Les écritures demandent le rôle comptable. Les listes ajoutent le balance (signe naturel).

HTTPPoint d’accès
GET/accounts
GET/accounts/:id
POST/accounts
PUT/accounts/:id
DELETE/accounts/:id
curl "https://balancelyne.slimbennasrallah.com/api/v1/accounts?type=expense&q=loyer" -H "Authorization: Bearer bal_…"

curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/accounts -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "code": "6132", "name": "Loyer dépôt", "type": "expense", "detailType": "expense" }'

Clients et fournisseurs

/customers et /vendors sont des vues de /contacts (un tiers peut être les deux). Les listes ajoutent balance.receivable, balance.payable et les montants échus. Les téléphones sont enregistrés au format +216 XX XXX XXX ; taxId est le matricule fiscal.

HTTPPoint d’accès
GET/customers
GET/customers/:id
POST/customers
PUT/customers/:id
DELETE/customers/:id
GET/vendors
GET/vendors/:id
POST/vendors
PUT/vendors/:id
DELETE/vendors/:id
GET/contacts?type=customer|vendor
curl "https://balancelyne.slimbennasrallah.com/api/v1/customers?q=alpha&updated_since=2026-11-01T00:00:00Z" -H "Authorization: Bearer bal_…"

curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/customers -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "displayName": "Société Alpha SARL", "email": "compta@alpha.tn", "phone": "71 123 456",
        "taxId": "1234567/A/M/000", "billingAddress": { "address1": "12 rue de Rome", "city": "Tunis", "governorate": "TUN" } }'

curl -X PUT https://balancelyne.slimbennasrallah.com/api/v1/customers/CUSTOMER_ID -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" -d '{ "notes": "Paie à 60 jours" }'

Produits et services

type : service, inventory, non_inventory, bundle (les lots demandent components). Les prix sont en millimes. À la création, un produit stocké peut recevoir une quantité d’ouverture : initial: { qty, date, unitCost }.

HTTPPoint d’accès
GET/items
GET/items/:id
POST/items
PUT/items/:id
DELETE/items/:id
curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/items -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "type": "service", "name": "Conseil", "sku": "CONS", "salesPrice": 120000, "salesTaxCodeId": "TAX_CODE_ID" }'

Factures, devis, factures fournisseurs, dépenses

Chaque document de vente ou d’achat est une transaction avec des lines. Les lignes de vente prennent un itemId ; les lignes d’achat un itemId ou un accountId (catégorie). taxCodeId par ligne, timbre (1000 = 1 DT) sur les factures. Les totaux, la TVA, le FODEC et l’écriture sont calculés par Balancelyne. draft: true enregistre sans comptabiliser. Lisez un document par son id, ou par son numéro sur le chemin de son type (/invoices/FAC-2026-0042).

Chemins par type : /invoices, /estimates, /sales-receipts, /credit-notes, /refund-receipts, /delayed-charges, /purchase-orders, /bills, /vendor-credits, /expenses, /cheques, /inventory-adjustments, ou /transactions?type=invoice,bill. Filtre status : draft, open, partial, paid, void, unpaid, overdue…

HTTPPoint d’accès
GET/invoices
GET/invoices/:id
POST/invoices
PUT/invoices/:id
DELETE/invoices/:id
POST/invoices/:id/void
GET/transactions?type=…&status=…&contact_id=…&from=…&to=…
curl "https://balancelyne.slimbennasrallah.com/api/v1/invoices?status=overdue" -H "Authorization: Bearer bal_…"

curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/invoices -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "contactId": "CUSTOMER_ID", "date": "2026-11-03", "timbre": 1000,
        "lines": [{ "itemId": "ITEM_ID", "qty": 10, "rate": 150000, "taxCodeId": "TAX_CODE_ID" }] }'

curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/bills -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "contactId": "VENDOR_ID", "date": "2026-11-05", "reference": "STEG-11",
        "lines": [{ "accountId": "ACCOUNT_ID", "qty": 1, "rate": 250000, "taxCodeId": "TAX_CODE_ID" }] }'

curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/invoices/INVOICE_ID/void -H "Authorization: Bearer bal_…"

Un document avec des paiements imputés ne peut pas être supprimé (409 has_payments) : supprimez ou modifiez d’abord le paiement, ou annulez le document. Dans une période close, ajoutez ?closing_password= sinon l’appel répond 409 period_closed.

Paiements

kind : received (d’un client), made (à un fournisseur), customer_refund, vendor_refund. applications indique les factures, factures fournisseurs ou avoirs réglés. Retenue à la source : withholding (millimes) et withholdingRateId ; amount est l’argent réellement versé. Sans accountId, un encaissement attend dans Valeurs à l’encaissement.

HTTPPoint d’accès
GET/payments
GET/payments/:id
POST/payments
PUT/payments/:id
DELETE/payments/:id
POST/payments/:id/void
curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/payments -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "kind": "received", "contactId": "CUSTOMER_ID", "date": "2026-11-20", "accountId": "BANK_ACCOUNT_ID",
        "amount": 1763500, "withholding": 22500, "withholdingRateId": "RATE_ID",
        "applications": [{ "transactionId": "INVOICE_ID", "amount": 1786000 }] }'

Écritures

Écritures manuelles (sourceType: manual) par leur key. Chaque ligne a un debit ou un credit, un accountId, et un contactId sur les comptes clients et fournisseurs. Les débits doivent égaler les crédits. GET /journal-entries?source=all liste aussi les écritures des documents, paiements, paies… (lecture seule).

HTTPPoint d’accès
GET/journal-entries
GET/journal-entries/:id
POST/journal-entries
PUT/journal-entries/:id
DELETE/journal-entries/:id
curl -X POST https://balancelyne.slimbennasrallah.com/api/v1/journal-entries -H "Authorization: Bearer bal_…" -H "Content-Type: application/json" \
  -d '{ "date": "2026-11-30", "memo": "Apport en caisse",
        "lines": [{ "accountId": "CASH_ID", "debit": 5000000 }, { "accountId": "CAPITAL_ID", "credit": 5000000 }] }'

États

Tous les états de l’application : GET /reports donne les clés. Paramètres : from, to (ou range=this_year, last_month…), basis=accrual|cash, columns=month|quarter|class…, lang=fr|en|ar. Les montants des lignes sont en millimes.

HTTPPoint d’accès
GET/reports
GET/reports/profit-and-loss
GET/reports/balance-sheet
GET/reports/trial-balance
GET/reports/:key
curl "https://balancelyne.slimbennasrallah.com/api/v1/reports/profit-and-loss?from=2026-01-01&to=2026-12-31&columns=month" -H "Authorization: Bearer bal_…"
curl "https://balancelyne.slimbennasrallah.com/api/v1/reports/balance-sheet?to=2026-12-31&lang=fr" -H "Authorization: Bearer bal_…"
Bloqué sur une intégration ?WhatsAppE-mail