Embed the Offline iFrame viewer and render results by sending the original file + API outputs via postMessage.
This quickstart shows a minimal working integration for the Offline iFrame viewer:
Render an <iframe> (using a placeholder bundle URL)
Fetch the original file and analysis results from your backend
Send them to the iframe via postMessage()
The Offline iFrame bundle URL is provided by Resistant AI during enablement. This page uses placeholders so the viewer cannot be launched without coordination.
See also: Access and hosting for delivery models (self-hosted vs Resistant AI–hosted static bundle).
Prerequisites
Before you start, you need:
An Offline iFrame bundle URL provided by Resistant AI:
<OFFLINE_IFRAME_URL_PROVIDED_BY_RESISTANT_AI>
The expected iframe origin (for postMessage targetOrigin):
<OFFLINE_IFRAME_ORIGIN_PROVIDED_BY_RESISTANT_AI>
A submission_id for a document already processed via the Documents API
Your service can fetch:
the original file bytes (as ArrayBuffer)
API results (/fraud required; /decision and /classification optional)
If your security posture allows it, we recommend using the Resistant AI–hosted static bundle to reduce maintenance overhead (updates are managed as part of our release process). For restricted environments, self-host the bundle.
Quick start
Security and CSP notes (important)
This viewer does not call the Documents API. Your application must fetch results and the original file bytes, then send them to the iframe.This example uses:
an inline <script> block, and
an iframe load handler for initialization.
If your Content Security Policy (CSP) forbids inline scripts (script-src 'unsafe-inline'), move the JavaScript into a separate file and attach the load handler with addEventListener.
Never use * as the targetOrigin in production. Always set targetOrigin to the expected iframe origin.
Display a submission once the iframe is loaded
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Resistant AI Offline iFrame Demo</title> </head> <body> <iframe id="rai-offline-iframe" src="<OFFLINE_IFRAME_URL_PROVIDED_BY_RESISTANT_AI>" allow="clipboard-write" width="1250" height="750" style="border: 0;" ></iframe> <script> async function sendToIframe() { const iframe = document.getElementById("rai-offline-iframe"); // Identifier returned by the Documents API after creating a submission const submission_id = "YOUR_DOCUMENT_SUBMISSION_ID"; // Example: fetch fraud result (recommended with metadata for overlays) // const fraudResult = await fetch(`/v2/submission/${submission_id}/fraud?with_metadata=true`).then(r => r.json()); const fraud = JSON.stringify(fraudResult); // Example: fetch decision result (recommended with additional data for score mapping) // const decisionResult = await fetch(`/v2/submission/${submission_id}/decision?include_additional_data=true`).then(r => r.json()); const decision = decisionResult ? JSON.stringify(decisionResult) : undefined; // Example: fetch original uploaded file bytes // const fileResp = await fetch(`/files/${submission_id}`); const fileData = await fileResp.arrayBuffer(); // Send message using postMessage with transferable ArrayBuffer (recommended) iframe.contentWindow.postMessage( { submissionId: submission_id, // for display/debugging fraud, decision, // optional, include for decisioning visualization fileData, }, "<OFFLINE_IFRAME_ORIGIN_PROVIDED_BY_RESISTANT_AI>", [fileData] ); } // Ensure iframe is loaded before sending message window.addEventListener("load", () => { const iframe = document.getElementById("rai-offline-iframe"); iframe.addEventListener("load", () => { sendToIframe().catch(console.error); }); }); </script> </body></html>
Communication protocol
Use window.postMessage() to send analysis data to the Offline iFrame viewer.
submissionId(optional, recommended): identifier used for display/debugging in the viewer. Use the API’s submission_id value.
fraud(required): JSON.stringify() of the response from GET /v2/submission/{submission_id}/fraud
Required for overlays/highlights: request fraud with ?with_metadata=true
decision(optional): JSON.stringify() of the response from GET /v2/submission/{submission_id}/decision
For proper score mapping and color visualization, include ?include_additional_data=true
classification(optional): JSON.stringify() of the response from GET /v2/submission/{submission_id}/classification
fileData(required): ArrayBuffer of the original uploaded file
clusterDocuments (optional): other documents from a serial fraud cluster, so a reviewer can open them in the viewer. A plain array of objects, not a JSON string. See Visualize a Serial fraud cluster.
style(optional): JSON.stringify() of a style object (you can pass a partial override)
locale(optional): "en", "pt" or "fr" (ISO 639-1 language code)
Styling
If no style is passed, the UI uses a default color scheme. You can override all or part of the palette.