SDK Quickstart
Aoexl Sign provides a high-performance PDF signing engine that can be embedded into any web application. While the core engine supports Vanilla JavaScript, we provide native wrappers for all major frameworks to ensure a seamless developer experience.
Install
Choose the package that matches your framework:
| Framework | Package | Install Command |
|---|---|---|
| Flutter | aoexl_sign | flutter pub add aoexl_sign |
| React Native | @aoexl/sign-react-native | npm install @aoexl/sign-react-native |
| React | @aoexl/sign-react | npm install @aoexl/sign-react |
| Vue 3 | @aoexl/sign-vue | npm install @aoexl/sign-vue |
| Svelte 4 | @aoexl/sign-svelte | npm install @aoexl/sign-svelte |
| Angular | @aoexl/sign-angular | npm install @aoexl/sign-angular |
| Vanilla JS | @aoexl/sign | npm install @aoexl/sign |
Optional Self-Hosted Engine Setup
Web SDKs use the managed Aoexl engine by default after license validation. You only need to copy dist-engine into your app when you intentionally want to self-host the engine during local development or in a tightly controlled environment.
If you do want to self-host those assets, copy them into your public folder:
rm -rf public/assets/aoexl/dist-engine
mkdir -p public/assets/aoexl
cp -R node_modules/@aoexl/sign/dist-engine public/assets/aoexl/dist-engineThen pass base="/assets/aoexl" (or base: "/assets/aoexl" in JS init) so the SDK can load engine.js and pdf.worker.min.js.
Use pk_test_demo for quick evaluation/local testing. Move to your own pk_live_* key before production.
For embedded signer journeys, prefer mode="embedded-signing" (or embedded-view for read-only disclosures). Those aliases keep the engine behavior the same while applying embed-friendly UI defaults so you need less wrapper code.
Recommended Web Production Auth
For web SDKs (React, Vue, Svelte, Angular, Vanilla JS), keep the long-lived pk_live_* key on your backend and point the SDK at a backend token route:
- frontend:
licenseEndpoint="/api/aoexl-token" - backend: calls Aoexl server-to-server and returns only a short-lived
engineToken
This keeps consumer integration nearly as simple as the old licenseKey prop, but avoids exposing the long-lived key in the browser.
Usage
Flutter
import 'package:aoexl_sign/aoexl_sign.dart';
// In your Widget build:
AoexlSignView(
licenseKey: 'pk_test_demo',
pdfUrl: 'https://your-server.com/contract.pdf',
mode: AoexlMode.sign,
onComplete: (result) {
// result.signedPdfBytes is a List<int>
print('Signing complete: \${result.fields}');
},
onError: (err) => print('Error: \$err'),
)If you already have the PDF in memory, you can pass local bytes instead:
final pdfBytes = await File('/path/to/contract.pdf').readAsBytes();
AoexlSignView(
licenseKey: 'pk_test_demo',
pdfBytes: pdfBytes,
fileName: 'contract.pdf',
mode: AoexlMode.sign,
)The Flutter wrapper loads these hosted assets by default:
cdnUrl:https://unpkg.com/@aoexl/sign@1.2.10/dist/aoexl-sign.umd.cjsengineUrl: not set by default; production uses the managed Aoexl engine after license validationworkerUrl:https://unpkg.com/pdfjs-dist@5.5.207/build/pdf.worker.min.mjs
Override them only if you need to pin a specific build or test a local engine:
AoexlSignView(
licenseKey: 'pk_test_demo',
pdfUrl: 'https://your-server.com/contract.pdf',
cdnUrl: 'https://unpkg.com/@aoexl/sign@1.2.10/dist/aoexl-sign.umd.cjs',
engineUrl: 'http://localhost:4173/engine.js',
workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/build/pdf.worker.min.mjs',
)React Native
import AoexlSign from '@aoexl/sign-react-native'
export default function SignScreen() {
return (
<AoexlSign
licenseKey="pk_test_demo"
pdfUrl="https://your-server.com/contract.pdf"
mode="sign"
onComplete={({ signedPdfBase64, fields }) => {
console.log('Signing complete:', fields)
}}
onError={(err) => console.error(err)}
style={{ flex: 1 }}
/>
)
}React
import { AoexlSign } from "@aoexl/sign-react";
export default function Signer() {
return (
<AoexlSign
licenseEndpoint="/api/aoexl-token"
pdfUrl="/document.pdf"
mode="embedded-signing"
completionRedirectUrl="/done?session={{sessionId}}"
onComplete={(result) => console.log("Final signed PDF:", result.pdfBytes)}
onError={(err) => console.error("SDK Error:", err)}
/>
);
}Vue 3
<script setup>
import { AoexlSign } from '@aoexl/sign-vue'
const onComplete = (res) => console.log("Final PDF:", res.pdfBytes)
</script>
<template>
<AoexlSign
license-endpoint="/api/aoexl-token"
pdf-url="/document.pdf"
base="/assets/aoexl"
@complete="onComplete"
style="height: 600px"
/>
</template>Svelte 4
<script>
import { AoexlSign } from '@aoexl/sign-svelte'
function handleComplete(event) {
console.log("Final PDF:", event.detail.pdfBytes)
}
</script>
<AoexlSign
licenseEndpoint="/api/aoexl-token"
pdfUrl="/document.pdf"
base="/assets/aoexl"
on:complete={handleComplete}
style="height: 600px"
/>Angular 16+
import { AoexlSignComponent } from '@aoexl/sign-angular';
@Component({
standalone: true,
imports: [AoexlSignComponent],
template: `
<aoexl-sign
licenseEndpoint="/api/aoexl-token"
pdfUrl="/document.pdf"
base="/assets/aoexl"
(complete)="onComplete($event)"
style="height: 600px; display: block;">
</aoexl-sign>
`
})
export class SignerComponent {
onComplete(result: any) {
console.log("Final PDF:", result.pdfBytes);
}
}Vanilla JavaScript / Vite
import AoexlSign from "@aoexl/sign";
async function initSigner() {
const viewer = await AoexlSign.init({
licenseEndpoint: "/api/aoexl-token",
container: "#viewer-container", // CSS selector or HTMLElement
pdfUrl: "/document.pdf",
base: "/assets/aoexl",
completionRedirectUrl: "/done?file={{fileName}}&completedAt={{completedAt}}",
onSave: (result) => {
console.log("Document saved", result.pdfBytes);
}
});
// Example: programmatically control the viewer
// viewer.setScale(1.5);
// viewer.destroy();
}Example Backend Token Route
app.post('/api/aoexl-token', async (req, res) => {
const upstream = await fetch('https://aoexl.com/api/v1/license_verification', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
licenseKey: process.env.AOEXL_LICENSE_KEY,
domain: req.body.domain,
timestamp: req.body.timestamp,
}),
})
const data = await upstream.json()
if (!upstream.ok || !data?.engineToken) {
return res.status(400).json({ error: data?.error || 'Failed to mint engine token' })
}
res.json({
engineToken: data.engineToken,
refreshAfterSeconds: data.refreshAfterSeconds,
})
})API Reference
Core Props
These apply to both <AoexlViewer /> and AoexlSign.init().
| Prop | Type | Description |
|---|---|---|
licenseKey | string | Required. Your Aoexl license key. Use pk_test_demo for local evaluation/dev. |
pdfUrl | string | URL of the PDF to load. |
pdfData | Uint8Array | Blob | string | Raw PDF bytes or data-URL (alternative to pdfUrl). |
fileName | string | Override the displayed file name. |
initialScale | number | Initial zoom level when config.initialViewMode is 'scale' (e.g. 1.0 for 100%). |
mode | 'prepare' | 'sign' | 'view' | Viewer mode. Default is 'sign'. |
base | string | Public asset base for self-hosted SDK assets, e.g. "/assets/aoexl" resolves dist-engine/engine.js and dist-engine/pdf.worker.min.js. |
signerInfo | { name, email } | Identity used in completion payloads and audit logs. |
sessionId | string | Optional identifier for the signing session. |
signers | Signer[] | Optional initial signer roster. |
fields | Field[] | Optional initial signature/form field overlays. |
theme | Theme | Color theme overrides. |
signatureConfig | Object | Customise signature dialog tabs and colors. |
ui | UIConfig | Visibility and layout overrides. |
config | Config | Behavioural feature flags (v1.2.0). |
autoJumpNextSign | boolean | Quick alias for config.autoJumpNextSign. |
UI Configuration (ui)
Control which elements are visible in the viewer.
| Option | Type | Description |
|---|---|---|
hide | string[] | List of element keys to hide (e.g., ['toolbar', 'sidebar', 'saveButton']). |
defaultTab | 'view' | 'sign' | Which tab to open by default. Default is 'view'. |
Common Hide Keys:
- Regions:
toolbar,subtoolbar,sidebar,rightPanel - Tabs:
view,annotate,forms,sign,pages,edit - Buttons:
openPdf,saveButton,themeToggle,thumbnailToggle,fileName
Behavioural Config (config)
| Option | Type | Description |
|---|---|---|
autoJumpNextSign | boolean | Auto-scroll to the next unsigned field after placement. |
autoFlattenOnAllSigned | boolean | Emit a flattened PDF automatically once complete. |
disableDigitalSignature | boolean | Hide the Certificate / Digital Signature option. |
fieldOrder | 'create' | 'display' | Order in which fields are visited when auto-jumping. |
initialViewMode | 'scale' | 'fit-width' | 'fit-page' | First-load zoom behavior. Use 'fit-width' when the document should open at readable width inside an embed. |
flattenedBanner | false | FlattenedBannerConfig | Hide or customize the flattened-document banner shown after fields are locked. |
First-load zoom and flattened banner
Use config.initialViewMode for responsive first-load zoom instead of guessing a fixed percentage. The default remains 'scale' on desktop, so existing embeds that pass initialScale keep the same behavior.
<AoexlViewer
licenseKey="pk_test_demo"
pdfUrl="/Merchant.pdf"
mode="sign"
base="/assets/aoexl"
initialScale={1}
config={{
initialViewMode: "fit-width",
flattenedBanner: {
text: "This document is locked for review.",
backgroundColor: "#0f172a",
textColor: "#ffffff",
actionLabel: "Edit again",
showUnlock: true
}
}}
/>Set flattenedBanner: false to hide that banner entirely.
When you copy SDK assets into your app's public folder, prefer base over wiring engineUrl and workerUrl separately. base="/assets/aoexl" expects /assets/aoexl/dist-engine/engine.js and /assets/aoexl/dist-engine/pdf.worker.min.js.
Updating self-hosted engine assets
If you use base to load assets from your own public folder, update those files every time you install a new SDK version. The npm package and the copied dist-engine assets must stay in sync.
For example, after npm install @aoexl/sign@latest, copy the installed engine assets again:
rm -rf public/assets/aoexl/dist-engine
mkdir -p public/assets/aoexl
cp -R node_modules/@aoexl/sign/dist-engine public/assets/aoexl/dist-engineThen keep the viewer pointed at that public base:
<AoexlViewer base="/assets/aoexl" config={{ initialViewMode: "fit-width" }} />Loading, rendering, and upload behavior
When base or engineUrl points to self-hosted assets, the SDK starts loading the PDF engine immediately while license validation runs in parallel. If the license later fails, the viewer tears down and reports the license error through onError.
Documents with 5 pages or fewer render all pages up front at high canvas quality. Larger documents render pages as needed and show an in-view preparing state while a page is being prepared, so users are not left staring at a blank surface.
If a user opens or uploads a new PDF from inside the viewer, any fields supplied for the previous PDF are cleared. Reinitialize the viewer with the replacement PDF's saved field layout if those fields should appear on the new document.
Theme
Customize the look and feel to match your brand.
| Token | Type | Description |
|---|---|---|
primary | string | Primary UI color (buttons, active states). |
accent | string | Accent color for highlights and focus. |
Events & Callbacks
| Callback | Payload | Description |
|---|---|---|
onDocumentLoaded | { pageCount, fileName } | Called after the PDF finishes loading. |
onSave | CompleteResult | Called when the user clicks Save. |
onComplete | CompleteResult | Called after all required fields are filled and saved. |
onAllSigned | { fields: Field[] } | Called immediately when the last required field is filled. |
onPopupStateChange | boolean | Called when the signature/initials modal opens or closes. |
onBack | void | Called when the user clicks the Back / Close button. |
onError | Error | Called on any SDK or license error. |
Result Object (CompleteResult)
The onSave and onComplete callbacks return:
pdfBytes:Uint8Array(The finalized PDF bytes)fileName:stringcompletedAt:string(ISO timestamp)fields:Field[](Snapshot of fields at completion)
Instance Methods
When using AoexlSign.init() or a React forwardRef, you get access to:
| Method | Description |
|---|---|
savePdf(options) | Trigger standard save/export path (returns Uint8Array). |
downloadPdf(options) | Same as savePdf but forces a browser download. |
getPdfBytes(options) | Retrieve current PDF bytes programmatically. |
flattenPdf() | Retrieve a flattened version of the PDF. |
setScale(number) | Set an explicit zoom level (e.g., 1.0 for 100%). |
zoomIn() / zoomOut() | Adjust zoom incrementally. |
fitWidth() / fitPage() | Apply zoom presets. |
destroy() | Unmount the viewer and clean up resources. |
Hosting the Engine
The SDK shell fetches the managed Aoexl engine after license validation. In advanced environments, you can override these paths:
<AoexlViewer
licenseKey="..."
engineUrl="/engine.js" // Local override for dev
workerSrc="/pdf.worker.js" // Custom worker path
/>IMPORTANT
Live keys are domain-bound. The SDK will fail to initialize if used on an unauthorized origin.