Skip to content

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:

FrameworkPackageInstall Command
Flutteraoexl_signflutter pub add aoexl_sign
React Native@aoexl/sign-react-nativenpm install @aoexl/sign-react-native
React@aoexl/sign-reactnpm install @aoexl/sign-react
Vue 3@aoexl/sign-vuenpm install @aoexl/sign-vue
Svelte 4@aoexl/sign-sveltenpm install @aoexl/sign-svelte
Angular@aoexl/sign-angularnpm install @aoexl/sign-angular
Vanilla JS@aoexl/signnpm 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:

bash
rm -rf public/assets/aoexl/dist-engine
mkdir -p public/assets/aoexl
cp -R node_modules/@aoexl/sign/dist-engine public/assets/aoexl/dist-engine

Then 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.

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

dart
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:

dart
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.cjs
  • engineUrl: not set by default; production uses the managed Aoexl engine after license validation
  • workerUrl: 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:

dart
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

tsx
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

jsx
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

vue
<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

svelte
<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+

typescript
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

javascript
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

js
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().

PropTypeDescription
licenseKeystringRequired. Your Aoexl license key. Use pk_test_demo for local evaluation/dev.
pdfUrlstringURL of the PDF to load.
pdfDataUint8Array | Blob | stringRaw PDF bytes or data-URL (alternative to pdfUrl).
fileNamestringOverride the displayed file name.
initialScalenumberInitial zoom level when config.initialViewMode is 'scale' (e.g. 1.0 for 100%).
mode'prepare' | 'sign' | 'view'Viewer mode. Default is 'sign'.
basestringPublic 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.
sessionIdstringOptional identifier for the signing session.
signersSigner[]Optional initial signer roster.
fieldsField[]Optional initial signature/form field overlays.
themeThemeColor theme overrides.
signatureConfigObjectCustomise signature dialog tabs and colors.
uiUIConfigVisibility and layout overrides.
configConfigBehavioural feature flags (v1.2.0).
autoJumpNextSignbooleanQuick alias for config.autoJumpNextSign.

UI Configuration (ui)

Control which elements are visible in the viewer.

OptionTypeDescription
hidestring[]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)

OptionTypeDescription
autoJumpNextSignbooleanAuto-scroll to the next unsigned field after placement.
autoFlattenOnAllSignedbooleanEmit a flattened PDF automatically once complete.
disableDigitalSignaturebooleanHide 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.
flattenedBannerfalse | FlattenedBannerConfigHide 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.

jsx
<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:

bash
rm -rf public/assets/aoexl/dist-engine
mkdir -p public/assets/aoexl
cp -R node_modules/@aoexl/sign/dist-engine public/assets/aoexl/dist-engine

Then keep the viewer pointed at that public base:

jsx
<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.

TokenTypeDescription
primarystringPrimary UI color (buttons, active states).
accentstringAccent color for highlights and focus.

Events & Callbacks

CallbackPayloadDescription
onDocumentLoaded{ pageCount, fileName }Called after the PDF finishes loading.
onSaveCompleteResultCalled when the user clicks Save.
onCompleteCompleteResultCalled after all required fields are filled and saved.
onAllSigned{ fields: Field[] }Called immediately when the last required field is filled.
onPopupStateChangebooleanCalled when the signature/initials modal opens or closes.
onBackvoidCalled when the user clicks the Back / Close button.
onErrorErrorCalled on any SDK or license error.

Result Object (CompleteResult)

The onSave and onComplete callbacks return:

  • pdfBytes: Uint8Array (The finalized PDF bytes)
  • fileName: string
  • completedAt: string (ISO timestamp)
  • fields: Field[] (Snapshot of fields at completion)

Instance Methods

When using AoexlSign.init() or a React forwardRef, you get access to:

MethodDescription
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:

jsx
<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.

Built for product, engineering, and operations teams shipping PDF signing flows.