Frontend (Next.js Client)
Request the embed URL and render the hosted journey in an iframe.
Create a client component that requests the embed URL and renders the iframe.
app/(borrower)/loan-journey/loan-journey-embed.tsx
"use client";
import { useState } from "react";
export function LoanJourneyEmbed() {
const [borrowerProviderID, setBorrowerProviderID] = useState("");
const [contactNumber, setContactNumber] = useState("");
const [pan, setPan] = useState("");
const [embedUrl, setEmbedUrl] = useState<string | null>(null);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const handleStart = async () => {
setIsLoading(true);
setErrorMessage(null);
try {
const response = await fetch("/api/loan-journeys/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
borrowerProviderID,
contactNumber,
...(pan ? { pan } : {}),
}),
});
if (!response.ok) {
const errorPayload = await response.json().catch(() => ({}));
throw new Error(errorPayload.error ?? "Failed to start session.");
}
const data = (await response.json()) as { embedUrl: string };
setEmbedUrl(data.embedUrl);
} catch (error) {
setErrorMessage(
error instanceof Error ? error.message : "Something went wrong.",
);
} finally {
setIsLoading(false);
}
};
return (
<div>
{!embedUrl && (
<div>
<label>
Borrower Provider ID
<input
type="text"
value={borrowerProviderID}
onChange={(event) => setBorrowerProviderID(event.target.value)}
placeholder="borrower_provider_id"
/>
</label>
<label>
Contact number
<input
type="tel"
value={contactNumber}
onChange={(event) => setContactNumber(event.target.value)}
placeholder="+919876543210"
/>
</label>
<label>
PAN (optional)
<input
type="text"
value={pan}
onChange={(event) => setPan(event.target.value)}
placeholder="ABCDE1234F"
/>
</label>
<button
onClick={handleStart}
disabled={isLoading || !borrowerProviderID || !contactNumber}
>
{isLoading ? "Starting..." : "Start loan journey"}
</button>
{errorMessage && <p>{errorMessage}</p>}
</div>
)}
{embedUrl && (
<iframe
src={embedUrl}
title="Loan Journey"
style={{ width: "100%", height: "80vh", border: "0" }}
allow="camera; microphone; clipboard-read; clipboard-write"
/>
)}
</div>
);
}When the iframe fails to load
If the iframe is blank or blocked, verify your embed domain is allow-listed in
embed_domains and that your CSP allows frame-ancestors for the platform
domain.