The Loan Application Element is a complete end-to-end mortgage loan application experience. This guide shows you how to integrate it into your application.
Prerequisites
Before building the Loan Application Element, ensure you have:
- Set up authentication - Configured your backend to handle Pylon authorization requests
- Installed the Elements library:
npm install @pylonlending/react-elements --save
Basic implementation
Here’s a minimal implementation of the Loan Application Element:
// Import the Loan Application Element
import { LoanApplicationElement } from "@pylonlending/react-elements";
// Create a function that returns a Promise<AuthLease>
// This should fetch the results of your auth handler endpoint
const fetchPylonAuthLease = async (): Promise<AuthLease> => {
const response = await fetch("/auth/pylon");
return response.json();
};
<YourApplication>
<LoanApplicationElement
// Include your function that returns a Promise<AuthLease>
authLeaseCallback={fetchPylonAuthLease}
/>
</YourApplication>
Required properties
| Property | Type | Description |
|---|
authLeaseCallback | AuthLeaseCallback | A function that fetches the results of your authentication route. Must return a Promise<AuthLease>. |
Loading an existing loan
To load an existing loan application, pass the loanId prop:
<LoanApplicationElement
authLeaseCallback={fetchPylonAuthLease}
loanId="loan_12345"
/>
To start a new loan application, omit the loanId prop or set it to undefined.
Pre-filling data with the GraphQL API
You can use the GraphQL API to pre-fill borrower information before initializing the Loan Application Element. When you create a loan and add borrower data (personal information, income, assets, property details, etc.) via the API, that data will automatically be pre-filled in the Element when it’s initialized.
This is useful for:
- Streamlined onboarding - Pre-fill data you already have from your system
- Hybrid workflows - Collect some information in your own UI, then let Elements handle the rest
- Better UX - Borrowers can review and complete pre-filled information rather than starting from scratch
See Loading loans for a complete example of pre-filling data via the API.
Content Security Policy
If you’re using a Content Security Policy, add these directives:
default-src https://api.{customer-id}.{env}.pylon.mortgage
frame-src https://api.{customer-id}.{env}.pylon.mortgage
script-src https://api.{customer-id}.{env}.pylon.mortgage/elements/pylon.js
connect-src https://api.{customer-id}.{env}.pylon.mortgage
Replace {customer-id} with your customer ID and {env} with test or prod.
Important notes
All props passed to the LoanApplicationElement should be const-they should not change after the Element’s first render. If props change, they will have no effect and will not be updated inside the Element.
Optional properties
| Property | Type | Description |
|---|
loanId | string | The ID of an existing loan to load. Omit or set to undefined to start a new application. |
theme | Theme | Theme configuration object to customize the Element’s appearance. See Theming for details. |
Complete example with all features
Here’s a complete example that includes theming and demonstrates how to handle loan completion:
import { LoanApplicationElement } from "@pylonlending/react-elements";
import { useState, useEffect } from "react";
function LoanApplicationPage() {
const [loanId, setLoanId] = useState<string | undefined>();
const [showDashboard, setShowDashboard] = useState(false);
const fetchPylonAuthLease = async (): Promise<AuthLease> => {
const response = await fetch("/auth/pylon");
return response.json();
};
// Poll for loan completion
useEffect(() => {
if (!loanId) return;
const interval = setInterval(async () => {
const query = `
query GetLoanStatus($id: ID!) {
loan(id: $id) {
id
submitted
}
}
`;
const response = await fetch("https://pylon.mortgage/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({ query, variables: { id: loanId } }),
});
const { data } = await response.json();
if (data.loan?.submitted) {
setShowDashboard(true);
clearInterval(interval);
}
}, 30 * 60 * 1000); // Poll every 30 minutes
return () => clearInterval(interval);
}, [loanId]);
const theme = {
Global: {
fonts: {
fontFamily: "Inter, sans-serif",
fontUrls: [
"https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap",
],
},
colors: {
core: {
primary: "#0066CC",
},
},
},
};
if (showDashboard && loanId) {
return <BorrowerDashboardElement loanId={loanId} authLeaseCallback={fetchPylonAuthLease} />;
}
return (
<LoanApplicationElement
authLeaseCallback={fetchPylonAuthLease}
loanId={loanId}
theme={theme}
/>
);
}
Next steps