Skip to content

Mobile Native Integration

When embedding CFC in a mobile native application, indicate that the app is running in native mode by setting the isMobileApp option:

typescript
import { CfcClient } from "@melio-eng/cfc-sdk";

const client = new CfcClient({
  container: document.getElementById("cfc-container"),
  environment: "production",
  token: "<your-token>",
  tenant: "<your-tenant>",
  mode: "full-page",
  isMobileApp: true,
  onDownloadFile: (fileName, data) => {
    // Handle file download in native app
    // data is base64-encoded file content
    nativeBridge.downloadFile(fileName, data);
  },
});

client.init();

This flag adds isMobileApp=true to the authentication URL, signaling CFC to adjust behaviors for native environments.

Behavior Changes in Native Mode

Sync Connections

The native environment does not support opening popups. Connecting to QuickBooks Online or QuickBooks Desktop is not supported in native mode. When users attempt to initiate a sync connection, they will see an informational message explaining that this action is only available via the web experience.

File Downloads

In a standard web integration, CFC handles file downloads through the browser. In native mode, CFC instead sends a DOWNLOAD_FILE postMessage event containing the file data and metadata. The host app is responsible for handling the download using native platform APIs.

File Download Event

When a user triggers a file download inside the iframe, the following postMessage is sent:

json
{
  "type": "DOWNLOAD_FILE",
  "fileName": "Receipt-12345.pdf",
  "data": "<base64-encoded file content>",
  "messageId": "<uuid>"
}
FieldTypeDescription
fileNamestringName of the file being downloaded
datastringBase64-encoded file content

Using the SDK

typescript
const client = new CfcClient({
  // ...other config
  isMobileApp: true,
  onDownloadFile: (fileName, data) => {
    // Decode base64 and save using native APIs
    const binaryData = atob(data);
    nativeBridge.saveFile(fileName, binaryData);
  },
});

Or use the low-level listener:

typescript
client.on("DOWNLOAD_FILE", (message) => {
  const { fileName, data } = message;
  // Handle download
});

Without the SDK (DIY)

javascript
window.addEventListener("message", (event) => {
  if (event.data.type === "DOWNLOAD_FILE") {
    const { fileName, data } = event.data;
    // Decode base64 and trigger native download
    nativeBridge.downloadFile(fileName, data);
  }
});