FinBaze for Platforms

Concepts

FinBaze files and keeps the official copy of every invoice, quote, reminder, payslip and year document. You decide how it looks, at one of three levels per document type (platform.documentRendering.settings.set):

ModeWhat renders
finbaze_layoutFinBaze's layout with your preset: colours, fonts, logo, blocks.
templateYour logic-less HTML template, rendered by FinBaze in an isolated renderer.
partnerYou render the PDF; FinBaze stores it as the official copy.

Whatever the level, the required content (VAT number, address, invoice number, reverse-charge text and so on) is checked. Rules the tax adviser has not yet confirmed produce warnings; the others refuse activation or reject your PDF, and FinBaze then falls back to its own layout.

Presets and fonts#

const { platform } = finbaze;
const layout = await platform.documentLayouts.save({
  documentType: "invoice",
  name: "Acme classic",
  layout: { /* blocks, theme */ },
  companyEditable: "unlocked_blocks",
});
const problems = await platform.documentLayouts.validate("invoice", layout.layout);
await platform.documentLayouts.activate(layout.id, { makeDefault: true });
await platform.documentFonts.upload({ woff2, family: "Acme Sans", weight: 400, attest: true });

A preset can let a company choose between several (documentLayouts.choose) or edit unlocked blocks. A company that picked a preset follows its new versions. Presets travel with the documents policy when you promote from the sandbox.

Templates#

Templates use a small logic-less language (placeholders, loops and conditions over the document's data model) with CSS and small images. Scripts, iframes, remote images, @import and SVG with script are refused. validate renders twelve fixtures and checks the required content; activate only works after a pass.

const t = await platform.documentTemplates.save({ documentType: "invoice", name: "Acme", source: html, css });
const checked = await platform.documentTemplates.validate(t.id); // checked.validationReport lists failures
await platform.documentTemplates.activate(checked.id, { makeDefault: true });

Rendering it yourself#

With mode partner, FinBaze sends document.render_requested with the data model (never a BSN), a deadline and signed links to attachments such as the invoice UBL. Render the PDF and answer before the deadline:

if (event.type === "document.render_requested") {
  const { job, dataModel } = event.data.object;
  const pdf = await renderInvoice(dataModel);
  const { uploadId } = await finbaze.platform.documentRendering.upload(pdf); // up to 10 MB, valid for an hour
  await finbaze.platform.documentRendering.attach(job, { uploadId }); // or { pdfBase64 } for small files
}

FinBaze scans the PDF (no scripts or embedded files) and checks its text against the document's facts. Emails and payment pages wait for the job to settle; on a rejection, a timeout or no answer FinBaze renders its own layout. Events: document.render_requested, document.render_rejected, document.render_failed, document.official_copy_created.

Custom domains#

Invoice, quote and payment pages can live on your own domain: customDomains.add("pay.acme.nl"), create the CNAME and TXT records it returns, and check. FinBaze issues the certificate; custom_domain.status_changed follows the status. A company is only served on its own platform's domains.