Licensing
BroadPaper is free to evaluate and there is nothing to sign up for.
pnpm add @broadpaper/core @broadpaper/blocks @broadpaper/renderer @broadpaper/editor @broadpaper/react
pnpm add @broadpaper/formeEverything works: every block, both PDF backends, the designer, data binding, themes, custom blocks, the render service and your real data. There is no trial clock, nothing expires, and no feature is behind a wall. Evaluate it for as long as you like; production use needs a licence.
In the software, one thing is different without a licence: generated PDFs carry a BroadPaper evaluation mark. A licence removes it, and under the licence agreement it is also what permits production use.
A licence is twelve months of unwatermarked commercial use, including every update released in those twelve months and support throughout. Renewing buys the next twelve.
What BroadPaper does not do
Worth stating plainly, because most SDKs at this price do at least one of these:
- No trial period, and nothing that stops working after n days.
- No feature gates. Both licences unlock exactly the same software.
- No per-developer seats, no activation, no machine or MAC-address binding.
- No domain locking.
- No telemetry, and no call home — not on render, not on start-up, not ever. The SDK makes no network request of its own under any circumstances.
- No licence server. PDF generation works with no route to the internet, and always will.
Licences are verified locally against a public key compiled into the package. We never see your templates, your data or your documents.
Configuring a licence
Set one environment variable:
BROADPAPER_LICENSE=BP1.eyJzY2hlbWFWZXJzaW9uIjox…Any package that generates a PDF picks it up. That is the whole integration.
Where an environment variable is not available — a browser bundle, a build-time constant, a configuration file you already have — configure it once at start-up instead:
import { BroadPaper } from "@broadpaper/forme";
BroadPaper.configure({ license: process.env.BROADPAPER_LICENSE });configure is process-wide and idempotent. Call it once, as early as you can — in your server's entry point, or in your app's bootstrap. It is exported from @broadpaper/forme, @broadpaper/pdf and @broadpaper/server, and they all write to the same place, so it does not matter which one you import it from.
Deliberately, there is no per-render licence argument in normal use. Threading a licence through every export path is how one path ends up forgetting it, and the way you find out is a customer's month-end report arriving stamped "Evaluation Copy".
Multi-tenant hosts
If one process really does render on behalf of several licensed organisations, every render function takes an optional license that overrides the configured one for that call.
The licence is not a secret
It is a signed certificate, not an API key. It says who bought what and until when, and BroadPaper signed it with a private key that only we hold.
That means it is safe in places a credential is not:
- a browser bundle, where anyone can read it;
- a container image;
- a repository, if you want it there;
- a build log.
Someone who copies your licence cannot change what it says — editing a single character of the payload breaks the signature — and cannot manufacture another one. Use of BroadPaper is governed by the licence agreement; the certificate is how the software knows which agreement applies, not a lock.
What a licence looks like
BP1.<base64url payload>.<base64url signature>The payload is readable — it is base64, not encryption:
{
"schemaVersion": 1,
"keyId": "bp-2026",
"licenseId": "lic_7k2m…",
"organisationId": "org_2abc…",
"organisationName": "Acme Ltd",
"product": "broadpaper-sdk",
"plan": "saas",
"licenseType": "subscription",
"issuedAt": 1788000000,
"validUntil": 1819536000,
"updatesUntil": 1819536000
}validUntil is when the right to use the software ends and updatesUntil is when the right to updates ends. For the licences sold today they are the same date, because what you buy is twelve months in which both hold. They are two fields rather than one so that a licence whose two clocks genuinely differ can be issued without changing the format — which would mean reissuing every certificate in the field.
The signature covers all of it, including keyId, so a licence cannot be re-pointed at a different key. BP1 is the string format version and schemaVersion is the payload's, and both move independently: a licence in a format your SDK predates is reported as "needs a newer BroadPaper", not as corrupt. Fields are only ever added, never renumbered — an SDK that meets a field it has never heard of carries it and honours the licence.
Licence states
| State | PDFs | What the SDK does |
|---|---|---|
| No licence | Watermarked | Logs once, at start-up, saying so |
| Malformed or tampered | Watermarked | Logs what is wrong with it |
| Signed by an untrusted key | Watermarked | Logs that the key is not one this build trusts |
| For a newer BroadPaper | Watermarked | Logs that the SDK needs updating |
| Valid | Clean | Nothing |
| Expired, within 30 days | Clean | Logs a renewal warning |
| Expired, beyond 30 days | Watermarked | Logs that it has expired |
Two things worth noticing.
Nothing ever fails. A missing, broken or expired licence never throws, never refuses to render and never returns an error. It produces a watermarked PDF and a line in your log. A typo in a configuration file must not be able to take down a payroll run.
There is a 30-day grace period. A licence keeps working for a month after it expires, warning as it goes. A card that expired over a holiday is an accounts-payable problem, not an incident.
Checking the state yourself
Useful in a health check, or to fail your own deployment when production is unlicensed:
import { resolveLicenseStatus } from "@broadpaper/forme";
const status = await resolveLicenseStatus();
status.state; // "active" | "grace" | "expired" | "unlicensed" | "invalid" | …
status.licensed; // true when PDFs render clean
status.plan; // "internal" | "saas" | null
status.validUntil; // Date | null
status.daysRemaining; // number | nullThe render service reports the same thing on GET /health, so an operator can see what a deployment is producing without generating a document to find out.
Plans
Two licences. They unlock identical software; what differs is what you may build with it.
Internal — BroadPaper may be used in software intended for your own organisation's users: employees, contractors, and other people working for you.
SaaS / OEM — required when BroadPaper's functionality is incorporated into software made available to customers or any other external third party: a SaaS product, an embedded product, something you ship or host for other people.
This is a commercial distinction, not a technical one, and BroadPaper makes no attempt to detect which you are doing — it could not, and trying would mean the telemetry and network calls this product exists to avoid. The plan is recorded in the signed licence, displayed in your account, and defined by the licence agreement.
Renewals
Licences run for a year, expiring when the period you have paid for does.
When a subscription renews, a new licence is issued automatically and appears in your account. Copy it into your configuration in the ordinary course of a deploy — you have a month to do it, because the old one keeps working through its grace period.
Cancelling does not revoke anything. A licence stays valid until the end of the period it was paid for, and then lapses on its own.
When a licence lapses, output goes back to carrying the evaluation mark — a month after expiry, once the grace period has run out. Nothing stops working, nothing is deleted, and your templates and documents are yours whatever the licence says; what a licence buys is a year of clean output, and a lapsed one stops buying it. That is the whole of it, stated plainly here because a surprise about it would arrive on a customer's month-end report rather than in your logs.
Evaluation output
The mark is one line across each page — light, diagonal, and behind the content, so an evaluation PDF is entirely readable and unmistakably not for production. It is applied at the point a PDF is produced, so it is the same through the browserless engine, the Chromium backend, the render service and the designer's print dialog.
The PDF's Producer records which licence produced the file — BroadPaper (lic_7k2m…), or BroadPaper (evaluation). That is a licence id, not an account or a person, and it is the only identifying thing BroadPaper puts in a document.
Development and production keys
Licences we issue for testing are signed with a different key from the one production licences use, and released SDKs do not trust it. A development licence therefore produces watermarked output in a production build, which is the point: nothing signed on a laptop can become a production licence by accident.
To honour a development licence locally, name its key:
BROADPAPER_TRUSTED_KEYS='[{"keyId":"bp-dev-1","publicKey":"s5aZ8HYu…"}]'or pass trustedKeys to configure. Production licences need none of this.
Buying one
Pricing and both plans are on the pricing page. A licence belongs to your organisation rather than to whoever paid, so anyone you add to it can see and use the same licence.