postMessage.
Your native app receives requests from the WebApp and responds by calling back
into JavaScript.
The bridge JavaScript is versioned (
v1, v2, …). The machine-readable
contract for each version is published as a schema.json. See the
Methods reference below for the current version, and the
Versions & download page to download a
schema or browse older versions.Transport
The WebApp communicates with your native app through thepostMessage API.
Your native app is responsible for exposing this channel at the exact
location where the WebApp expects to find it. The location depends on the
platform:
- iOS (WKWebView)
- Android (WebView)
- Flutter (webview_flutter)
WebApp → NativeThe You never call this yourself: the WebApp does it internally. Your app
only needs to (1) register the channel at the expected location and (2)
handle the incoming payloads. WKWebView auto-deserializes the JSON, so
your handler receives a
PayleadBridge channel must be exposed to
window.webkit.messageHandlers.PayleadBridge.Once the channel is registered, the WebApp sends messages to your app by
calling postMessage on it. For example, on iOS:WebApp
[String: Any] dictionary.Native → WebAppCall back with argument binding; never interpolate the JSON into the source.Native
Message format
Request (WebApp → Native)
Your handler receives JSON-RPC 2.0 request objects:Success response (Native → WebApp)
Callwindow.payleadBridge.response(jsonString) with a serialized JSON-RPC 2.0 result:
Error response (Native → WebApp)
If the action fails, respond with a JSON-RPC 2.0 error (see Error codes):Envelope constraints
jsonrpcmust equal"2.0". Reject any other value with error code-32600. If the envelope cannot be parsed at all, respond with"id": nulland error code-32600.idmust be a UUID v4 string. The WebApp always sends a randomly generated UUID v4; non-string ids are silently dropped by the WebApp.- The
idin the response must match theidfrom the request. resultanderrorare mutually exclusive. On success includeresultand omiterror; on failure includeerrorand omitresult. If the WebApp receives both,errortakes precedence and the call rejects.- Timeouts. The WebApp rejects requests that don’t receive a response within 5 seconds for
browser.openandclipboard.write, and 30 seconds forfile.download. Forfile.download, respond once the download has been triggered (consent granted, transfer started), not once it completes.
Methods
browser.open
Opens a URL in the device’s native browser (outside the WebView).
string
required
URL to open. Must use the https:// scheme.Pattern
^https:// · max length 2048clipboard.write
Copies text to the device clipboard.
string
required
Text to copy to clipboard.max length 4096
file.download
Downloads a file and presents it to the user.
string
required
URL of the file to download. Must use the https:// scheme.Pattern
^https:// · max length 200string
Suggested filename. Allowed characters: letters, digits, underscore, hyphen, dot. Must start with a letter or digit. The native app must still sanitise before writing to disk.Pattern
^[a-zA-Z0-9][a-zA-Z0-9_\-.]*$ · max length 255string
MIME type hint (e.g. application/pdf).one of
application/pdf, text/csv, image/jpeg, image/jpg, image/pngError codes
When a method fails, the native app responds with a JSON-RPC 2.0 error object carrying one of these codes inerror.code. error.message must never contain
stack traces, filesystem paths, or other sensitive information.
Integration guide
- iOS (Swift / WKWebView)
- Android (Kotlin / WebView)
- Flutter (webview_flutter)
1
Register the message handler
Register a
WKScriptMessageHandler named PayleadBridge.2
Receive the request
Receive JSON-RPC requests in
userContentController(_:didReceive:).3
Execute and respond
Execute the action and call back with
callAsyncJavaScript using named argument binding.Security checklist for partners
Before shipping your integration, verify each item:- HTTPS only: every URL received from the bridge is validated to start with
https://before opening or downloading.javascript:,data:,file:, andintent://schemes are explicitly rejected. - Filename sanitisation: the schema restricts filenames to a safe character set (
^[a-zA-Z0-9][a-zA-Z0-9_\-.]*$); as defense in depth, the native app re-validates and strips null bytes / OS-reserved names before writing to disk. - Origin allowlist: the bridge is only reachable from pages whose host matches your trusted allowlist (
*.paylead.fr,*.paylead.tech,*.paylead.eu). Navigations outside the allowlist are blocked. - User consent:
file.downloadtriggers a native prompt so the user can confirm or cancel. - App-bound domains (iOS 14+):
limitsNavigationsToAppBoundDomains = trueandWKAppBoundDomainsare configured inInfo.plist.
General recommendations
- Back/forward gestures: disable
allowsBackForwardNavigationGestures(iOS) and handle the back button explicitly (Android) to avoid accidental off-domain navigations. - Loading indicators:
file.downloadcan take up to 30 seconds; surface progress in your native UI. - Correlation logging: when logging bridge errors natively, include the request
idso failures can be cross-referenced with the WebApp’s client-side logs.
What’s next
Page URLs
The WebApp URLs your app can open to land on a specific screen.
Troubleshooting
Diagnose a recurring auth screen, lost cookies, or hard-to-trace behaviour.