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.
- JavaScript
- TypeScript
const embed = IntellirentIncome.init({
publishableKey: "pk_live_xxxxxxxxxxxxxxxx",
sessionToken, // from your backend — see Config Options below
userContext: { userId: "renter-123", userType: "CONSUMER" },
});
import type { IncomeEmbed } from "@intellirent/sdk";
const embed: IncomeEmbed = IntellirentIncome.init({
publishableKey: "pk_live_xxxxxxxxxxxxxxxx",
sessionToken,
userContext: { userId: "renter-123", userType: "CONSUMER" },
});
Config Options
The config argument is an IncomeEmbedConfig:
| Option | Type | Required | Description |
|---|---|---|---|
publishableKey | string | Yes | Your publishable API key (pk_live_* or pk_test_*) |
userContext | UserContext | Yes | The 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. |
sessionToken | string | Yes | Single-use session grant (sgt_live_*/sgt_test_*) your backend mints from POST /v1/sessions, proving the mount was server-authorized. See Session Tokens. |
onTokenExpired | function | No | Called 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.
- JavaScript
- TypeScript
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);
},
});
import type {
IncomeReportCompleteEvent,
IncomeReportFailureEvent,
} from "@intellirent/sdk";
const instance = await embed.mount("#income", {
onIncomeReportComplete: (event: IncomeReportCompleteEvent) => {
console.log("Report ready:", event.reportId, "via", event.route);
},
onIncomeReportFailure: (event: IncomeReportFailureEvent) => {
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.
| Option | Type | Required | Description |
|---|---|---|---|
onReady | function | No | The embed has loaded and the renter can interact with it |
onError | function | No | A mount- or flow-level error. See IntellirentIncome.SdkErrorCode |
onResize | function | No | Content height or width changed. The embed resizes itself to match — this callback is for your own layout, not something you need to act on |
onIncomeReportStarted | function | No | The renter started the flow on a route |
onIncomeRouteChanged | function | No | The 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 |
onIncomeConnectionSuccess | function | No | The renter finished connecting their income source. Not the same as the report being ready — see onIncomeReportComplete |
onIncomeReportComplete | function | No | The report is complete — the terminal success outcome |
onIncomeReportFailure | function | No | The 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.