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);
  }
});