Skip to main content

AI Integration Guide

Quick reference for AI development agents (Claude Code, Cursor, Copilot, etc.) to integrate native-update into Capacitor projects.

Installation

yarn add native-update
# or
npm install native-update

Core Concepts

Native Update provides three main features:

  1. Live Updates (OTA) - Deploy JS/HTML/CSS updates without app store approval
  2. App Updates - Native app store update management (Google Play, App Store)
  3. App Reviews - In-app review prompts

Quick Start

Basic Setup

import { NativeUpdate } from 'native-update';

// Configure the plugin (nested UpdateConfig — one section per feature)
await NativeUpdate.configure({
liveUpdate: {
appId: 'com.your.app',
// Canonical rule: serverUrl is the backend base; the plugin appends
// /v1/updates/check. Hosted backend: https://nativeupdatebe.aoneahsan.com/api
serverUrl: 'https://nativeupdatebe.aoneahsan.com/api',
// Sent as X-API-Key on every check. Mint/copy in the dashboard
// (Apps → your app → API Keys). Supported here since v3.1.3.
apiKey: 'nu_app_…',
channel: 'production', // e.g. 'development' | 'staging' | 'production'
autoUpdate: true,
updateStrategy: 'background', // 'immediate' | 'background' | 'manual'
},
});

Live Updates (OTA)

import { NativeUpdate } from 'native-update';

// Check and apply updates — sync() reports a status enum
const result = await NativeUpdate.sync();
if (result.status === 'UPDATE_INSTALLED') {
// sync() already downloaded + staged the bundle
await NativeUpdate.reload();
}

// Manual update flow
const latest = await NativeUpdate.getLatest();
if (latest.available && latest.url && latest.version && latest.checksum) {
const bundle = await NativeUpdate.download({
url: latest.url,
version: latest.version,
checksum: latest.checksum,
});
await NativeUpdate.set(bundle);
await NativeUpdate.reload();
}

// Notify app is stable after update (prevents auto-rollback)
await NativeUpdate.notifyAppReady();

App Store Updates

import { NativeUpdate } from 'native-update';

// Check for app store updates
const updateInfo = await NativeUpdate.getAppUpdateInfo();
if (updateInfo.updateAvailable) {
if (updateInfo.updatePriority >= 4) {
// Critical update - force immediate
await NativeUpdate.performImmediateUpdate();
} else {
// Flexible update - download in background
await NativeUpdate.startFlexibleUpdate();
// Later, when ready to install
await NativeUpdate.completeFlexibleUpdate();
}
}

App Reviews

import { NativeUpdate } from 'native-update';

// Request review at appropriate moment
const eligibility = await NativeUpdate.canRequestReview();
if (eligibility.canRequest) {
const result = await NativeUpdate.requestReview();
// result.displayed — note: actual review submission not guaranteed (platform controls)
}

API Reference

Live Update Methods

MethodDescriptionReturns
sync(options?)Check and apply updatesPromise<SyncResult>
download(options)Download specific versionPromise<BundleInfo>
set(bundle)Set active bundlePromise<void>
reload()Reload app with current bundlePromise<void>
reset()Reset to original bundlePromise<void>
current()Get current bundle infoPromise<BundleInfo>
list()List all downloaded bundlesPromise<BundleInfo[]>
delete(options)Delete bundlesPromise<void>
notifyAppReady()Mark update as stablePromise<void>
getLatest()Check for latest versionPromise<LatestVersion>
setChannel(channel)Switch update channelPromise<void>
setUpdateUrl(url)Set update server URLPromise<void>

App Update Methods

MethodDescriptionReturns
getAppUpdateInfo()Get app store update infoPromise<AppUpdateInfo>
performImmediateUpdate()Force immediate updatePromise<void>
startFlexibleUpdate()Start background downloadPromise<void>
completeFlexibleUpdate()Install downloaded updatePromise<void>
openAppStore(options?)Open app store pagePromise<void>

App Review Methods

MethodDescriptionReturns
requestReview()Request in-app reviewPromise<ReviewResult>
canRequestReview()Check review eligibilityPromise<CanRequestReviewResult>

Configuration Options

configure() takes a nested UpdateConfig — one optional section per feature:

interface UpdateConfig {
liveUpdate?: LiveUpdateConfig; // OTA updates
appUpdate?: AppUpdateConfig; // app store updates
appReview?: AppReviewConfig; // in-app reviews
backgroundUpdate?: BackgroundUpdateConfig; // background checks + notifications
security?: SecurityConfig; // HTTPS enforcement, cert pinning
}

interface LiveUpdateConfig {
appId: string; // Your app identifier (required)
serverUrl?: string; // Backend base URL; checks hit {serverUrl}/v1/updates/check (HTTPS required in production)
apiKey?: string; // Sent as X-API-Key on every check (dashboard: Apps → your app → API Keys). Since v3.1.3
channel?: string; // Update channel (default: 'production')
autoUpdate?: boolean; // Auto-check + apply updates
updateStrategy?: 'immediate' | 'background' | 'manual';
publicKey?: string; // Public key for signature verification
requireSignature?: boolean; // Reject unsigned bundles
checksumAlgorithm?: 'SHA-256' | 'SHA-512'; // (default: 'SHA-256')
checkInterval?: number; // Auto-check interval
}

See the full field list for every section in src/definitions.ts or the Configuration Guide.

Event Listeners

Available events (see src/definitions.ts for payload types):

EventFires when
downloadProgressOTA bundle download progresses ({ percent, bytesDownloaded, totalBytes, bundleId })
updateStateChangedAn OTA bundle changes state (pending → downloading → ready → active/failed)
backgroundUpdateProgressA background update advances through its phases
backgroundUpdateNotificationA background-update notification is shown/tapped
appUpdateStateChanged / appUpdateProgressNative app-store update state/progress changes
appUpdateAvailable / appUpdateReady / appUpdateFailedApp-store update lifecycle
appUpdateNotificationClicked / appUpdateInstallClickedUser interacted with an app-update notification
import { NativeUpdate } from 'native-update';

const progressListener = await NativeUpdate.addListener('downloadProgress', (progress) => {
console.log(`Download: ${progress.percent}%`);
});

const stateListener = await NativeUpdate.addListener('updateStateChanged', (event) => {
console.log('Bundle state:', event.status);
});

// Later: await progressListener.remove(); or await NativeUpdate.removeAllListeners();

Update Channels

ChannelPurposeAuto-UpdateCheck Interval
developmentInternal testingYes1 minute
stagingQA/Beta testingConfigurable1 hour
productionLive usersNo (consent)Daily

Backend Requirements

Easiest path: use the hosted backend at nativeupdate.aoneahsan.com (free dashboard — register the app, upload bundles, get the serverUrl + API key). Self-hosting instead? Your server must implement this contract (full spec: server requirements):

GET {serverUrl}/v1/updates/check?channel={channel}

Request headers sent by the plugin: X-API-Key, X-Device-ID, X-Current-Version, X-Platform (and X-App-Version when known).

Response — 200 with available: false when there is no update, 200 with:

{
"available": true,
"version": "1.2.0",
"bundleId": "bundle-ulid",
"downloadUrl": "https://cdn.example.com/bundles/1.2.0.zip",
"checksum": "sha256-hex...",
"signature": "base64signature...",
"size": 1048576,
"mandatory": false,
"releaseNotes": "Bug fixes and improvements"
}

downloadUrl must be an HTTPS URL that returns the bundle zip.

CLI Tools

# Create a bundle from your build
npx native-update bundle create ./dist --version 1.2.0 --output ./bundles

# Sign a bundle
npx native-update bundle sign ./bundles/1.2.0.zip --key ./private.key

# Verify a bundle
npx native-update bundle verify ./bundles/1.2.0.zip --key ./public.key

# Generate signing keys
npx native-update keys generate --type rsa --size 4096

Upload the resulting bundle through your backend's dashboard/API (hosted dashboard: the Upload page at nativeupdate.aoneahsan.com).

Platform-Specific Setup

Android

No additional setup required. The plugin's own Gradle config already includes the Google Play App Update and Play Review libraries (do NOT add the legacy com.google.android.play:core artifact — it conflicts with them).

iOS

No additional setup required. Uses native APIs.

Web (Limited Support)

Web platform supports checking for updates only. Actual OTA updates require native platforms.

Security Best Practices

  1. Always use HTTPS for update URLs
  2. Enable signature verification with RSA/ECDSA keys
  3. Use checksums to verify bundle integrity
  4. Test rollback scenarios before production
  5. Implement notifyAppReady() to prevent auto-rollback on stable updates

Common Patterns

Check on App Start

import { App } from '@capacitor/app';
import { NativeUpdate } from 'native-update';

App.addListener('appStateChange', async ({ isActive }) => {
if (isActive) {
const result = await NativeUpdate.sync();
if (result.status === 'UPDATE_INSTALLED') {
// Show user prompt to reload (NativeUpdate.reload())
}
}
});

Review After Positive Action

async function handlePurchaseComplete() {
// After successful purchase
const eligibility = await NativeUpdate.canRequestReview();
if (eligibility.canRequest) {
await NativeUpdate.requestReview();
}
}

Troubleshooting

IssueSolution
Update not applyingCall notifyAppReady() after successful update
Rollback on restartPrevious update crashed; check error logs
Download failsVerify network, check server response format
Signature invalidRegenerate keys, re-sign bundle