Step 5: Sharing Reports
A consumer's completed report can be shared with more than one end user account (agents, property managers) under the same TSP. Granting access and managing access are two different actions, handled by two different views:
| Action | View | Who sees it |
|---|---|---|
| Grant access to a new end user | share | The consumer, deciding on one specific end user's request |
| Review and revoke existing access | report (built-in panel) | The consumer, viewing their own report |
There is no single view that does both. The report view's recipient panel intentionally has no "add a recipient" control — it only shows who already has access and lets the consumer take it away. Granting a new end user is what the share view is for.
Granting access: the share view
When to use it — reusing an existing report, not completing a new one
A consumer's first screening for a given end user already ends with its own consent step under that same publishable key — nothing more is needed there. The share view is for the opposite case: a consumer who already has a completed report (from a prior screening, typically under a different end user or none at all) wants to apply somewhere new. Instead of a full fresh view: 'screening' — identity verification, payment — for an end user they've never screened under, they consent to reuse the report they already have.
This only works if your own system already knows the consumer has a usable report before you offer it — in practice, save a userId → reportId record when a screening completes, and check it the next time that consumer starts a new application.
Mount view: 'share' with share: { reportId } to show a focused, mobile-first "agree or decline" decision for that existing report and one new recipient:
// Mounted for a consumer your system has already matched to an existing
// report (userId → reportId), applying to a new end user they haven't
// screened under before
const sdk = Intellirent.init({
publishableKey: "pk_live_eu_xxxxxxxxxxxxxxxx", // the NEW end user's own key
userContext: { userId: consumerUserId, userType: "CONSUMER" },
});
await sdk.mount("#share-container", {
view: "share",
share: { reportId: "550e8400-e29b-41d4-a716-446655440000" }, // their existing report
onReportShared: (event) => {
console.log("Shared with:", event.recipientAccountDisplayName);
},
onReportShareDeclined: (event) => {
console.log("Declined at:", event.declinedAt);
},
});
There's no recipient field — the publishable key is the recipient
ShareOptions has exactly one field, reportId — nothing to set to say "share with this end user." The recipient is determined entirely by which publishable key you initialized the SDK with, the same key-scoping the report/reports views already use (see Report Visibility by User Type and Key). Mount the share view with the new end user's own pk_live_eu_*/pk_test_eu_* key, and agreeing grants access to that account and no other — there's no picker inside the view for the consumer to redirect the grant elsewhere.
So mount the share view only on a page or link already scoped to one end user — never on a generic or TSP-level page where the consumer would need to choose among several. If you need to offer that choice, build the picker in your own UI and load the share view (with the chosen end user's key) after the consumer picks one.
Specifying the property address (optional)
The share view's "Desired rental" field falls back to whatever address the consumer captured on their original screening submission. Pass share.unitAddress when the invite is for a different unit or listing than the one they originally screened for — for example, a TSP or end user managing several listings who wants to reuse an existing report for one specific property.
await sdk.mount("#share-container", {
view: "share",
share: {
reportId: "550e8400-e29b-41d4-a716-446655440000",
unitAddress: {
street: "456 Oak Ave",
city: "New York",
state: "NY",
zip: "10001",
},
},
onReportShared: (event) => {
console.log("Shared with:", event.recipientAccountDisplayName);
},
});
unitAddress takes the same shape as screening.unitAddress — see unitAddress Fields — and goes through the same validation whenever you pass it: an invalid shape rejects the mount() Promise with a plain Error, the same as an invalid screening.unitAddress (see SDK Methods).
Suggested entry points
- Returning-applicant Apply-Now flow. When a consumer starts an application for a new listing, check your own records for an existing report under that
userIdfirst. If one exists, mountview: 'share'with it under the new end user's key instead of a freshview: 'screening'. If none exists, fall back to a normal screening (see Step 3: Screen a Consumer). - End-user invite link. An end user who already knows an applicant has a report elsewhere sends an invite link scoped to their own publishable key and that
reportId. Opening it and agreeing grants exactly that end user, by construction. - Multiple end users over time. Each mount is scoped to one recipient, so reusing a report across several end users just means one
shareview mount per new end user. Each resulting grant is independent — see Two-clock access below.
Agree vs. decline
- Agree grants access immediately — there's nothing else to specify, since the recipient is already whichever end user's key you mounted with. It starts that recipient's 24-month view window and fires
onReportShared. - Decline grants nothing and isn't remembered anywhere. It fires
onReportShareDeclined, but opening the same or a different share link for the same report/end-user pair afterward shows the same agree/decline choice again, not a "previously declined" state — track declines in your own system if that matters to you.
Both actions disable once either is selected, until any in-flight request resolves — no double-submit.
Reviewing and revoking access: the report view
The report view (mounted by the consumer for their own report) includes a built-in recipient-management panel: every current recipient's status, consent date, and access-expiry, with a per-recipient revoke action. End users viewing a shared report never see this panel — it's consumer-only.
const sdk = Intellirent.init({
publishableKey: "pk_live_xxxxxxxxxxxxxxxx", // the consumer's own key
userContext: { userId: consumerUserId, userType: "CONSUMER" },
});
await sdk.mount("#report-container", {
view: "report",
report: { id: "550e8400-e29b-41d4-a716-446655440000" },
onReportRevoked: (event) => {
console.log("Revoked for:", event.recipientAccountDisplayName);
},
});
Revoking is permanent and scoped to that one recipient — revoking one end user never affects any other end user's existing access, and a revoked recipient can't be re-granted the same report, including by mounting the share view for them again.
Two-clock access
Every share carries two independent expiry clocks:
- The consumer's own report validity — 30 days from report completion. Once this lapses, the consumer loses all access to the report itself, including sharing, reviewing, or revoking recipients.
- Each recipient's view window — 24 months, anchored to when that recipient's share was consented, not to report completion. A recipient keeps access well after the consumer's own 30-day window closes, and independently of every other recipient's window.
See Error Codes for how each clock's expiry surfaces (SCREENING_REPORT_EXPIRED vs. REPORT_SHARING_EXPIRED).
Next Steps
- SDK Methods — Full reference for
ShareOptions,onReportShareDeclined, and the recipient-management panel - Type Reference — TypeScript declarations for
ShareOptions,ReportShareDeclinedEvent, and the rest of the sharing types - Step 4: View Reports — Mounting the
report/reportsviews and how visibility is scoped by user type and key