SDK
hisab-sdk enveloppe l'API REST avec un typage complet, la pagination automatique, des relances et la vérification des webhooks.
npm install hisab-sdk|TypeScript|Node.js 18+Installez depuis npm. Le SDK fournit des builds ESM et CommonJS, sans dépendance de production.
npm install hisab-sdk
# or
yarn add hisab-sdk
# or
pnpm add hisab-sdkNécessite Node.js 18 ou plus récent. Votre clé API vient du tableau de bord : Paramètres, puis Clés API.
Créez un client avec votre clé API, puis créez et finalisez votre première facture.
import Hisab from 'hisab-sdk';
const hisab = new Hisab({ apiKey: process.env.HISAB_API_KEY });
// 1. create a draft invoice
const draft = await hisab.invoices.create({
customer_id: 'cus_2b81fe',
issue_date: '2026-06-05',
items: [
{ description: 'Integration services', quantity: 8, unit_price: 1300, tax_rate: 20 },
],
});
// 2. finalize it - this assigns the official invoice number
const invoice = await hisab.invoices.finalize(draft.id);
console.log(invoice.invoice_number); // FAC-2026-0142Le cycle de vie complet : brouillon, finalisation, envoi, paiement, annulation, plus les exports PDF et UBL 2.1.
// list with filters (paginated)
const { data, meta } = await hisab.invoices.list({ status: 'paid', page: 1 });
// lifecycle
const invoice = await hisab.invoices.get('inv_8f3a91');
await hisab.invoices.update('inv_8f3a91', { due_date: '2026-08-05' }); // drafts only
await hisab.invoices.finalize('inv_8f3a91');
await hisab.invoices.markAsSent('inv_8f3a91');
await hisab.invoices.markAsPaid('inv_8f3a91', { payment_method: 'bank_transfer' });
await hisab.invoices.void('inv_8f3a91', { reason: 'Duplicate billing' });
// exports
const pdf = await hisab.invoices.exportPdf('inv_8f3a91', { locale: 'fr' }); // ArrayBuffer
const xml = await hisab.invoices.exportXml('inv_8f3a91'); // UBL 2.1 stringCréez et gérez des clients B2B / B2C, cherchez par nom ou ICE, archivez sans perdre l'historique.
// create a B2B customer (ICE required for B2B)
const customer = await hisab.customers.create({
name: 'MERIT Sarl',
type: 'b2b',
ice: '001234567000089',
});
// read and update
const { data } = await hisab.customers.list({ type: 'b2b' });
await hisab.customers.update('cus_2b81fe', { email: 'finance@example.ma' });
// search helpers (built on list)
const matches = await hisab.customers.search('MERIT');
const byIce = await hisab.customers.findByIce('001234567000089');
// archiving keeps the invoice history
await hisab.customers.archive('cus_2b81fe');Des planifications qui génèrent les factures à la fréquence de votre choix, avec pause / reprise et génération à la demande.
// a monthly schedule that finalizes its invoices automatically
const recurring = await hisab.recurringInvoices.create({
customer_id: 'cus_2b81fe',
frequency: 'monthly',
start_date: '2026-07-01',
auto_finalize: true,
items: [{ description: 'Monthly retainer', quantity: 1, unit_price: 10400 }],
});
// control the schedule
await hisab.recurringInvoices.pause(recurring.id);
await hisab.recurringInvoices.resume(recurring.id, { next_run_date: '2026-08-01' });
// generate the next invoice on demand
const invoice = await hisab.recurringInvoices.generate(recurring.id);
// inspect past runs
const history = await hisab.recurringInvoices.getHistory(recurring.id);Lisez profil, abonnement et quotas API ; mettez à jour identifiants légaux et coordonnées.
// read your organization profile, subscription and API quotas
const org = await hisab.organization.get();
console.log(org.quotas.api_rate_limit_per_minute); // 120
// update legal identifiers and contact info
await hisab.organization.update({ phone: '+212 5 22 00 00 01' });Vérifiez la signature HMAC des webhooks entrants et parsez les événements avec un typage sûr.
import { verifyWebhookSignature, parseWebhookEvent } from 'hisab-sdk';
// app/api/hisab-webhook/route.ts (Next.js)
export async function POST(req: Request) {
const payload = await req.text();
const valid = verifyWebhookSignature({
payload,
signature: req.headers.get('x-webhook-signature')!,
timestamp: req.headers.get('x-webhook-timestamp')!,
secret: process.env.HISAB_WEBHOOK_SECRET!,
});
if (!valid) return new Response('Invalid signature', { status: 401 });
const event = parseWebhookEvent(payload);
if (event.event === 'invoice.paid') {
// mark the order as paid in your system
}
return new Response('ok');
}Chaque erreur API correspond à une classe typée portant le statut HTTP, le code stable et les détails par champ.
import {
ValidationError,
AuthenticationError,
NotFoundError,
RateLimitError,
HisabError,
} from 'hisab-sdk';
try {
await hisab.invoices.finalize('inv_8f3a91');
} catch (err) {
if (err instanceof ValidationError) {
console.error(err.details); // field-level issues
} else if (err instanceof RateLimitError) {
console.error('Retry after', err.retryAfter, 'seconds');
} else if (err instanceof NotFoundError) {
// unknown invoice id
} else if (err instanceof HisabError) {
console.error(err.code, err.message);
}
}Utilisez page et per_page manuellement, ou laissez listAll() parcourir toutes les pages pour vous.
// manual pagination
const page1 = await hisab.invoices.list({ page: 1, per_page: 50 });
console.log(page1.meta.pagination.total);
// auto-pagination - iterates every page for you
for await (const invoice of hisab.invoices.listAll({ status: 'paid' })) {
console.log(invoice.invoice_number);
}
// or collect everything at once
const allPaid = await hisab.invoices.listAll({ status: 'paid' }).toArray();