OmniAI provides a pre-built component aimed at making it easy for users to connect bank account data to your system. There are two ways to injest user bank data with Omni:

  1. Plaid connection (https://plaid.com/)
  2. Bank statement upload

We provide a standardized response body with tagged transactions (either from Plaid or Omni’s Bank statement extractor) corresponding to the number of periods requested.

How it works

  1. Render a widget (Plaid Connect or Statement Upload) with a client-side Publishable Key.
  2. Widget collects user input and POSTs it to POST /api/v1/embedded/actions with:
    • the publishable key
    • the Action Type (plaid_link or statement_upload)
    • opaque Action Token (e.g., Plaid public_token or file handle)
    • developer-supplied metadata (user id, application id, etc.)
  3. OmniAI validates the key, secures the token, and begins processing.
  4. Your backend receives a Webhook / REST callback with normalized results (transactions, PDFs parsed, errors, etc.).

Quickstart

<!-- ❶ Load the library -->
<script src="https://cdn.getomni.ai/embedded/v1/omni-embedded.js"></script>

<!-- ❷ Container -->
<div id="omni-widget"></div>

<!-- ❸ Mount -->
<script>
  OmniEmbedded.mount('#omni-widget', {
    publishableKey: 'pk_live_abc123',   // REQUIRED
    action:         'auto',             // 'plaid', 'upload', or 'auto'
    metadata: {
      userId:    'usr_789',
      loanAppId: 'loan_456'
    },
    onChange: (event) => {
      // event => { stage, detail, timestamp }
      // Examples:
      // { stage: 'plaid_open',  detail: null }
      // { stage: 'file_selected', detail: { filename: 'jan-24.pdf' } }
      // { stage: 'user_exit', detail: { reason: 'closed_modal' } }
      console.log('[OmniEmbedded] change:', event);
    },
    onComplete: (result) => {
      // { actionId, type }  — OmniAI now owns the token / file
      console.log('[OmniEmbedded] accepted:', result);
    },
    onExit: (exit) => {
      // { stage, reason }
      console.warn('[OmniEmbedded] exited:', exit);
    }
  });
</script>

Widget configuration (OmniEmbedded.mount)

OptionType / ExampleDefaultDescription
action"plaid" | "upload" | "auto""auto"Which UI to show."auto"lets the end-user decide.
publishableKey"pk_live_…"Required.
metadata{ userId: 'usr_123', … }{}Free-form object (≤ 2 KB) returned verbatim in webhooks.
environment"sandbox" | "live""live"Sandbox hits test endpoints & dummy Plaid items.
onCompletefunction(result) {…}Fires once OmniAI has accepted the action (result ⇒ { actionId, type }).
onExitfunction(info) {…}Fires if user closes the widget early.
onChangefunction(event) {…}nullStreams every front-end interaction—stage transitions, file picks, Plaid events, user exits, etc.

Webhook / REST Callback - Full Payload

{
  /* ── Core identifiers ─────────────────────────────────────────── */
  "actionId": "act_9f8e7d",
  "type":     "plaid_link",              // plaid_link | statement_upload
  "status":   "completed",               // accepted | processing | completed | errored
  "metadata": {                          // ← echoed from widget init
    "userId":    "usr_789",
    "loanAppId": "loan_456"
  },

  /* ── Normalized outputs ───────────────────────────────────────── */
  "accounts": [                          // Plaid or PDF-parsed
    {
      "accountId":     "acc_123",
      "name":          "Business Checking",
      "mask":          "6789",
      "type":          "depository",
      "subtype":       "checking",
      "currentBalance":  22450.73,
      "availableBalance":20123.11,
      "institution":   "Chase",
      "currency":      "USD"
    }
  ],

  "transactions": [                      // Unified schema
    {
      "txId":        "tx_abc",
      "accountId":   "acc_123",
      "date":        "2025-04-15",
      "description": "Stripe Payout",
      "amount":      -1520.00,
      "category":    "Deposits",
      "currency":    "USD",
      "source":      "plaid"            // plaid | statement
    }
  ],

  "statements": [                        // Present only if statement_upload
    {
      "statementId":       "stmt_456",
      "accountId":         "acc_123",
      "periodStart":       "2025-04-01",
      "periodEnd":         "2025-04-30",
      "pages":             4,
      "validated":         true,         // ex: period matches Apr-25
      "validationMessage": "",           // or reason if false
      "fileUrl":           "https://files.getomni.ai/stmts/stmt_456.pdf"
    }
  ],

  /* ── Plaid connection details ─────────────────────────────────── */
  "plaid": {                             // Present only if plaid_link
    "itemId":      "item_dev_abc",
    "accessToken": "plaid-sandbox-xzy…", // store securely
    "institution": {
      "id":   "ins_3",
      "name": "Chase"
    },
    "requestId":   "plaid-req-789",
    "raw": { /* full Plaid /transactions/get response */ }
  },

  /* ── Error collection ─────────────────────────────────────────── */
  "errors": [                            // Always present (may be empty)
    {
      "code":    "PDF_VALIDATION_FAILED",
      "message": "Statement period does not include Apr 2025",
      "field":   "statements[0]"
    }
  ],

  /* ── Timestamps ───────────────────────────────────────────────── */
  "createdAt": "2025-06-22T23:08:16Z",
  "completedAt":"2025-06-22T23:08:42Z"
}