<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:

  1. 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).
  2. 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:

"Lock Request"

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.

"Submit Float"

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 a type 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 as approved, 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, or null 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, or null 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 the creditApplicationFields 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 as approved, 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, or null 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, or null 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 the creditApplicationFields 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 the create-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
);