<iframe>
API messages
All messages sent to and from the LoanPASS app are plain JavaScript objects, with a message
field indicating the type of message. Note that we may add more messages in the future, so to future-proof your integration, ensure unknown message types are ignored!
Sendable messages
connect
Connect to the LoanPASS <iframe>
API. This message must be sent to the LoanPASS app before any other messages, and this message must be sent before any messages will be sent from LoanPASS back to your app.
After sending connect
, the <iframe>
will respond with the listening
message once it's ready to receive more messages.
It's recommended that this message is sent in an event listener that listens for the <iframe>
's load
event.
Fields
None
Example
iframe.addEventListener("load", function () {
iframe.contentWindow.postMessage(
{
message: "connect",
},
loanpassOrigin
);
});
log-in
Automatically log the user in to LoanPASS with the given credentials.
NOTE: If the user is already signed in to the LoanPASS UI, then this message may cause them to log out and be logged in with the specified credentials. When this happens, the <iframe>
may be reloaded. To account for this properly, you should wait for the listening
message again before sending any more messages.
SECURITY NOTE: Like all messages, the log-in
message is handled entirely client-side, so the given email and password will be sent to the server in exactly the same way as if the user had entered the email and password themselves. However, for security purposes, that leads to 2 details to consider:
- The end user can get the credentials. A tech-savvy user could trivially use the Web Inspector in their browser to find the email and password that were sent to the
<iframe>
(say, by viewing the "Network" tab and looking for the "log in" API call). - The credentials should be stored and sent securely. The password for the user should be considered a secret, so it should be treated as such and standard best practices should be used.
Fields
clientAccessId
: The client access ID to log in as. This should be the same as the client access ID used to embed the<iframe>
.emailAddress
: The email address of the account to sign in as.password
: The password of the account to sign in as.
Example
Signing in a user
iframe.contentWindow.postMessage(
{
message: "log-in",
clientAccessId: "example-client",
emailAddress: "user@example.com",
password: "password1234",
},
loanpassOrigin
);
Signing in a user on page load
// Track the current state of the user:
// 1. "pending": iframe just added to page, user may be logged out or logged in
// 2. "logged-in": `log-in` message sent, user is now logged in
let userState = "pending"; // "pending" | "logged-in"
const loanpassOrigin = "https://app.loanpass.io";
const clientAccessId = "example-client";
const emailAddress = "user@example.com";
const password = "password1234";
window.addEventListener("load", function () {
console.log("page loaded");
const iframe = document.createElement("iframe");
const handleListening = () => {
switch (userState) {
case "pending":
console.log("sending log in message...");
iframe.contentWindow.postMessage(
{
message: "log-in",
clientAccessId,
emailAddress,
password,
},
loanpassOrigin
);
userState = "logged-in";
break;
case "logged-in":
console.log("log in completed");
break;
}
};
window.addEventListener("message", function (event) {
if (event.origin !== loanpassOrigin) {
console.warn("received message from unexpected origin", event);
return;
}
console.log("received message", event.data);
switch (event.data.message) {
case "listening":
handleListening();
break;
}
});
iframe.src = `${loanpassOrigin}/frame-redirect/${clientAccessId}`;
iframe.addEventListener("load", function () {
console.log("iframe load event fired");
if (iframe.contentWindow == null) {
return;
}
console.log("connecting...");
iframe.contentWindow.postMessage(
{
message: "connect",
},
loanpassOrigin
);
});
document.getElementById("iframe-container").appendChild(iframe);
});
log-out
Log out the current user if they are logged in.
NOTE: Sending this message may trigger the <iframe>
to reload! To continue receiving messages after sending the log-out
message, make sure the connect
message is sent after the load
event triggers on the <iframe>
. See the connect
message for more details.
Fields
clientAccessId
: The client access ID of the login page to show.
Example
iframe.contentWindow.postMessage(
{
message: "log-out",
clientAccessId: "example-client",
},
loanpassOrigin
);
See log-in
for more details about logging the user back in after logging out.
enable-price-locking
Set a flag to show a "Lock Request" button in the UI. When clicked, the LoanPASS app will send a price-lock
message back to your app. That is, sending enable-price-lock
doesn't itself handle price locking, it just enables integrators to grab the pricing data to handle price locking through another system.
After this message is sent and after filling out the fields on the "Price a Loan" page, clicking into a product, then clicking one of the prices in the table, the modal that pops up will have a "Lock Request" button at the bottom:
The label of the button can be changed by setting the lockRequestLabel
field on the message.
enable-float-requests
Set a flag to allow the "Float Request" button to send float requests back to the parent application.
When viewing a pipeline record on the "Price a Loan" page, the user is presented with a "Submit Float" button. Before sending the enable-float-requests
message, the "Submit Float" button will only create a new pipeline scenario for the selected pipeline record. After sending the enable-float-requests
message, the "Submit Float" button will both create a new pipeline scenario as well as post a float-request
message back to the parent application.
Example
iframe.contentWindow.postMessage(
{
message: "enable-float-requests",
},
loanpassOrigin
);
Fields
lockRequestLabel
(optional): A string indicating what label to use for the price locking button. Defaults to "Lock Request". The same label will also be used after clicking the button, where the label will change to say "${lockRequestLabel} Sent
".
Example
iframe.contentWindow.postMessage(
{
message: "enable-price-locking",
lockRequestLabel: "Lock Request", // optional
},
loanpassOrigin
);
set-fields
Fill in fields on the "Price a Loan" page with preset values. Calling set-fields
is very similar to loading an existing scenario, except the data is controlled by the integration rather than the LoanPASS backend.
Fields
fields
: An array of specifying fields to set and their values. The format matches the.creditApplicationFields[]
schema from the/execute-product
and/execute-summary
Public API endpoints.fieldId
: The field ID.value
: An object describing the value of the field, with atype
field indicating the type of value.
Example
iframe.contentWindow.postMessage(
{
message: "set-fields",
fields: [
{
fieldId: "field@occupancy-type",
value: {
type: "enum",
enumTypeId: "occupancy-type",
variantId: "primary-residence",
},
},
{
fieldId: "field@desired-loan-term",
value: {
type: "duration",
unit: "months",
count: "6",
},
},
{
fieldId: "field@number-of-units",
value: {
type: "number",
value: "1",
},
},
],
},
loanpassOrigin
);
create-pipeline-record
Creates a new pipeline record using the current state on the "Price a Loan" page including field values, selected product, and selected rate/lock period.
Fields
pipelineFieldValues
: An array of pipeline-only fields to set and their values. The format matches the.creditApplicationFields[]
schema from the/execute-product
and/execute-summary
Public API endpoints, and the fields are defined in the "Pipeline Settings" tab of the "Fields" page.
Example
iframe.contentWindow.postMessage(
{
message: "create-pipeline-record",
pipelineFieldValues: [
{
fieldId: "field@borrower-last-name",
value: {
type: "string",
value: "Smith",
},
},
{
fieldId: "field@loan-number",
value: {
type: "string",
value: "12345",
},
},
],
},
loanpassOrigin
);
set-pipeline-record
Loads an existing pipeline record on the "Price a Loan" page. You may choose to pass an optional list of field values to overwrite the values loaded by the pipeline record.
Fields
pipelineRecordId
: The ID of the pipeline record you want to load.overrideCreditApplicationFields
: An optional array of fields to set and their values. The format matches the.creditApplicationFields[]
schema from the/execute-product
and/execute-summary
Public API endpoints. If left empty the pipeline record will use the values stored within itself.
Examples
- Loading a Record
iframe.contentWindow.postMessage(
{
message: "set-pipeline-record-id",
pipelineRecordId: "51",
// This will retain the field values saved in the pipeline record
overrideCreditApplicationFields: [],
},
loanpassOrigin
);
- Overriding Fields
iframe.contentWindow.postMessage(
{
message: "set-pipeline-record-id",
pipelineRecordId: "51",
// This will override fields stored in the pipeline record
overrideCreditApplicationFields: [
{
fieldId: "field@occupancy-type",
value: {
type: "enum",
enumTypeId: "occupancy-type",
variantId: "primary-residence",
},
},
{
fieldId: "field@desired-loan-term",
value: {
type: "duration",
unit: "months",
count: "6",
},
},
{
fieldId: "field@number-of-units",
value: {
type: "number",
value: "1",
},
},
],
},
loanpassOrigin
);
Receivable messages
listening
Sent after the <iframe>
receives the connect
message and is ready to receive more messages.
logged-in
Sent after succesfully logging in with a log-in
message.
log-in-error
Sent after a failed log in attempt using the log-in
message.
price-lock
Sent when a user clicks the "Lock Request" button in the UI after the enable-price-locking
message is sent.
Fields
role
: Contains details about the user's active role.id
: The role ID.name
The display name of the role.
pricingProfile
: Contains details about the user's active pricing profile.id
: The pricing profile ID.name
The display name of the pricing profile.
product
: Contains details about the product that was price locked.id
: The product ID.name
The display name of the product.
investor
: Contains details about the investor of the product that was price locked.id
: The investor's ID.name
: The display name of the investor.
scenario
: The details about the price scenario that was locked. The schema matches the.priceScenarios[]
schema returned from the/execute-product
Public API endpoint.status
: The status of the price scenario, such asapproved
,rejected
, etc.adjustedRate
: The rate with rate adjustments applied.adjustedPrice
The price with price adjustments applied.priceScenarioFields
: An array of price scenario fields and values.fieldId
: The field ID.value
: An object describing the value of the field, ornull
if the field has no value.
calculatedFields
: An array of calculated fields and their values for this price scenario.fieldId
: The calculated field ID.value
: An object describing the value of the field, ornull
if the field has no value.
creditApplicationFields
: An array of fields and their values that were filled in by the user for the price scenario. This corresponds to thecreditApplicationFields
field for the/execute-product
Public API endpoint.fieldId
: The input's field ID.value
: An object describing the value of the field.
Example
{
"message": "price-lock",
"role": {
"id": "11",
"name": "Loan Officer"
},
"pricingProfile": {
"id": "22",
"name": "Standard"
},
"investor": {
"id": "123",
"name": "Test Investor",
"code": "TI",
"isPricingEnabled": true
},
"product": {
"id": "1234",
"code": "EXAMPLE",
"name": "Example Product",
"description": "Example product",
"activationTimestamp": "2021-01-01T00:00:00Z",
"deactivationTimestamp": null,
"investorId": "123"
},
"scenario": {
"id": "00000000-0000-0000-0000-000000000000",
"priceScenarioFields": [
{
"fieldId": "base-interest-rate",
"value": {
"type": "number",
"value": "1.0"
}
},
{
"fieldId": "rate-lock-period",
"value": {
"type": "duration",
"count": "15",
"unit": "days"
}
},
{
"fieldId": "base-price",
"value": {
"type": "number",
"value": "101.000"
}
}
],
"calculatedFields": [
{
"fieldId": "calc@fsb-lpmi-refinance",
"value": {
"type": "number",
"value": "0.000"
}
},
{
"fieldId": "calc@fsb-jumbo-max-price",
"value": null
},
{
"fieldId": "calc-field@ah-va-purch-tier",
"value": {
"type": "number",
"value": "4"
}
}
],
"adjustedRate": "1.75",
"adjustedRateLockPeriod": {
"count": "15",
"unit": "days"
},
"adjustedPrice": "101.000",
"status": "approved",
"priceAdjustments": [
{
"ruleId": "1234",
"amount": "0.25",
"description": "Price adjustment 1"
},
{
"ruleId": "5678",
"amount": "0.25",
"description": "Price adjustment 2"
}
],
"marginAdjustments": [
{
"ruleId": "12345",
"amount": "-0.300",
"description": "Margin adjustment"
}
],
"rateAdjustments": [],
"stipulations": []
},
"creditApplicationFields": [
{
"fieldId": "field@occupancy-type",
"value": {
"type": "enum",
"enumTypeId": "occupancy-type",
"variantId": "primary-residence"
}
},
{
"fieldId": "field@loan-purpose",
"value": {
"type": "enum",
"enumTypeId": "loan-purpose",
"variantId": "purchase"
}
},
{
"fieldId": "field@decision-credit-score",
"value": {
"type": "number",
"value": "750"
}
},
{
"fieldId": "field@state",
"value": {
"type": "string",
"format": "us-state-code",
"value": "TX"
}
},
{
"fieldId": "field@property-type",
"value": {
"type": "enum",
"enumTypeId": "property-type",
"variantId": "single-family"
}
},
{
"fieldId": "field@base-loan-amount",
"value": {
"type": "number",
"value": "400000.00"
}
}
]
}
float-request
Sent when a user clicks the "Submit Float" button in the UI after the enable-float-requests
message is sent. The shape of this message is the same as the price-lock
message.
Fields
role
: Contains details about the user's active role.id
: The role ID.name
The display name of the role.
pricingProfile
: Contains details about the user's active pricing profile.id
: The pricing profile ID.name
The display name of the pricing profile.
product
: Contains details about the product that was price locked.id
: The product ID.name
The display name of the product.
investor
: Contains details about the investor of the product that was price locked.id
: The investor's ID.name
: The display name of the investor.
scenario
: The details about the price scenario that was locked. The schema matches the.priceScenarios[]
schema returned from the/execute-product
Public API endpoint.status
: The status of the price scenario, such asapproved
,rejected
, etc.adjustedRate
: The rate with rate adjustments applied.adjustedPrice
The price with price adjustments applied.priceScenarioFields
: An array of price scenario fields and values.fieldId
: The field ID.value
: An object describing the value of the field, ornull
if the field has no value.
calculatedFields
: An array of calculated fields and their values for this price scenario.fieldId
: The calculated field ID.value
: An object describing the value of the field, ornull
if the field has no value.
creditApplicationFields
: An array of fields and their values that were filled in by the user for the price scenario. This corresponds to thecreditApplicationFields
field for the/execute-product
Public API endpoint.fieldId
: The input's field ID.value
: An object describing the value of the field.
Example
{
"message": "float-request",
"role": {
"id": "11",
"name": "Loan Officer"
},
"pricingProfile": {
"id": "22",
"name": "Standard"
},
"investor": {
"id": "123",
"name": "Test Investor",
"code": "TI",
"isPricingEnabled": true
},
"product": {
"id": "1234",
"code": "EXAMPLE",
"name": "Example Product",
"description": "Example product",
"activationTimestamp": "2021-01-01T00:00:00Z",
"deactivationTimestamp": null,
"investorId": "123"
},
"scenario": {
"id": "00000000-0000-0000-0000-000000000000",
"priceScenarioFields": [
{
"fieldId": "base-interest-rate",
"value": {
"type": "number",
"value": "1.0"
}
},
{
"fieldId": "rate-lock-period",
"value": {
"type": "duration",
"count": "15",
"unit": "days"
}
},
{
"fieldId": "base-price",
"value": {
"type": "number",
"value": "101.000"
}
}
],
"calculatedFields": [
{
"fieldId": "calc@fsb-lpmi-refinance",
"value": {
"type": "number",
"value": "0.000"
}
},
{
"fieldId": "calc@fsb-jumbo-max-price",
"value": null
},
{
"fieldId": "calc-field@ah-va-purch-tier",
"value": {
"type": "number",
"value": "4"
}
}
],
"adjustedRate": "1.75",
"adjustedRateLockPeriod": {
"count": "15",
"unit": "days"
},
"adjustedPrice": "101.000",
"status": "approved",
"priceAdjustments": [
{
"ruleId": "1234",
"amount": "0.25",
"description": "Price adjustment 1"
},
{
"ruleId": "5678",
"amount": "0.25",
"description": "Price adjustment 2"
}
],
"marginAdjustments": [
{
"ruleId": "12345",
"amount": "-0.300",
"description": "Margin adjustment"
}
],
"rateAdjustments": [],
"stipulations": []
},
"creditApplicationFields": [
{
"fieldId": "field@occupancy-type",
"value": {
"type": "enum",
"enumTypeId": "occupancy-type",
"variantId": "primary-residence"
}
},
{
"fieldId": "field@loan-purpose",
"value": {
"type": "enum",
"enumTypeId": "loan-purpose",
"variantId": "purchase"
}
},
{
"fieldId": "field@decision-credit-score",
"value": {
"type": "number",
"value": "750"
}
},
{
"fieldId": "field@state",
"value": {
"type": "string",
"format": "us-state-code",
"value": "TX"
}
},
{
"fieldId": "field@property-type",
"value": {
"type": "enum",
"enumTypeId": "property-type",
"variantId": "single-family"
}
},
{
"fieldId": "field@base-loan-amount",
"value": {
"type": "number",
"value": "400000.00"
}
}
]
}
pipeline-record-created
Sent after succesfully creating a pipeline record using the create-pipeline-record
message. Returns the ID of the newly created record.
Fields
pipelineRecordId
: The ID of the created pipeline record.
Example
iframe.contentWindow.postMessage(
{
message: "pipeline-record-created",
pipelineRecordId: "51",
},
loanpassOrigin
);
pipeline-record-creation-error
Sent after a failed attempt to create a pipeline record using the create-pipeline-record
message. Returns an error message.
Fields
error
: An error message returned from calling thecreate-pipeline-record
message.
Example
iframe.contentWindow.postMessage(
{
message: "pipeline-record-creation-error",
// Actual error message dependant on issue
error: "Failed to create pipeline record",
},
loanpassOrigin
);