> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tolt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Refer-a-friend page

> Give every signed-in user a referral link and a live earnings dashboard inside your app, enrolling them as partners by email the first time they open it.

![An embedded referral dashboard inside an app, showing the partner's link, earnings and recent referrals](https://mintcdn.com/tolt-29/IdZ6_r2VYMOh5a6x/images/dashboard/embed-settings-light.webp?fit=max\&auto=format\&n=IdZ6_r2VYMOh5a6x\&q=85\&s=baad9826cfa96c03782f77a8a005748f)

Turn your users into partners without sending them anywhere. When a signed-in user opens the page, your backend asks Tolt for a dashboard token by their email. Tolt enrolls them as a partner on their first visit, and your app shows their [embedded dashboard](/sdks/embed): referral link, earnings, stats and recent referrals. It works with any backend and any auth; the examples use TypeScript.

Your app\<ToltEmbed />Your backendtoken endpointToltplatform.tolt.com*1*POST /api/referrals/token*2*POST /v2/embed-tokens by email*3*new? create the partner*4*200 token, expires\_at*5*token: eyJhbGciOi…*6*iframe /referrals?token=…

## Build it

**1. Install the packages and set two variables**

```bash theme={"system"}
npm install @tolt/api @tolt/embed
```

Add your [API key](/api-reference/authentication) and the id of the program users should join to your server's environment:

```bash .env theme={"system"}
TOLT_API_KEY=tlt_live_...
TOLT_PROGRAM_ID=prg_...
```

**2. Return a token from your backend**

One call. Tolt finds the partner by email in your program, or creates them (active, with a referral link) the first time.

```ts referrals.ts theme={"system"}
import { ToltApi, ToltApiClient } from "@tolt/api";

const tolt = new ToltApiClient({ token: process.env.TOLT_API_KEY! });

// Returns { token, expires_at, partner_id }, or null when this user can't have a dashboard.
export async function referralToken(user: { email: string }) {
  try {
    const { data } = await tolt.embedTokens.create({
      partner: { email: user.email, program_id: process.env.TOLT_PROGRAM_ID! },
    });
    return data;
  } catch (error) {
    if (error instanceof ToltApi.NotFoundError) return null;
    throw error;
  }
}
```

Send `first_name` and `last_name` in `partner` too if you have them; they're used only when the partner is created.

Call it from any endpoint your app can reach with the user's session:

```ts Next.js theme={"system"}
// app/api/referrals/token/route.ts
export async function POST() {
  const user = await getCurrentUser(); // your auth
  if (!user?.emailVerified) return new Response(null, { status: 403 });

  const token = await referralToken(user);
  return token ? Response.json(token) : new Response(null, { status: 409 });
}
```

```ts Express theme={"system"}
app.post("/api/referrals/token", async (req, res) => {
  if (!req.user?.emailVerified) return res.sendStatus(403); // your auth

  const token = await referralToken(req.user);
  return token ? res.json(token) : res.sendStatus(409);
});
```

> [!WARNING]
>
> Only enroll users whose email you have verified. The lookup matches on email, so an unverified account using someone else's address would open that person's dashboard.

> **Edge cases**
>
> * **Partner the dashboard won't open.** A partner who was invited but hasn't finished onboarding, or who is suspended or rejected, gets `404`, so `referralToken` returns `null`. Show a short "Referrals aren't available for your account" message instead of a dashboard.
> * **Paused program.** A program that isn't active also returns `404`, and no one is enrolled into it.
> * **Two tabs at once.** Two first visits at the same moment end up with the same partner; Tolt creates them once.
> * **No name.** Without a name, Tolt builds the link slug from the part of the email before the `@`.
> * **Review first.** Partners created here are active right away. To approve them before they earn, create them yourself with `status: "pending"` (see [Partner signup](/guides/partner-signup)).

**3. Render the dashboard**

Wherever the dashboard lives in your app, fetch a token when it mounts and pass it to `<ToltEmbed>`. Match your app's theme, and fetch a new token only when the old one has expired. Not using React? See the [plain iframe](/sdks/embed#iframe-without-react).

```tsx ReferAFriend.tsx theme={"system"}
"use client";
import { useEffect, useState } from "react";
import { ToltEmbed } from "@tolt/embed";

type EmbedToken = { token: string; expires_at: string };

export function ReferAFriend({ theme }: { theme: "light" | "dark" | "system" }) {
  const [embed, setEmbed] = useState<EmbedToken>();
  const [failed, setFailed] = useState<number>();

  const load = async () => {
    setFailed(undefined);
    const res = await fetch("/api/referrals/token", { method: "POST" }).catch(() => null);
    if (res?.ok) setEmbed(await res.json());
    else setFailed(res?.status ?? 0);
  };

  useEffect(() => {
    load();
  }, []);

  if (failed === 409) return <p>Referrals aren't available for your account.</p>;
  if (failed === 403) return <p>Verify your email to get your referral link.</p>;
  if (failed !== undefined) {
    return (
      <p>
        Couldn't load your referrals. <button onClick={load}>Try again</button>
      </p>
    );
  }
  if (!embed) return null;

  return (
    <ToltEmbed
      key={embed.token}
      token={embed.token}
      theme={theme}
      themeOptions={{ radius: 16 }}
      onError={() => {
        if (Date.parse(embed.expires_at) <= Date.now()) load();
      }}
    />
  );
}
```

The dashboard has its own refresh button and a **Portal** link to your partner portal (payout details, profile), so it needs nothing around it.

## Tips

* **Give it an obvious home.** Account settings, a sidebar link or a dedicated page all work. It belongs to the person, so every user gets their own link.
* **Explain the deal.** A line about what partners earn tells users what the numbers mean before they see a \$0 balance.
* **Say what you share.** Note that the user's name and email go to Tolt to track referrals and pay commissions.
* **Hide it until it's configured.** If `TOLT_API_KEY` or `TOLT_PROGRAM_ID` is missing, leave it out of your navigation and have the endpoint return `404`.

> [!NOTE]
>
> Referral links only earn once your site records the click and the signup. If you haven't set that up, start with the [Quickstart](/quickstart).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.