Credit SDK by Aarthik Labs

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.