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:
| Option | Type | Required | Description |
|---|---|---|---|
publishableKey | string | Yes | Your publishable API key (pk_live_* or pk_test_*) |
userContext | UserContext | Yes | User identity and type for access control |
sessionToken | string | No | Single-use session grant (sgt_live_*/sgt_test_*) minted by your backend, proving the mount was server-authorized. See Session Tokens. |
onTokenExpired | function | No | Called 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 Type | Description | Access Level |
|---|---|---|
TSP | Tenant screening provider (dashboard admin) | Key management, origins, theme settings |
END_USER | Operators (agents, property managers) | All screenings on account, after verified |
CONSUMER | Individuals 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 environmentpk_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
| Parameter | Type | Required | Description |
|---|---|---|---|
selector | string | Yes | CSS selector for the container |
options | MountOptions | No | Callbacks and configuration |
Mount Options
| Option | Type | Required | Description |
|---|---|---|---|
view | SdkView | No | View to display: 'screening' (default), 'dashboard', 'reports', 'report' |
screening | ScreeningOptions | No | Screening configuration: prefill, unitAddress, applicationFee, endUserType, and productId |
report | ReportOptions | No | Report configuration: id (required when view='report') |
onReady | function | No | Called when the view is fully loaded and ready for interaction |
onVerificationSuccess | function | No | Called when the identity verification step completes; returns liveKey/testKey for END_USER enrollment |
onVerificationFailure | function | No | Called when identity verification fails |
onScreeningSuccess | function | No | Called when the entire screening flow is complete; use this to capture the report ID |
onPaymentSuccess | function | No | Called when a payment step completes successfully |
onError | function | No | Called when a fatal error occurs |
onWarning | function | No | Called on non-fatal warnings (e.g., invalid prefill fields) |
onReportShared | function | No | Called when the consumer consents to share their report |
onReportRevoked | function | No | Called when the consumer revokes report sharing |
onResize | function | No | Called when content height or width changes |
onChange | function | No | Called when a form field value changes |
onStepStart | function | No | Called when a wizard step begins |
onStepComplete | function | No | Called when a wizard step completes |
handlePrintRequested | function | No | Takes over printing — see Takeover Handlers |
handleDownloadRequested | function | No | Takes over file downloads — see Takeover Handlers |
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.
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.
| View | Description | Required Options |
|---|---|---|
dashboard | Key management, origins, and theme settings | None |
screening | Identity verification flow (default) | screening.unitAddress (required unless userType === 'END_USER') |
reports | List of accessible screening reports | None |
report | View a specific screening report | report.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:
1to1,000,000($0.01–$10,000.00) - Invalid values (negative, zero, non-integer,
NaN,Infinity, or above1,000,000) reject themount()Promise with a plainErrorbefore the iframe mounts — see Validation failures that don't go throughonError
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 nullis treated the same as omitting the option- On a non-
END_USERmount (i.e.userContext.userTypeis'CONSUMER'or'TSP'), a valid value is ignored — there is no selection screen to skip — and a non-fatalonWarningfires with codeIGNORED_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 throughonError
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)
}
| Field | Type | Required | Description |
|---|---|---|---|
street | string | Yes | Street address |
street2 | string | No | Additional address line |
unit | string | No | Unit or apartment number |
city | string | Yes | City |
state | string | Yes | 2-letter state code |
zip | string | Yes | ZIP code (5-digit, ZIP+4, or 9-digit) |
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
}
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:
| Code | Meaning |
|---|---|
PAYMENT_REQUIRED | On 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:
| Code | Meaning | recoverable |
|---|---|---|
IFRAME_LOAD_FAILED | The embedded iframe's error event fired while loading | always false |
IFRAME_TIMEOUT | The iframe did not finish loading within 30 seconds | always false |
IFRAME_ERROR | Internal: the iframe element could not be created | always false |
TOKEN_EXCHANGE_FAILED | The 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 instead | true only for HTTP 5xx responses |
TOKEN_REFRESH_FAILED | A background token refresh (used to keep the session alive) failed for the same reasons as above, before the API returned any structured error | true only for HTTP 5xx responses |
UNKNOWN_ERROR | The token-exchange (or refresh) response was a non-2xx status and the body could not be parsed as JSON at all | true 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:
| Code | Meaning |
|---|---|
MISSING_KEY | No X-Publishable-Key header was sent (internal SDK bug if seen — file a report) |
INVALID_KEY | The publishable key is malformed, or not recognized for this account |
KEY_INACTIVE | The publishable key exists but has been deactivated |
MISSING_ORIGIN | No Origin header was sent (internal SDK bug if seen in a browser) |
ORIGIN_NOT_ALLOWED | The host page's origin is not on the key's allowed-origins list |
RATE_LIMITED | The key has exceeded its per-minute request quota — retry after the delay implied by the failure |
BILLING_NOT_CONFIGURED | A 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_ERROR | An 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:
| Code | Fires when | recoverable |
|---|---|---|
FINGERPRINT_SDK_UNAVAILABLE | The device-fingerprinting SDK failed to initialize before submission | false |
FINGERPRINT_SCRIPT_LOAD_FAILED | The device-fingerprinting script failed to load | false |
FINGERPRINT_COLLECTION_FAILED | Device fingerprint data could not be collected in time for submission | false |
AUTH_TOKEN_INVALID | The screening submission has no valid auth token (session expired or was never established) | false |
SCREENING_OTP_RESEND_FAILED | Requesting a new OTP code failed | true |
SCREENING_KBA_QUESTIONS_MISSING | No KBA questions were available to present (stepUp data was corrupted or incomplete) | true |
SYSTEM_INTERNAL_ERROR | END_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 own | false |
SYSTEM_CONFIGURATION_ERROR | A TSP user tried to mount view: 'screening' — the screening flow does not support the TSP user type | false |
COMPONENT_RENDER_FAILED | A wizard step failed to render (caught by an internal error boundary); the step shows a retry option | true |
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).
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) ifpublishableKeydoesn't match thepk_(live|test)_<16+ chars>format. Wrapinit()intry/catch.sdk.mount(selector, options)'s returned Promise rejects ifscreening.unitAddressis missing/invalid for aCONSUMERscreeningview, ifscreening.applicationFeeis not a positive integer ≤ 1,000,000, or ifscreening.endUserTypeis not one of'INDEPENDENT_OWNER'/'REAL_ESTATE_AGENT'/'PROPERTY_MANAGEMENT'(when provided). Wrap theawait sdk.mount(...)call intry/catch.sdk.mount(selector, options)'s returned Promise also rejects ifselectordoesn't match an element currently in the DOM (Container element not found: <selector>), or if an instance is already mounted on thissdk— oneIntellirentSDKinstance holds at most one live view at a time; callsdk.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
| Code | Fires when | Reachable via the packaged SDK? |
|---|---|---|
INVALID_PREFILL_FIELDS | One or more screening.prefill fields are unknown, wrong type, or otherwise not allowed — see Screening Pre-fill | Yes |
IGNORED_END_USER_TYPE | screening.endUserType was a valid value but userContext.userType isn't 'END_USER' | Yes |
INVALID_PRODUCT_ID | screening.productId isn't one of the values in ProductId — see productId | Yes (not validated client-side) |
INVALID_APPLICATION_FEE | The embedded view received a screening.applicationFee it considers invalid | No — 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_TYPE | The embedded view received a screening.endUserType it considers invalid | No — same reasoning as INVALID_APPLICATION_FEE, since the SDK client validates endUserType the same way before mount |
DELEGATION_UNSUPPORTED | handlePrintRequested and/or handleDownloadRequested was provided, but the embedded form build didn't acknowledge takeover of that action on READY — see Takeover Handlers | Yes — 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 andonPaymentSuccessnever fires for that sessionEND_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.
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
}
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();