Skip to main content

Income Embed

The Income Embed is a second, smaller script for integrators who call relay's REST API directly and render their own UI, and have not adopted the Embedded SDK. It gives that audience the same renter-facing income and employment verification flow as Intellirent.mount(selector, { view: "income" }) (see Available Views), without requiring the six-view SDK surface.

If you've already adopted the SDK, use view: "income" instead — there's no reason to load both. The two produce the same renter experience; this page exists for integrators for whom the SDK itself would be the larger addition.

The renter's actual connection steps — search, credential entry, MFA, account selection — run inside relay's iframe on relay's own origin, exactly as they do for the SDK's income view. Nothing vendor-related runs on your page, so no vendor Content-Security-Policy allowances are needed there.

Loading the embed

<script src="https://sdk.ir.app/v0/income-latest.js"></script>

income-latest.js always points at the newest release. To pin a specific version instead:

<script src="https://sdk.ir.app/v0/income-0.26.0.js"></script>

The embed is published from the same version line as the SDK, under the same v{major}/ path, so its version numbers track the SDK's directly — see Versioning below. Loading income-latest.js sets a distinct global, IntellirentIncome, so a page that also loads the full SDK's Intellirent global can do so without either one overwriting the other.

IntellirentIncome.init(config)

Creates an embed instance. Call this once per mount.

const embed = IntellirentIncome.init({
publishableKey: "pk_live_xxxxxxxxxxxxxxxx",
sessionToken, // from your backend — see Config Options below
userContext: { userId: "renter-123", userType: "CONSUMER" },
});

Config Options

The config argument is an IncomeEmbedConfig:

OptionTypeRequiredDescription
publishableKeystringYesYour publishable API key (pk_live_* or pk_test_*)
userContextUserContextYesThe renter's identity. In practice userType is always 'CONSUMER' here — the renter connects their own payroll or bank account — but it's still required rather than defaulted, since a wrong value changes what the embed shows.
sessionTokenstringYesSingle-use session grant (sgt_live_*/sgt_test_*) your backend mints from POST /v1/sessions, proving the mount was server-authorized. See Session Tokens.
onTokenExpiredfunctionNoCalled at most once, when the supplied sessionToken was rejected as expired; return a fresh token to retry. Same behavior as the SDK's onTokenExpired.

sessionToken is required here, unlike on Intellirent.init(), where it's optional (see Session Tokens). A publishable key alone is public by construction and can't prove a report was started by you, and this product is billable and renter-triggered — without a grant, anyone who copies your publishable key off your page could start income reports on your account. IntellirentIncome.init() throws synchronously if sessionToken is omitted, rather than allowing a mount that only starts failing once your account is switched to requiring one.

That requirement is enforced at init() time — a token must be present to call init() at all. It doesn't change what happens if that token has since expired by the time the mount actually exchanges it: the fallback is exactly the SDK's own (see Handling expiry). Returning undefined from onTokenExpired, or omitting the callback entirely, lets the mount proceed without a grant — it doesn't reject — on the same terms as if sessionToken had never been required. onTokenExpired is the only way to keep every mount actually grant-authorized; without it, an expired token degrades silently to the ungranted case this option exists to prevent.

embed.mount(selector, options)

Mounts the flow into the DOM element matched by selector. Mount once and follow progress through the callbacks below — the flow drives its own step progression, including a payroll-to-banking fallback, without a remount. Calling mount() again while something is already mounted throws; call unmount() first to move the flow to a different container.

const instance = await embed.mount("#income", {
onIncomeReportComplete: (event) => {
console.log("Report ready:", event.reportId, "via", event.route);
},
onIncomeReportFailure: (event) => {
console.error("Failed on", event.route, ":", event.code);
},
});

Mount Options

options is an IncomeEmbedMountOptions — a closed set covering only what the income flow itself reads. There is no view option: the embed always renders the income flow, and no screening, report, share, or dashboard options apply.

OptionTypeRequiredDescription
onReadyfunctionNoThe embed has loaded and the renter can interact with it
onErrorfunctionNoA mount- or flow-level error. See IntellirentIncome.SdkErrorCode
onResizefunctionNoContent height or width changed. The embed resizes itself to match — this callback is for your own layout, not something you need to act on
onIncomeReportStartedfunctionNoThe renter started the flow on a route
onIncomeRouteChangedfunctionNoThe flow crossed routes (payroll → banking) — not an error; a report that completes after crossing is worth exactly as much as one that didn't need it
onIncomeConnectionSuccessfunctionNoThe renter finished connecting their income source. Not the same as the report being ready — see onIncomeReportComplete
onIncomeReportCompletefunctionNoThe report is complete — the terminal success outcome
onIncomeReportFailurefunctionNoThe flow failed on a route — the terminal failure outcome

These are the same five onIncome* callbacks and payload types the SDK's income view delivers — see Income/Employment Report Events in SDK Methods and the corresponding types in Type Reference for the full payload shapes and callback-by-callback detail.

Return Value

Returns a Promise that resolves to an IncomeEmbedInstance — the same shape as the SDK's IframeInstance:

interface IncomeEmbedInstance {
readonly id: string; // Unique instance identifier
destroy(): void; // Remove the iframe and clean up
}

instance.destroy() and embed.unmount() tear down the same mounted view — calling either is equivalent, and either is safe to call more than once.

embed.unmount()

Removes the mounted iframe. The embed instance can be reused to mount again afterward. Safe to call when nothing is mounted.

embed.destroy()

Removes the iframe and destroys the embed instance permanently. Calling mount() or unmount() afterward throws — create a new instance with IntellirentIncome.init() instead. destroy() itself is safe to call more than once.

IntellirentIncome.version

The embed's version string, e.g. "0.26.0". Pinned to the SDK's own version — see Versioning.

IntellirentIncome.SdkErrorCode

The same constant object as the SDK's Intellirent.SdkErrorCode — see Error codes in SDK Methods, and SDK Codes in Error Codes, for which codes it exposes and which ones onError actually delivers.

Versioning

The embed ships from the same version line as the SDK — there's no independent version number for it. The same compatibility guarantee that covers the SDK applies here too: a change to IncomeEmbedConfig, IncomeEmbedMountOptions, or any type they reference ships as backwards-compatible unless it comes with a major version bump. See What's New for the version history both artifacts share.