Skip to content

PDF-SDK 2.4.1 is out.See what’s new

PDF-SDK
Skip to Content
Docs

License keys

PDF-SDK is licensed per app. Each app sets the license key issued for it once at startup. Without a valid key the editor does not open documents — there is no free tier and no watermark.

Get a key

  1. Request a trial or buy a license — start a free trial (a key for any app, on every platform) or see pricing.
  2. Send your app identifiers — the bundle ID of each iOS, iPadOS and Mac Catalyst app (and its extensions or variants, or a wildcard such as com.acme.*), the Android package names, and the web domains (app.acme.com, or *.acme.com for subdomains).
  3. Receive one key line — PE1.…, covering every identifier you sent on every platform you licensed, plus a separate development key for web development hosts (localhost and the like).

Only the vendor can issue keys: each one is signed, and the SDK verifies the signature offline. Adding an identifier, a platform or a later update period means a new key line — replace the old one.

Set the key

PlatformWhereCall
iOS, iPadOS, Mac CatalystApp.init or didFinishLaunchingPDFEditorSDK.setLicenseKey("PE1.…")
AndroidApplication.onCreatePdfEditorSdk.setLicenseKey("PE1.…")
Webbefore or in createPDFEditor.create(canvas, { licenseKey: 'PE1.…' }) or await PDFEditor.setLicenseKey(key, { wasmUrl })
Fluttermain(), before runAppawait PdfEditor.setLicenseKey('PE1.…')
React Nativeapp start, before the first openawait PdfEditor.setLicenseKey('PE1.…')

Set it once, before the first editor or document opens — the document API (PDFDocumentEditor, PdfDocumentEditor, PdfDocument) is licensed the same way and refuses to open a document without a valid key. Flutter and React Native resolve with the verdict.

A key is not a secret. It only unlocks the apps it names, so it is safe in source control, a build setting or a web page.

What a key contains

A key is a single line — PE1.<payload>.<signature>. The payload is readable JSON: who the key is for and what it covers. The signature is Ed25519 over PE1.<payload>; change one character and the key no longer verifies. Only the vendor can issue keys.

FieldMeaning
sub, id, planlicensee, license id, plan (commercial, trial, internal)
expoptional — the key works through this date (UTC) and stops the day after. Trials always have one.
updoptional — "updates until": the key works with every SDK release published on or before this date, forever
web, ios, macos, androidthe apps covered on each platform; a platform that is not listed is not licensed
srvonline licenses only — the license server the SDK confirms the key with (see Online licenses)

What is checked

A standard key is checked offline — no network call, no activation server, no telemetry. (An online license also confirms with the license server.) The SDK reads the app's identity from the platform itself:

PlatformIdentityExample patterns
Webthe page's host (scheme and port ignored)app.acme.com, *.acme.com (subdomains, not the apex)
iOS / Catalystthe main bundle's identifiercom.acme.app, com.acme.*
Androidthe installed package name (case-sensitive)com.acme.app, com.acme.app.*

On the web, development hosts — localhost, 127.0.0.1, [::1] and *.localhost — need your separate development key, which you keep on your developers' machines. Your production key only unlocks the domains it names, so a key copied off your public site cannot run the engine from a local server.

Expiry and updates

  • Perpetual licenses use upd and no exp: an app built with a covered release keeps working forever, and only a newer SDK release needs a renewed key. Apps already in the stores never stop.
  • Trials and subscriptions use exp: the editor stops opening documents the day after it. Renew before then and ship the new key in an update. An app that stays open past the date refuses the next document it opens; a document already open stays open and can be saved.
  • Online licenses have no exp: they keep working while they are active — see below.
  • Renewing means a new key string with later dates; replace the old one.

Online licenses

A license can also be issued as an online license. It never expires on a date. Instead, we can suspend and resume it — for example while a subscription payment is overdue — and the same key works again the moment it is resumed. Nothing in your app changes and no new build is needed.

  1. At launch — setLicenseKey restores the last confirmation saved on the device and asks the license server for a fresh one in the background. It asks again when the app returns to the foreground (on the web, when the page becomes visible), at most every 10 minutes.
  2. The server answers with a short confirmation signed by us: active, payment due or suspended. The SDK checks the signature itself, and that the confirmation is for this exact key and app.
  3. Between checks the app works offline for as long as the confirmation allows — 30 days by default. An app that can't reach the server for longer stops opening documents until it can.
We setWhat your app does
ActiveWorks.
Payment dueStill works. The SDK logs our message for you (developer console / Logcat).
SuspendedStops opening documents at its next check (suspended). A document that is open stays open and can be saved.
ResumedWorks again at its next check, or straight away with Try again on the locked screen. Same key.

What the SDK sends: the license key, your app's identity (bundle identifier, package name or page origin) and the SDK version — no device identifiers or user data. The iOS and Android SDKs (and Flutter / React Native over them) identify themselves only as PDF-SDK/<version>; iOS adds the device language (Accept-Language). On the web the browser adds its own User-Agent and language. Like any request, it comes from an IP address.

What the vendor's server keeps (for its usage charts): the license, app, SDK version and the answer it gave; the language where it is sent; for web apps, the OS, browser and phone / tablet / desktop read from the browser's User-Agent. It never stores the key or the IP address — only a one-way hash of the address with a salt that changes every day, so a device can be counted for a day but not followed across days. Individual requests are deleted after 35 days; daily totals are kept.

The first launch needs the network once: until the first confirmation arrives the status is verificationRequired, and an editor opened meanwhile waits up to 12 seconds for it.

  • Android: the android.permission.INTERNET permission.
  • Web: allow the license server in your Content-Security-Policy connect-src.
  • iOS: nothing — the license server is HTTPS.

To ask the server now — from an admin screen, say — call refreshLicense(): PDFEditorSDK.refreshLicense() (iOS, async), PdfEditorSdk.refreshLicense() (Android, blocking — call it off the main thread), PDFEditor.refreshLicense() (web), PdfEditor.refreshLicense() (Flutter, React Native). Online licenses need SDK 2.4.0 or later.

Statuses

StatusRunsMeaning and fix
validyesthe key covers this app
developmentyesyour development key, on a web development host
unlicensednono key was set — call setLicenseKey before the first editor opens
invalidnothe key is truncated, altered or not a PDF-SDK key — paste the whole line again. If the reason says the key's format isn't understood, update the SDK.
expirednopast exp — renew
wrongAppnothe key does not list this domain / bundle id / package; the reason names the one the SDK saw
wrongPlatformnothe key has no entry for this platform
versionNotCoverednothis SDK release is newer than upd — renew, or stay on an earlier release
unknownSigningKeynothe key is newer than this SDK release — update the SDK
suspendednoan online license we suspended — the reason carries our message; it works again when we resume it
verificationRequirednoan online license not confirmed yet, or whose confirmation ran out — connect to the network; the SDK asks again by itself

Android spells the same statuses in upper snake case — VALID, WRONG_APP, VERSION_NOT_COVERED and so on; Apple, the web, Flutter and React Native use the names above.

Read the verdict any time: PDFEditorSDK.license (Apple), PdfEditorSdk.license (Android), PDFEditor.licenseInfo() (web), PdfEditor.license() (Flutter, React Native). Each has a one-sentence reason; the SDK also logs it once.

Questions

We have debug builds and app extensions with other identifiers.

Ask for them to be listed, or for a wildcard such as com.acme.*, which covers the app, its extensions and its variants.

Staging and preview deployments on the web?

List each host, or a wildcard for a subdomain you control (*.staging.acme.com).

Does a suspended license break apps already in the stores?

Only for an online license, and only on purpose: it stops opening new documents at its next check and works again the moment it is resumed — no update needed. A standard key is never switched off remotely: it works until its own date, if it has one.

Can someone copy our key into their app?

They would get wrongApp: the key names your identifiers and the SDK reads the identity from the platform, not from the app.

Need a key, more identifiers, or a renewal? Contact sales.