Een kleine client
Deze helper zet de juiste headers, pakt data uit, herhaalt bij 429 en serverfouten en geeft een bruikbare fout bij 4xx. De andere JavaScript-voorbeelden gebruiken hem.
// factora.js — kleine client met foutafhandeling en 429-herhaling (Node 18+).
const BASE = 'https://factora.one/api/v1';
export async function factora(path, { method = 'GET', body, attempt = 0 } = {}) {
const res = await fetch(BASE + path, {
method,
headers: {
Authorization: `Bearer ${process.env.FACTORA_API_KEY}`,
Accept: 'application/json',
...(body ? { 'Content-Type': 'application/json' } : {}),
},
body: body ? JSON.stringify(body) : undefined,
});
if ((res.status === 429 || res.status >= 500) && attempt < 4) {
const wait = Number(res.headers.get('Retry-After')) || 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
return factora(path, { method, body, attempt: attempt + 1 });
}
const json = res.headers.get('content-type')?.includes('json') ? await res.json() : null;
if (!res.ok) {
throw Object.assign(new Error(json?.message ?? res.statusText), {
status: res.status,
errors: json?.errors,
code: json?.error?.code,
});
}
return json?.data ?? json;
}Klant en factuur aanmaken en versturen
import { factora } from './factora.js';
const customer = await factora('/customers', {
method: 'POST',
body: { name: 'Jansen Bouw', email: 'info@jansenbouw.nl', city: 'Rotterdam' },
});
const invoice = await factora('/invoices', {
method: 'POST',
body: {
customer_id: customer.id,
invoice_date: new Date().toISOString().slice(0, 10),
lines: [{ description: 'Website onderhoud', quantity: 2, unit_price: 7500, tax_rate: 21 }],
},
});
await factora(`/invoices/${invoice.id}/send`, { method: 'POST' });
console.log(`Factuur ${invoice.invoice_number} verstuurd: € ${(invoice.total_amount / 100).toFixed(2)}`);Alle pagina’s van een lijst ophalen
import { factora } from './factora.js';
// Alle onbetaalde, verzonden facturen ophalen.
async function allInvoices(query) {
const items = [];
for (let page = 1; ; page++) {
const result = await factora(`/invoices?${query}&per_page=100&page=${page}`);
items.push(...result.data);
if (!result.next_page_url) return items;
}
}
const open = await allInvoices('status=sent');
const total = open.reduce((sum, invoice) => sum + invoice.outstanding_amount, 0);
console.log(`${open.length} facturen, € ${(total / 100).toFixed(2)} openstaand`);Betalingen registreren en betaallinks
# Deelbetaling van € 50,00 registreren
curl -X POST https://factora.one/api/v1/invoices/<invoice_id>/register-payment \
-H "Authorization: Bearer $FACTORA_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"amount_cents": 5000, "paid_at": "2026-11-12"}'
# Openbare betaallink (Mollie/Stripe) aanmaken
curl -X POST https://factora.one/api/v1/invoices/<invoice_id>/payment-link \
-H "Authorization: Bearer $FACTORA_API_KEY" \
-H "Accept: application/json"Een deelbetaling verhoogt paid_amount. Pas als het volledige bedrag binnen is, wordt de status paid. Een betaallink werkt alleen als online betalen in de organisatie aan staat.
Van offerte naar factuur
# Offerte accepteren en omzetten naar een factuur
curl -X POST https://factora.one/api/v1/quotes/<quote_id>/accept \
-H "Authorization: Bearer $FACTORA_API_KEY" -H "Accept: application/json"
curl -X POST https://factora.one/api/v1/quotes/<quote_id>/convert \
-H "Authorization: Bearer $FACTORA_API_KEY" -H "Accept: application/json"PDF downloaden
curl https://factora.one/api/v1/invoices/<invoice_id>/pdf \
-H "Authorization: Bearer $FACTORA_API_KEY" \
-o factuur.pdfVoeg ?inline=1 toe om de PDF in de browser te tonen in plaats van te downloaden.
Lees ook
- SnelstartMaak een API-sleutel, doe je eerste verzoek en maak een klant en een conceptfactuur aan.
- FacturenConceptfacturen maken en bijwerken, versturen, betalingen registreren, annuleren met creditnota en PDF downloaden.
- WebhooksLaat Factora je systeem aanroepen zodra er iets gebeurt, zoals een betaalde factuur of een geaccepteerde offerte.