Skip to main content

SDK Methods

Detailed reference for the relay Embedded SDK methods.

For the TypeScript declarations of every type named on this page, see the Type Reference.

Intellirent.init(config)

Creates an SDK instance. Call this once at application startup. Returns an IntellirentSDK — the sdk object whose methods are documented below.

const sdk = Intellirent.init(config);

Config Options

The config argument is an SdkConfig:

OptionTypeRequiredDescription
publishableKeystringYesYour publishable API key (pk_live_* or pk_test_*)
userContextUserContextYesUser identity and type for access control
sessionTokenstringNoSingle-use session grant (sgt_live_*/sgt_test_*) minted by your backend, proving the mount was server-authorized. See Session Tokens.
onTokenExpiredfunctionNoCalled at most once, when a supplied sessionToken was rejected as expired; return a fresh token to retry. See Session Tokens.

User Context

Your platform is the authentication provider. The SDK does not manage user identity — your application must authenticate users and pass their identity via userContext. The userType (an SdkUserType) indicates the user's role for the mounted screen.

interface UserContext {
userId: string; // Stable identifier from your auth system (e.g., Cognito sub, Auth0 user_id)
userType: SdkUserType; // 'TSP' | 'END_USER' | 'CONSUMER'
displayName?: string; // Optional display name for the user
email?: string; // Optional email address for the user
}
User TypeDescriptionAccess Level
TSPTenant screening provider (dashboard admin)Key management, origins, theme settings
END_USEROperators (agents, property managers)All screenings on account, after verified
CONSUMERIndividuals being screened (renters, applicants)Own screenings only
const sdk = Intellirent.init({
publishableKey: "pk_live_xxxxxxxxxxxxxxxx",
userContext: {
userId: user.id, // Your auth system's user ID
userType: "END_USER", // Or 'TSP', 'CONSUMER'
},
});

Publishable Key

Your publishable key identifies your account and determines the environment:

  • pk_live_* - Production environment
  • pk_test_* - Test/staging environment
// Production
const sdk = Intellirent.init({
publishableKey: "pk_live_xxxxxxxxxxxxxxxx",
userContext: { userId: "user_123", userType: "END_USER" },
});

// Testing
const sdk = Intellirent.init({
publishableKey: "pk_test_xxxxxxxxxxxxxxxx",
userContext: { userId: "user_123", userType: "END_USER" },
});

Session Token

A publishable key is public by construction, so on its own it cannot prove that a mount was authorized by your backend rather than replayed by anyone holding it. The optional sessionToken config option supplies that proof: your backend mints a single-use grant, and your frontend presents it once at init(). See Session Tokens for the full mint-and-consume flow, the onTokenExpired retry callback, and the POST /v1/sessions API it depends on.


sdk.mount(selector, options)

Mounts an iframe view into a container element.

const instance = await sdk.mount(selector, options);

Parameters

ParameterTypeRequiredDescription
selectorstringYesCSS selector for the container
optionsMountOptionsNoCallbacks and configuration

Mount Options

OptionTypeRequiredDescription
viewSdkViewNoView to display: 'screening' (default), 'dashboard', 'reports', 'report'
screeningScreeningOptionsNoScreening configuration: prefill, unitAddress, applicationFee, endUserType, and productId
reportReportOptionsNoReport configuration: id (required when view='report')
onReadyfunctionNoCalled when the view is fully loaded and ready for interaction
onVerificationSuccessfunctionNoCalled when the identity verification step completes; returns liveKey/testKey for END_USER enrollment
onVerificationFailurefunctionNoCalled when identity verification fails
onScreeningSuccessfunctionNoCalled when the entire screening flow is complete; use this to capture the report ID
onPaymentSuccessfunctionNoCalled when a payment step completes successfully
onErrorfunctionNoCalled when a fatal error occurs
onWarningfunctionNoCalled on non-fatal warnings (e.g., invalid prefill fields)
onReportSharedfunctionNoCalled when the consumer consents to share their report
onReportRevokedfunctionNoCalled when the consumer revokes report sharing
onResizefunctionNoCalled when content height or width changes
onChangefunctionNoCalled when a form field value changes
onStepStartfunctionNoCalled when a wizard step begins
onStepCompletefunctionNoCalled when a wizard step completes
handlePrintRequestedfunctionNoTakes over printing — see Takeover Handlers
handleDownloadRequestedfunctionNoTakes over file downloads — see Takeover Handlers
Print handling

By default, while an SDK view is mounted, the SDK intercepts Ctrl/Cmd+P on the host page and forwards it to the embedded view so it can print its own content (e.g. a report) instead of the host page. No mount option or callback is involved — this is automatic.

If handlePrintRequested is provided, this changes: Ctrl/Cmd+P invokes your handler directly instead, and the embedded view never calls window.print(). See Takeover Handlers.

Navigation guard on the host page

While the user has unsaved personal data entered in the screening form (from the Information step onward), the SDK may add a beforeunload listener on the host page — not just inside the iframe — so that navigating away or closing the tab triggers the browser's native "Leave site?" confirmation. This is automatic (a cross-origin iframe can't trigger that dialog itself) and the listener is added/removed as the user enters and clears data; no mount option or callback is involved. If your host page has its own beforeunload handling, be aware the SDK may register one too.

Available Views

The view option is an SdkView — one of the four values below.

ViewDescriptionRequired Options
dashboardKey management, origins, and theme settingsNone
screeningIdentity verification flow (default)screening.unitAddress (required unless userType === 'END_USER')
reportsList of accessible screening reportsNone
reportView a specific screening reportreport.id
// Dashboard
await sdk.mount("#container", { view: "dashboard" });

// Screening flow (default) — requires unitAddress for CONSUMER
await sdk.mount("#container", {
view: "screening",
screening: {
unitAddress: {
street: "123 Main St",
city: "New York",
state: "NY",
zip: "10001",
},
},
});

// Reports list
await sdk.mount("#container", { view: "reports" });

// Single report
await sdk.mount("#container", {
view: "report",
report: { id: "550e8400-e29b-41d4-a716-446655440000" },
});

ScreeningOptions

Passed as the screening property of MountOptions. Configures the screening view.

interface ScreeningOptions {
prefill?: ScreeningPrefillData; // Pre-populate form fields with known applicant data
unitAddress?: UnitAddress; // Rental property address (required unless userType === 'END_USER')
applicationFee?: number; // Fee override in cents (positive integer, 1–1,000,000)
endUserType?: EndUserCategory; // END_USER category — skips the wizard's user-type selection screen
productId?: ProductId; // Override the Experian report product requested for this screening
}

See Screening Pre-fill for the full list of ScreeningPrefillData fields.

applicationFee

Overrides the default application fee derived from the TSP account's Stripe configuration for this session only.

  • Value is in cents (e.g., 3500 = $35.00)
  • Valid range: 1 to 1,000,000 ($0.01–$10,000.00)
  • Invalid values (negative, zero, non-integer, NaN, Infinity, or above 1,000,000) reject the mount() Promise with a plain Error before the iframe mounts — see Validation failures that don't go through onError

endUserType (SDK v0.13.0+)

END_USER flow only. The END_USER screening flow normally opens with a step asking the operator which category they screen under (independent owner, real estate agent, or property management company). When your platform already knows this, endUserType skips that selection screen and starts the wizard directly at the first data-entry step, already scoped to the given category.

const sdk = Intellirent.init({
publishableKey: "pk_live_xxx",
userContext: { userId: "enduser_abc123", userType: "END_USER" },
});

await sdk.mount("#screening-container", {
view: "screening",
screening: {
endUserType: "PROPERTY_MANAGEMENT",
},
});
  • Accepted values: 'INDEPENDENT_OWNER', 'REAL_ESTATE_AGENT', 'PROPERTY_MANAGEMENT' — the same three options the selection screen itself offers
  • null is treated the same as omitting the option
  • On a non-END_USER mount (i.e. userContext.userType is 'CONSUMER' or 'TSP'), a valid value is ignored — there is no selection screen to skip — and a non-fatal onWarning fires with code IGNORED_END_USER_TYPE
  • An unrecognized value rejects the mount() Promise rather than silently falling back to the selection screen — see Validation failures that don't go through onError

productId (SDK v0.10.6+)

Overrides the Experian report product requested for this screening. When omitted, the TSP account's configured default (account_screening_config.product_id) applies.

ProductId covers two independent Experian Connect API bundle families — consumer-platform bundles and TSP passive-Identity bundles. Which family is meaningful for a given screening depends on your account's entitlements; passing a value from the wrong family for your account is rejected server-side the same as any other invalid value.

Value (ProductId)Product
9 (EXP_9)Credit Report: Credit Profile + VantageScore
34 (EXP_34)Credit Report + Background Data (1 free share): Credit Profile, VantageScore, Criminal Search, and Housing Court Records
36 (EXP_36)Credit Report + Background Data (30 free shares): Credit Profile, VantageScore, Criminal Search, and Housing Court Records
38 (EXP_38)Credit Report + Background Data (unlimited free shares): Credit Profile, VantageScore, Criminal Search, and Housing Court Records
51 (EXP_51)Credit + Background + RentBureau: Credit Profile, VantageScore, Criminal Search, Housing Court Records, and RentBureau Consumer Profile
52 (EXP_52)Credit + RentBureau: Credit Profile, VantageScore, and RentBureau Consumer Profile
68 (EXP_68)Credit Report (alternate): Credit Profile variant (see Experian account configuration for details)
71 (EXP_71)Identity (Passive) + Credit Report + VantageScore + Background Data (Criminal + Housing Court) + RentBureau Consumer Profile
72 (EXP_72)Identity (Passive) + Credit Report + VantageScore + RentBureau Consumer Profile
73 (EXP_73)Identity (Passive) + Credit Report + VantageScore + Background Data (Criminal + Housing Court)
74 (EXP_74)Identity (Passive) + Credit Report + VantageScore only

Unlike unitAddress, applicationFee, and endUserType, productId is not validated by the SDK client itself — an invalid value is passed straight through to the embedded view, which validates it when the session initializes and emits a non-fatal onWarning (code INVALID_PRODUCT_ID) if it isn't one of the values above; the mount proceeds and the account's configured default product is used instead. POST /screening/submit independently re-validates productId server-side and rejects any other value with a 400, so this holds even for a caller who bypasses the SDK and posts directly with a valid JWT. See ScreeningOptions for the full type.

UnitAddress

Specifies the rental property address used for criminal background and housing court record searches. Required unless userContext.userType === 'END_USER' — that includes TSP, so a TSP-context screening mount also needs it. In practice, mounting view: 'screening' as TSP is not a supported flow regardless (the embedded view itself rejects it with SYSTEM_CONFIGURATION_ERROR — see the error table below); unitAddress is only meaningful for CONSUMER.

interface UnitAddress {
street: string; // Street address
street2?: string; // Additional address line
unit?: string; // Unit or apartment number
city: string; // City
state: string; // 2-letter state code
zip: string; // ZIP code (5-digit, ZIP+4, or 9-digit)
}
FieldTypeRequiredDescription
streetstringYesStreet address
street2stringNoAdditional address line
unitstringNoUnit or apartment number
citystringYesCity
statestringYes2-letter state code
zipstringYesZIP code (5-digit, ZIP+4, or 9-digit)
note

The full UnitAddress is collected by the SDK and stored with the screening session, but only zip is forwarded to Experian for the background/housing-court search.

ReportOptions

Passed as the report property of MountOptions. Required when view='report'.

interface ReportOptions {
id: string; // UUID of the screening report to display
}
note

report.id is not validated by sdk.mount() — omitting it does not reject the Promise. The report view simply mounts with no report loaded. Always pass report.id when mounting view: 'report'.

Callback Details

onReady()

Called when the view has loaded and is ready for user interaction.

sdk.mount("#form", {
onReady: () => {
hideLoadingSpinner();
showForm();
},
});

onVerificationSuccess(result)

Called when the identity verification step completes. This is an intermediate event — it fires after the user passes identity verification but before payment (for CONSUMER flows). For END_USER enrollment, liveKey and testKey are returned here and should be stored for use when screening consumers.

To know when an entire screening is fully complete, use onScreeningSuccess (documented under Callback Details) instead.

sdk.mount("#screening-container", {
onVerificationSuccess: async (result) => {
if (result.liveKey) {
// END_USER enrollment: store the new publishable keys
await saveEndUserKeys({ liveKey: result.liveKey, testKey: result.testKey });
}
},
});

Result object:

interface VerificationResult {
id?: string; // UUID of the screening session
/** @deprecated Always the empty string "" — the real value is never sent. Use `id` instead. */
screeningId: string;
userType: "CONSUMER" | "END_USER" | "TSP"; // User type that completed verification
liveKey?: string; // Live publishable key issued after END_USER enrollment
testKey?: string; // Test publishable key issued after END_USER enrollment
}

onVerificationFailure(failure)

Called when identity verification fails. Use reasonCode to determine the cause and present an appropriate message. reasonCode is an open string, not a closed enum — it is usually one of 'BLOCKED', 'EXPIRED', or 'ERROR' (terminal identity-verification states), but if the screening submission itself fails outright before verification can even start, reasonCode instead carries that failure's own error code (see Verification-flow error codes — the same codes onError can deliver).

sdk.mount("#screening-container", {
onVerificationFailure: (failure) => {
console.error(`Verification failed: ${failure.reasonCode}`);
},
});

Failure object:

interface VerificationFailure {
reasonCode: string; // Machine-readable failure reason
/** @deprecated Always the empty string "" — the real value is never sent. */
screeningId: string;
}

onError(error)

Called when an error occurs (network issues, validation errors, etc.).

sdk.mount("#form", {
onError: (error) => {
console.error(`[${error.code}] ${error.message}`);

if (error.recoverable) {
showRetryButton();
} else {
showContactSupport();
}
},
});

Error object:

interface SdkError {
code: string; // Stable error code — match on this, not on message
message: string; // Human-readable message; wording may change between releases
recoverable?: boolean; // Whether retrying may succeed
}

The only code guaranteed to be stable and enumerated on the global Intellirent.SdkErrorCode object today is:

CodeMeaning
PAYMENT_REQUIREDOn the report view, overloaded across two unrelated causes: the account's prepaid credit balance is exhausted, or this specific renter hasn't completed their own Stripe Checkout payment for the report. Always recoverable: false in both cases — do not retry; distinguish them by message text. See Billing for both message strings and how to route each

Intellirent.SdkErrorCode also exposes VALIDATION_INVALID_FORMAT and INVALID_PUBLISHABLE_KEY constants, but neither is currently ever delivered to onError — do not match on them. See Validation failures that don't go through onError below for how those two categories of failure actually surface.

sdk.mount("#form", {
onError: (error) => {
if (error.code === Intellirent.SdkErrorCode.PAYMENT_REQUIRED) {
// Deterministic failure — do not retry. Two unrelated causes share
// this code; branch on `message` to route each correctly.
if (error.message.includes("credit balance")) {
notifyBillingIssue(); // Account's prepaid credit balance is exhausted.
} else {
notifyRenterPaymentIncomplete(); // This renter hasn't paid for this report.
}
}
},
});

Runtime network/embedding codes. The SDK can also emit these codes via onError, none of which are on the Intellirent.SdkErrorCode object:

CodeMeaningrecoverable
IFRAME_LOAD_FAILEDThe embedded iframe's error event fired while loadingalways false
IFRAME_TIMEOUTThe iframe did not finish loading within 30 secondsalways false
IFRAME_ERRORInternal: the iframe element could not be createdalways false
TOKEN_EXCHANGE_FAILEDThe initial token-exchange request failed outright (network error, no response received) or the response body was well-formed JSON with no error.code to surface insteadtrue only for HTTP 5xx responses
TOKEN_REFRESH_FAILEDA background token refresh (used to keep the session alive) failed for the same reasons as above, before the API returned any structured errortrue only for HTTP 5xx responses
UNKNOWN_ERRORThe token-exchange (or refresh) response was a non-2xx status and the body could not be parsed as JSON at alltrue only for HTTP 5xx responses

Token exchange error codes. When the token-exchange API rejects the request with a structured error body, that response's own error.code is passed straight through to onError instead of the generic TOKEN_EXCHANGE_FAILED/TOKEN_REFRESH_FAILED/UNKNOWN_ERROR codes above. These are the codes actually returned by the API, not on Intellirent.SdkErrorCode:

CodeMeaning
MISSING_KEYNo X-Publishable-Key header was sent (internal SDK bug if seen — file a report)
INVALID_KEYThe publishable key is malformed, or not recognized for this account
KEY_INACTIVEThe publishable key exists but has been deactivated
MISSING_ORIGINNo Origin header was sent (internal SDK bug if seen in a browser)
ORIGIN_NOT_ALLOWEDThe host page's origin is not on the key's allowed-origins list
RATE_LIMITEDThe key has exceeded its per-minute request quota — retry after the delay implied by the failure
BILLING_NOT_CONFIGUREDA pk_live_* exchange was rejected because the account has neither a Metronome prepaid customer nor a Stripe connected account configured (pk_test_* is exempt). Not recoverable by retrying — configure billing for the account first. See Billing
INTERNAL_ERRORAn unexpected server-side error occurred during token exchange

Verification-flow error codes. During the screening view's identity-verification steps (device fingerprinting, OTP, KBA, and — for END_USER — post-verification account enrollment), the embedded view can also report these codes to onError. None are on Intellirent.SdkErrorCode, and none are token-exchange codes:

CodeFires whenrecoverable
FINGERPRINT_SDK_UNAVAILABLEThe device-fingerprinting SDK failed to initialize before submissionfalse
FINGERPRINT_SCRIPT_LOAD_FAILEDThe device-fingerprinting script failed to loadfalse
FINGERPRINT_COLLECTION_FAILEDDevice fingerprint data could not be collected in time for submissionfalse
AUTH_TOKEN_INVALIDThe screening submission has no valid auth token (session expired or was never established)false
SCREENING_OTP_RESEND_FAILEDRequesting a new OTP code failedtrue
SCREENING_KBA_QUESTIONS_MISSINGNo KBA questions were available to present (stepUp data was corrupted or incomplete)true
SYSTEM_INTERNAL_ERROREND_USER publishable-key generation failed after identity verification succeeded (verification itself is unaffected — onVerificationSuccess still fires); also the fallback if a later enrollment step fails without a code of its ownfalse
SYSTEM_CONFIGURATION_ERRORA TSP user tried to mount view: 'screening' — the screening flow does not support the TSP user typefalse
COMPONENT_RENDER_FAILEDA wizard step failed to render (caught by an internal error boundary); the step shows a retry optiontrue

Screening-session API codes, forwarded as-is. Submitting the initial screening form, an OTP code, or KBA answers can also deliver onError the exact code the corresponding API call returned — INVALID_OTP, INVALID_KBA, USER_BLOCKED, TOO_MANY_ATTEMPTS, VALIDATION_ERROR, IDENTITY_NOT_FOUND, and the rest of the Screening Session Codes family — rather than a code from either table above. recoverable matches that table (e.g. false for USER_BLOCKED/TOO_MANY_ATTEMPTS, true for INVALID_OTP/INVALID_KBA).

note

These codes come from libs/shared/error-handling's error-code registry (or, per above, the screening-session API's own response body) in intellirent-services — not from the SDK's own lightweight errors.ts. Treat SdkError.code as an open string in every callback; matching only on the codes documented on this page will miss legitimate errors the embedded view can report.

Validation failures that don't go through onError

These failures are not delivered to onError at all — they reject the relevant Promise directly (or throw synchronously) with a plain Error (no .code, .message only):

  • Intellirent.init(config) throws synchronously (not a rejected Promise) if publishableKey doesn't match the pk_(live|test)_<16+ chars> format. Wrap init() in try/catch.
  • sdk.mount(selector, options)'s returned Promise rejects if screening.unitAddress is missing/invalid for a CONSUMER screening view, if screening.applicationFee is not a positive integer ≤ 1,000,000, or if screening.endUserType is not one of 'INDEPENDENT_OWNER' / 'REAL_ESTATE_AGENT' / 'PROPERTY_MANAGEMENT' (when provided). Wrap the await sdk.mount(...) call in try/catch.
  • sdk.mount(selector, options)'s returned Promise also rejects if selector doesn't match an element currently in the DOM (Container element not found: <selector>), or if an instance is already mounted on this sdk — one IntellirentSDK instance holds at most one live view at a time; call sdk.unmount() before mounting again (Iframe is already mounted. Call unmount() first to mount in a different container.).
try {
const sdk = Intellirent.init({ publishableKey, userContext });
const instance = await sdk.mount("#container", {
view: "screening",
screening: { unitAddress },
});
} catch (error) {
// error is a plain Error — check error.message, there is no error.code here
console.error(error.message);
}

onWarning(warning)

Called when a non-fatal warning occurs, such as invalid prefill fields that were silently ignored.

sdk.mount("#form", {
onWarning: (warning) => {
console.warn(`[${warning.code}] ${warning.message}`);
if (warning.invalidFields) {
console.warn("Invalid fields:", warning.invalidFields);
}
},
});

Warning object:

interface SdkWarning {
code: string; // Warning code identifier
message: string; // Human-readable message
invalidFields?: string[]; // Field names that triggered the warning
}

Known warning codes

CodeFires whenReachable via the packaged SDK?
INVALID_PREFILL_FIELDSOne or more screening.prefill fields are unknown, wrong type, or otherwise not allowed — see Screening Pre-fillYes
IGNORED_END_USER_TYPEscreening.endUserType was a valid value but userContext.userType isn't 'END_USER'Yes
INVALID_PRODUCT_IDscreening.productId isn't one of the values in ProductId — see productIdYes (not validated client-side)
INVALID_APPLICATION_FEEThe embedded view received a screening.applicationFee it considers invalidNo — the SDK client validates applicationFee before the view ever mounts, rejecting mount()'s Promise instead of letting an invalid value reach the view; only a non-standard integration bypassing the packaged SDK bundle could reach this
INVALID_END_USER_TYPEThe embedded view received a screening.endUserType it considers invalidNo — same reasoning as INVALID_APPLICATION_FEE, since the SDK client validates endUserType the same way before mount
DELEGATION_UNSUPPORTEDhandlePrintRequested and/or handleDownloadRequested was provided, but the embedded form build didn't acknowledge takeover of that action on READY — see Takeover HandlersYes — invalidFields lists which of 'print'/'download' weren't honored

onResize(dimensions)

Called when the embedded content's height or width changes (useful for dynamic layouts). Receives a ResizeDimensions object.

sdk.mount("#form", {
onResize: ({ width, height }) => {
console.log(`Form resized to ${width}x${height}`);
},
});
interface ResizeDimensions {
width: number; // Content width in pixels
height: number; // Content height in pixels
}

The SDK enforces a 200px minimum on the mounted iframe's actual rendered height. dimensions.height reflects the raw value reported by the embedded view and is not clamped to that minimum — if you size a wrapper element from this callback, apply the same 200px floor yourself to avoid the wrapper and the iframe disagreeing on height.

If the embedded content reports a width wider than the iframe's actual rendered width, the SDK logs a one-time-per-overflow console.warn noting that content is being clipped and to verify the host container width or that the embedded layout is fully responsive. This is a console-only diagnostic — it doesn't invoke onWarning or any other callback — useful when debugging a form that appears cut off.

onChange(field)

Called when a form field value changes.

sdk.mount("#form", {
onChange: (field) => {
console.log(`Field changed: ${field}`);
},
});

onStepStart(step) / onStepComplete(step)

Called when a wizard step begins or completes. Common step values include 'terms', 'information', 'payment', 'verify'.

sdk.mount("#form", {
onStepStart: (step) => console.log(`Step started: ${step}`),
onStepComplete: (step) => console.log(`Step completed: ${step}`),
});

onScreeningSuccess(result)

Called when the entire screening flow is complete. This is the terminal success event — use it to capture the report ID and trigger any downstream logic.

  • CONSUMER: fires after payment completes, unless your account has been configured by relay to waive the payment step, in which case it fires immediately after identity verification and onPaymentSuccess never fires for that session
  • END_USER: fires after identity verification completes (no payment required)
sdk.mount("#screening-container", {
onScreeningSuccess: (result) => {
// Store result.id — required to mount the report view later
console.log("Report ID:", result.id);
console.log("User type:", result.userType);
saveReportId(result.id);
},
});

Result object:

interface ScreeningResult {
id?: string; // UUID of the screening report — store this to mount the report view later
userType: "CONSUMER" | "END_USER" | "TSP"; // User type that completed the screening
/** @deprecated Always the empty string "" — the real value is never sent. Use `id` instead. */
screeningId: string;
}

onPaymentSuccess(result)

Called when a payment step completes successfully.

sdk.mount("#screening-container", {
onPaymentSuccess: (result) => {
console.log("Payment completed. Transaction:", result.transactionId);
console.log("Amount:", result.amount);
},
});

Result object:

interface PaymentResult {
transactionId: string; // Stripe transaction ID
amount: number; // Amount charged in cents
}

onReportShared(event)

Called when the consumer consents to share their screening report with the end user. Use this to update your UI or trigger downstream workflows.

sdk.mount("#screening-container", {
onReportShared: (event) => {
console.log("Report shared:", event.reportId);
console.log("Shared at:", event.sharedAt);
},
});

Event object:

interface ReportSharedEvent {
reportId: string; // UUID of the screening session
sharedAt: string; // ISO 8601 timestamp when sharing was consented
}

onReportRevoked(event)

Called when the consumer revokes sharing of their report. The end user will lose access to the report.

sdk.mount("#screening-container", {
onReportRevoked: (event) => {
console.log("Sharing revoked:", event.reportId);
console.log("Revoked at:", event.revokedAt);
},
});

Event object:

interface ReportRevokedEvent {
reportId: string; // UUID of the screening session
revokedAt: string; // ISO 8601 timestamp when sharing was revoked
}

Takeover Handlers (Native WebViews)

The embedded view normally prints via the browser's own window.print() and downloads files via an invisible anchor click. Both are standard browser behavior — and both are unreliable or silently do nothing inside a native mobile WebView (iOS WKWebView, Android WebView), which is why they need special attention if you're embedding the SDK in a native app. See WebView Integration for the full picture; this section covers just the two mount options.

handlePrintRequested and handleDownloadRequested are deliberately named handle* rather than on*. Every other option in the table above is a passive notification — providing it doesn't change what the form does. These two are not: providing a handle* option suppresses the form's browser-native default and hands the action to you instead. Provide one and do nothing in it, and the user's print/download button will appear to do nothing. The two are independent — you can take over one and leave the other on the default browser behavior.

Delegation only takes effect once the embedded form build acknowledges it on READY. If you provide a handle* option but a stale form build predates delegation support, the form keeps using its browser-native default and your handler is never invoked — silently, except for a non-fatal onWarning with code DELEGATION_UNSUPPORTED (invalidFields lists which of 'print'/'download' weren't honored) — see the Known warning codes table under onWarning above.

handlePrintRequested()

When provided, the embedded view never calls window.print(). Your handler is invoked whenever the user asks to print — including the Ctrl/Cmd+P interception described in the note above — and your code is responsible for producing the printout, however that fits your app.

sdk.mount("#form", {
handlePrintRequested: () => {
// Your code — handle the print request however fits your app
},
});

handleDownloadRequested(download)

When provided, the embedded view never triggers a browser download. Your handler receives a DownloadRequest — the file's URL and a suggested filename — and your code is responsible for saving or sharing the file.

Do not persist the report on your own systems

This is a screening report sourced from Experian. Experian's terms prohibit retaining these reports outside of delivering them to the requesting consumer or end user — hand the file straight to that person (share sheet, save dialog) and discard your local copy; don't archive, cache, or log it server-side. See WebView Integration for detail.

sdk.mount("#form", {
handleDownloadRequested: ({ url, filename }) => {
// Your code — retrieve `url` and get it to the user as `filename`
},
});
interface DownloadRequest {
url: string; // Short-lived presigned URL — see note below
filename: string; // Suggested filename for the saved file
}

The url is a short-lived presigned S3 URL: authentication is embedded in its query string, so a plain unauthenticated GET — from any HTTP client, including your native host, outside the iframe's CORS/cookie context — retrieves the file with no cookies, headers, or extra credentials. Fetch it promptly; it expires within minutes.

Omit either option (or pass undefined) to keep today's default browser behavior for that action — existing integrations are unaffected.

Return Value

Returns a Promise that resolves to an IframeInstance:

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

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


sdk.unmount()

Unmounts the view if mounted. The SDK can be reused to mount again.

sdk.unmount();

// Can mount again later
await sdk.mount("#different-container");

sdk.destroy()

Destroys the SDK instance completely. Unmounts the view and prevents future mount() calls.

sdk.destroy();

// This will throw an error:
await sdk.mount("#form"); // Error: SDK has been destroyed

sdk.on(event, listener) / sdk.off(event, listener)

Subscribe to lifecycle events. event is a LifecycleEventType and listener is a LifecycleEventListener whose payload type is determined by the event. See Lifecycle Events for details.

const unsubscribe = sdk.on("mounted", ({ selector, instanceId }) => {
console.log(`Mounted at ${selector}`);
});

// Later: unsubscribe
unsubscribe();