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

# Gates and Auth

> Handle authentication, access codes, and additional verification with the public journey contract.

When a journey is `gated`, Fanfare is telling your application that the consumer must complete a public requirement before the journey can continue.

```ts theme={null}
const view = journey.view$.get();

if (view.journeyStage === "gated") {
  const firstGate = view.gates[0];
  showGate(firstGate);
}
```

Your integration should present the appropriate UI, complete the required customer action, then call `reroute()` to ask Fanfare for the next public state.

<img src="https://mintcdn.com/fanfare/oKzL5u1gWepNCXYO/images/sdk/gates-auth-flow.webp?fit=max&auto=format&n=oKzL5u1gWepNCXYO&q=85&s=46c7c413628b00c6ea330d2f9b1a17a8" alt="Gate and authentication workflow showing gated state, required customer action, reroute, routing, and the next public state." width="1837" height="856" data-path="images/sdk/gates-auth-flow.webp" />

## Gate types

| Gate             | What to show                                           | How to continue                                    |
| ---------------- | ------------------------------------------------------ | -------------------------------------------------- |
| `authentication` | Email or phone sign-in, depending on your integration. | Complete auth, then call `view.reroute()`.         |
| `access_code`    | Access-code form.                                      | Call `view.reroute({ accessCode })`.               |
| `bot_check`      | Additional verification UI.                            | Complete verification, then call `view.reroute()`. |

Do not explain private enforcement details in your UI. Use clear outcome language such as "Additional verification is required" or "Enter your access code to continue."

## Email or phone auth

```ts theme={null}
async function authenticateWithEmail(email: string, code: string) {
  await sdk.auth.requestOtp({ email });
  await sdk.auth.verifyOtp({ email, code });

  const view = journey.view$.get();
  if (view.journeyStage === "gated") {
    await view.reroute();
  }
}
```

You can also create a guest session for flows that allow anonymous participation:

```ts theme={null}
const auth = sdk.auth.check();

if (!auth.isAuthenticated) {
  await sdk.auth.guest();
}
```

## Access codes

```ts theme={null}
async function submitAccessCode(accessCode: string) {
  const view = journey.view$.get();

  if (view.journeyStage !== "gated") {
    return;
  }

  await view.reroute({ accessCode });
}
```

If the code is invalid, the journey may remain gated. Keep the consumer on the access-code UI and let the next `view$` value drive the message.

## Additional verification

For additional verification, render the verification experience your Fanfare contact has enabled for your account. When the user completes it, verify the challenge result and reroute.

```ts theme={null}
async function completeVerification(challengeId: string, token: string) {
  await sdk.challenges.verify({ challengeId, token });

  const view = journey.view$.get();
  if (view.journeyStage === "gated") {
    await view.reroute();
  }
}
```

Keep verification copy generic. The integration should not expose why a verification step appeared or how Fanfare evaluates access.
