Wrapply Bridge API: connect your website to native app features
Practical guide to Wrapply native bridge APIs for notifications, deep links, inbound links, in-app purchases and location in generated Flutter apps.
Native bridge reference
The generated Flutter app exposes window.Wrapply inside the WebView. Your website can call this object to use native features only when the related module is enabled during configuration. Always wait for wrapplyNativeBridgeReady and always handle { ok:false, error } as a normal fallback case.
| API | When to use it | Input | Response |
|---|---|---|---|
window.Wrapply.isNativeApp() | Detect the native wrapper | none | true inside app |
notifications.requestPermission(payload) | Ask notification permission | { provider } | { ok, permission, granted } |
notifications.getToken(payload) | Read or refresh the device token | { provider, refresh? } | { ok, token, provider } |
notifications.refreshToken(payload) | Regenerate the token. Alias: updateToken | { provider } | { ok, token, refreshed:true } |
notifications.show(payload) | Show an immediate local notification | { title, body?, data? } | { ok, shown:true } |
notifications.getStatus(payload) | Read provider and permission status | { provider } | { ok, granted, configured? } |
iap.getProducts(payload) | Read configured store products | { packageName, productIds } | { ok, available, products } |
iap.purchase(payload) | Start an in-app purchase | { packageName, productId, consumable? } | { ok, purchaseStarted } |
iap.restorePurchases(payload) | Restore non-consumable purchases | { packageName } | { ok, latestPurchases } |
deepLinks.open(payload) | Open internal URL, external URL, phone, email or WhatsApp | { type, url/value } | { ok, type, url } |
wrapply://open/path | Open the installed app from email, SMS or external site | external link | loads https://DOMAIN/path |
Notification providers
The website can choose the notification provider on each call. Wrapply includes only the provider selected in the generated app.
| Provider | Use | Required configuration | Important note |
|---|---|---|---|
| local | Safe default, local token stored in shared preferences | No external file | Useful for tests/session ID; not a real remote push token |
| firebase | Firebase Cloud Messaging provider | android/app/google-services.json and optional ios/Runner/GoogleService-Info.plist | If files are missing, bridge returns ok:false/configured:false |
| onesignal | OneSignal provider | OneSignal App ID in configuration/build | Requires OneSignal setup before sending remote pushes |
Device permissions
Camera, microphone and geolocation use standard browser APIs. The wrapper adds the native Android/iOS permissions when the feature is enabled.
| Feature | Web API | Native permissions | Behaviour |
|---|---|---|---|
| Camera | navigator.mediaDevices.getUserMedia({ video:true }) | Android CAMERA, iOS NSCameraUsageDescription | Use standard web API; app handles native prompt |
| Microphone | navigator.mediaDevices.getUserMedia({ audio:true }) | Android RECORD_AUDIO, iOS NSMicrophoneUsageDescription | Use standard web API; no direct Wrapply call |
| Geolocation | navigator.geolocation.getCurrentPosition(...) | Android COARSE/FINE, iOS location usage string | Fine location is optional and should be enabled only when needed |
Examples by code type
These examples are intentionally small: they show the exact integration pattern, while your generated PDF lists the modules enabled for the specific app.
Ready helper
if (window.Wrapply && window.Wrapply.__nativeBridgeReady) {
callback(window.Wrapply);
return;
}
window.addEventListener("wrapplyNativeBridgeReady", () => {
callback(window.Wrapply);
}, { once: true });
}
JavaScript
if (!window.Wrapply?.notifications) return alert("Available inside the app");
const permission = await window.Wrapply.notifications.requestPermission({ provider: "firebase" });
if (!permission.ok || !permission.granted) return;
const token = await window.Wrapply.notifications.getToken({ provider: "firebase" });
await fetch("/api/device-token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: token.token, platform: "wrapply" })
});
});
TypeScript
declare global {
interface Window {
Wrapply?: {
__nativeBridgeReady?: boolean;
isNativeApp: () => Promise<boolean>;
notifications?: {
requestPermission: (p: Record<string, unknown>) => WrapplyResponse;
getToken: (p: Record<string, unknown>) => WrapplyResponse;
refreshToken: (p: Record<string, unknown>) => WrapplyResponse;
updateToken: (p: Record<string, unknown>) => WrapplyResponse;
show: (p: Record<string, unknown>) => WrapplyResponse;
getStatus: (p: Record<string, unknown>) => WrapplyResponse;
};
iap?: { purchase: (p: Record<string, unknown>) => WrapplyResponse };
deepLinks?: { open: (p: Record<string, unknown>) => WrapplyResponse };
};
}
}
export {};
React
export function useWrapplyBridge() {
const [ready, setReady] = useState(false);
useEffect(() => {
if (window.Wrapply?.__nativeBridgeReady) return setReady(true);
const onReady = () => setReady(true);
window.addEventListener("wrapplyNativeBridgeReady", onReady);
return () => window.removeEventListener("wrapplyNativeBridgeReady", onReady);
}, []);
return { ready, Wrapply: ready ? window.Wrapply : null };
}
Vue 3
export function useWrapplyBridge() {
const ready = ref(false);
const markReady = () => { ready.value = true; };
onMounted(() => {
if (window.Wrapply?.__nativeBridgeReady) markReady();
else window.addEventListener("wrapplyNativeBridgeReady", markReady);
});
onBeforeUnmount(() => window.removeEventListener("wrapplyNativeBridgeReady", markReady));
return { ready };
}
Angular
export class WrapplyBridgeService {
async requestToken(provider = "firebase") {
if (!window.Wrapply?.notifications) {
return { ok: false, error: "Bridge unavailable" };
}
return window.Wrapply.notifications.getToken({ provider });
}
}
jQuery
if (!window.Wrapply?.notifications) return;
const result = await window.Wrapply.notifications.getToken({ provider: "local" });
$("#wrapply-output").text(JSON.stringify(result, null, 2));
});
PHP / Laravel Blade
<script>
async function buyNativeProduct() {
if (!window.Wrapply?.iap) return;
const result = await window.Wrapply.iap.purchase({
packageName: "{{ config('app.mobile_package') }}",
productId: "premium_monthly",
consumable: false
});
console.log(result);
}
</script>
WordPress
<script>
window.wrapplyNotify = async function () {
if (!window.Wrapply?.notifications) return;
return window.Wrapply.notifications.show({
title: "WordPress",
body: "Notification called from theme/plugin"
});
};
</script>
<?php });
Deep links
wrapply://open/profile
wrapply://open/checkout?plan=premium
wrapply://open/orders/123
// Native action inside the app
await window.Wrapply.deepLinks.open({ type: "internal_url", url: "https://example.com/account" });
await window.Wrapply.deepLinks.open({ type: "mailto", value: "support@example.com" });
await window.Wrapply.deepLinks.open({ type: "tel", value: "+390000000000" });
await window.Wrapply.deepLinks.open({ type: "whatsapp", value: "+390000000000" });
What the Wrapply bridge does
The bridge exposes a JavaScript API inside the WebView. Your website can call window.Wrapply and the generated Flutter app handles the native action only when the related feature was enabled during configuration.
Enable only the modules you need
Local/Firebase/OneSignal provider, permission request, token read/refresh and local notification display.
Open internal WebView URLs, external browser URLs, phone, email and WhatsApp from your website.
Open the installed app from a configured scheme or app link, then route the user to the right page.
Query store products, start purchase, restore purchases and send results to your backend for validation.
Add the native permission base for maps, nearby results or geolocation flows.
Setup flow
1. Configure features
Enable only the modules you need in the Wrapply configurator.
2. Add required files
Upload Firebase files or provider identifiers when the selected provider requires them.
3. Generate source code
Wrapply writes conditional dependencies, AndroidManifest entries, Info.plist keys and bridge modules.
4. Add JavaScript calls
Call window.Wrapply from your website only after checking the bridge exists.
5. Test before publishing
Test native permissions, tokens, purchases and links on real Android/iOS devices.
Real JavaScript examples
Use these calls from your website only after verifying that window.Wrapply exists.
Notifications
if (!window.Wrapply?.notifications) return;
await window.Wrapply.notifications.requestPermission({ provider: 'firebase' });
const token = await window.Wrapply.notifications.getToken({ provider: 'firebase' });
await fetch('/api/device-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: token.token, platform: 'app' })
});
}
window.Wrapply?.notifications?.show({ title: 'Order updated', body: 'Your request is ready' });
Actions and deeplinks
window.Wrapply?.deepLinks?.open({ type: 'mailto', value: 'support@example.com' });
window.Wrapply?.deepLinks?.open({ type: 'tel', value: '+390000000000' });
window.Wrapply?.deepLinks?.open({ type: 'whatsapp', value: '+390000000000' });
window.Wrapply?.deepLinks?.open({ type: 'url', url: 'https://example.com/help' });
In-app purchases
if (!window.Wrapply?.iap) return;
await window.Wrapply.iap.getProducts({ productIds: ['premium_monthly'] });
const result = await window.Wrapply.iap.purchase({
productId: 'premium_monthly',
consumable: false,
applicationUserName: currentUser.id
});
await fetch('/api/iap/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
});
}
Location
navigator.geolocation.getCurrentPosition((position) => {
console.log(position.coords.latitude, position.coords.longitude);
});
}
What you receive with bridge features
Only selected dependencies, permissions and bridge files are included.
Firebase files, OneSignal App ID and iOS optional files are inserted only when requested.
When bridge features are selected, Wrapply also provides a PDF implementation guide with the exact calls, enabled modules and configuration notes for your generated project.
Payment, notification and permission modules should be tested before publishing.
Bridge FAQ
Does the bridge work on the public website?
No. It works inside the generated app WebView. Always check window.Wrapply before calling native APIs.
Do I need a backend?
For Firebase push and in-app purchase validation, yes. The app exposes tokens and purchase events, but the backend should send messages and validate receipts.
Can Wrapply implement it?
Yes. Managed publishing can include configuration, testing and documentation for the enabled bridge modules.
Ready to connect native features?
Practical guide to Wrapply native bridge APIs for notifications, deep links, inbound links, in-app purchases and location in generated Flutter apps.