Concepts
Policies#
A policy is a versioned setting for all your companies, with an override per company. Kinds: category_mapping (including MCC codes), chart_template, booking_rules, filing_policy, roles_mapping, company_defaults (including optional modules), quotas, messaging and documents.
You write a draft, FinBaze validates it against the kind's schema (platform.policies.schemas()), and activating it makes it live and archives the previous version. A company override applies on top of the platform policy; effective shows the result.
const draft = await finbaze.platform.policies.createDraft("quotas", { aiRunsPerMonth: 200 });
await finbaze.platform.policies.activate(draft.id);
await finbaze.platform.policies.overrides.set(companyId, "quotas", { aiRunsPerMonth: 20 });
const effective = await finbaze.platform.policies.effective("quotas", companyId);
Sandbox to production#
Configure in the sandbox, then promote with one action. In the sandbox bundle.export signs a bundle of the active policies; in production you preview it (a diff per kind plus warnings) and confirm the import, which activates every kind in one transaction.
const bundleId = await sandbox.platform.policies.bundle.export(); // all kinds, or pass a list const preview = await live.platform.policies.bundle.preview(bundleId); if (preview.warnings.length === 0) await live.platform.policies.bundle.confirm(preview.importId);
Filing policy produces tax.deadline_upcoming messages and can require roles to prepare and approve a filing. quota.reached is sent once a month when a quota is used up, and policy.activated when a version goes live.
Extensions#
Custom actions add buttons next to FinBaze's own on a booking, an invoice or a transaction. A click either calls your embed callback or sends custom_action.invoked to your endpoints. Slots are named places on a screen where you put items. Link templates turn a FinBaze object into a link in your own app ("Open shipment in TMS"), and linkTemplates.resolve returns the resolved links; the host of every link must be one of your allowed origins.
const ext = finbaze.platform.extensions;
await ext.linkTemplates.upsert({
resourceType: "sales_invoice",
urlTemplate: "https://tms.example.com/shipments/{externalId}",
label: { en: "Open shipment", nl: "Open zending" },
});
await ext.customActions.upsert({
key: "open_tms",
label: { en: "Open in TMS" },
placements: ["sales_invoice"],
contextType: "sales_invoice",
});
Custom fields add your own typed fields to invoices, transactions, relations and projects (feature extensions.custom_fields). They show in the embedded views, can be included in events (custom_fields) and on documents, and are written with customFields.setValues; only the keys you pass change.
Field control hides, locks or presets a field of a FinBaze view, for all your companies or one. Fields the law requires on a document cannot be controlled. A write to a locked field fails with FIELD_LOCKED.
await ext.customFields.define({ entityType: "sales_invoice", key: "shipment", label: { en: "Shipment" }, type: "text" });
await ext.fieldControl.set({ view: "invoice", field: "reference", mode: "locked" });