@beel_es/sdk
v1.1.0
Published
Official Node.js SDK for BeeL Public API - Spanish invoicing platform with VeriFactu support
Maintainers
Readme
BeeL Node.js SDK
Official Node.js/TypeScript SDK for the BeeL API — Spanish invoicing for self-employed professionals with VeriFactu compliance.
Node.js 18+. Single dependency (openapi-fetch).
Features
- Full TypeScript types auto-generated from OpenAPI spec
- Automatic retries with exponential backoff on 429 and 5xx
- Auto idempotency keys on every POST request
- Typed errors — catch
BeeLNotFoundErrorinstead of checking status codes - PDF download as Buffer
- Webhook signature verification with HMAC-SHA256
- Instance-based client — multiple API keys, no global state
- ESM + CommonJS
Installation
npm install @beel_es/sdkQuick Start
import { BeeL } from '@beel_es/sdk';
const beel = new BeeL({ apiKey: 'beel_sk_live_...' });
// Create a draft invoice
const invoice = await beel.invoices.create({
type: 'STANDARD',
recipient: { customer_id: 'customer-uuid' },
lines: [
{ description: 'Consulting', quantity: 1, unit_price: 100, discount_percentage: 0 },
],
});
console.log(invoice.id); // UUID assigned immediately
// Issue it to assign an invoice number and trigger VeriFactu
const issued = await beel.invoices.issue(invoice.id);
console.log(issued.invoice_number); // e.g. "A-2026/0001"Resources
// Invoices
const { invoices, pagination } = await beel.invoices.list({ status: 'ISSUED', limit: 20 });
const invoice = await beel.invoices.get('invoice-uuid');
const created = await beel.invoices.create({ ... });
const updated = await beel.invoices.update('id', { ... });
await beel.invoices.delete('id');
// Invoice lifecycle
await beel.invoices.issue('id');
await beel.invoices.markPaid('id');
await beel.invoices.markSent('id');
await beel.invoices.void('id', { reason: 'Duplicate invoice sent in error' });
await beel.invoices.schedule('id', { scheduled_for: '2026-04-15' });
await beel.invoices.unschedule('id');
await beel.invoices.duplicate('id');
await beel.invoices.createCorrective('id', { ... });
// Customers
const { customers, pagination } = await beel.customers.list({ search: 'Acme' });
const customer = await beel.customers.create({
legal_name: 'Acme SL',
nif: 'B86561412',
address: { street: 'Calle Mayor', number: '1', postal_code: '28001', city: 'Madrid', province: 'Madrid', country: 'Spain', country_code: 'ES' },
});
// Products
const { products } = await beel.products.list();
const results = await beel.products.search('consulting');
// Configuration
const taxConfig = await beel.configuration.getTaxConfig();
const series = await beel.series.list();
// NIF validation
const result = await beel.nif.validate('B12345678');Typed Errors
Every API error maps to a specific error class:
import { BeeL, BeeLNotFoundError, BeeLValidationError } from '@beel_es/sdk';
try {
await beel.invoices.get('nonexistent-id');
} catch (error) {
if (error instanceof BeeLNotFoundError) {
console.log(error.message); // "Invoice not found"
console.log(error.requestId); // "abc123" (for support)
}
if (error instanceof BeeLValidationError) {
console.log(error.message); // "El NIF no tiene un formato válido"
console.log(error.details); // { field: "nif", invalid_value: "..." }
}
}| Error class | Status | When |
|---|---|---|
| BeeLAuthError | 401, 403 | Invalid or missing API key |
| BeeLNotFoundError | 404 | Resource doesn't exist |
| BeeLValidationError | 422 | Invalid data |
| BeeLConflictError | 409 | Duplicate (e.g. same NIF) |
| BeeLRateLimitError | 429 | Too many requests (auto-retried) |
| BeeLApiError | 5xx | Server error (auto-retried) |
Automatic Retries
429 and 5xx errors are retried with exponential backoff. Client errors (400, 401, 404, 422) are never retried.
const beel = new BeeL({
apiKey: 'beel_sk_live_...',
maxRetries: 5, // default: 3
retryDelayMs: 1000, // default: 500
maxRetryDelayMs: 60000, // default: 30000
});PDF Download
import fs from 'fs';
const { buffer, fileName } = await beel.downloadPdf('invoice-uuid');
fs.writeFileSync(fileName, buffer);
// => factura_A-2026-0001.pdfWebhooks
Verify webhook signatures before processing:
import express from 'express';
import { WebhookVerifier } from '@beel_es/sdk';
const verifier = new WebhookVerifier(process.env.BEEL_WEBHOOK_SECRET!);
app.post('/webhooks/beel', express.raw({ type: 'application/json' }), (req, res) => {
try {
const event = verifier.verify(
req.body.toString('utf8'),
req.headers['beel-signature'] as string,
);
if (event.type === 'verifactu.status.updated') {
console.log(event.data.new_status); // 'ACCEPTED' | 'REJECTED'
}
res.status(200).send('OK');
} catch {
res.status(400).send('Invalid signature');
}
});Builders
Optional fluent builders for common operations:
import { InvoiceBuilder, CustomerBuilder } from '@beel_es/sdk';
const customer = CustomerBuilder.create()
.name('Acme SL')
.nif('B12345678')
.email('[email protected]')
.address('Calle Mayor', '1', '28001', 'Madrid', 'Madrid', 'Spain')
.build();
const invoice = InvoiceBuilder.create()
.forCustomer('customer-uuid')
.addLine('Service A', 5, 100.0)
.addLine('Service B', 3, 150.0)
.metadata({ stripe_id: 'pi_abc123' })
.build();Environments
// Sandbox — no VeriFactu quota consumed, safe to test
const sandbox = new BeeL({ apiKey: 'beel_sk_test_...' });
// Production
const prod = new BeeL({ apiKey: 'beel_sk_live_...' });Full Configuration
const beel = new BeeL({
apiKey: 'beel_sk_live_...', // Required
baseUrl: 'https://app.beel.es/api', // Default
maxRetries: 3, // Default
retryDelayMs: 500, // Default
maxRetryDelayMs: 30000, // Default
});Documentation
Full API docs: docs.beel.es
License
MIT
