# Quickstart

> Show your first quest to a signed-in user: one backend route and one widget.

Source: https://dashboard.adquest.batriders.ir/docs/quickstart · Audience: Developers · Section: Get started

## Before you start

- A public API key (aqk_) and a Secret Key (aqs_) from a platform that is accepted and turned on.
- Your app’s address on the platform’s Where AdQuest may appear list, if the publisher keeps one.
- React 18 or newer, a signed-in user and a backend that can keep the Secret Key private.

- [Keys and environments](https://dashboard.adquest.batriders.ir/docs/environments): What to ask the publisher for, and where each value goes.

## 1. Add a backend route

**app/api/adquest/session/route.ts**

```typescript
// Server only. Add your own check that the user is signed in first.
export async function POST() {
  const userId = "USER_ID_FROM_YOUR_SESSION";
  const response = await fetch(process.env.ADQUEST_API_URL + "/platform/participant-sessions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-AdQuest-Platform-Secret": process.env.ADQUEST_PLATFORM_SECRET!,
    },
    body: JSON.stringify({ external_user_id: userId }),
  });
  const { data } = await response.json();
  return Response.json({ externalUserId: userId, participantToken: data.participant_token, expiresAt: data.expires_at });
}
```

> **Where the Secret Key goes.** Save the Secret Key as ADQUEST_PLATFORM_SECRET on your server only. Never send it to the browser. The full helper with error handling and language is in the Participant sessions guide.

- [Participant sessions](https://dashboard.adquest.batriders.ir/docs/participant-sessions#mint-token): The full backend helper with error handling and language.

## 2. Show the widget

**Rewards.tsx**

```tsx
"use client";
import { useEffect, useState } from "react";
import { AdQuestWidget } from "@adquest/sdk/react";
import "@adquest/sdk/styles.css";

export default function Rewards() {
  const [session, setSession] = useState<{ externalUserId: string; participantToken: string } | null>(null);
  useEffect(() => {
    fetch("/api/adquest/session", { method: "POST" }).then((r) => r.json()).then(setSession);
  }, []);
  if (!session) return <p>Loading rewards…</p>;
  return <AdQuestWidget
    apiKey={process.env.NEXT_PUBLIC_ADQUEST_PLATFORM_API_KEY!}
    baseUrl={process.env.NEXT_PUBLIC_ADQUEST_API_URL!}
    externalUserId={session.externalUserId}
    participantToken={session.participantToken}
  />;
}
```

> **This version is for a first test.** It does not refresh the token or show errors. Add both before launch (see the React & Next.js guide). Run npm install @adquest/sdk first. The two environment variables are listed in API keys & credentials.

- [React & Next.js](https://dashboard.adquest.batriders.ir/docs/react#mount): Token refresh, errors, language and callbacks.

## 3. What you should see

- The widget loads and shows a list of quests and your token balance.
- Opening a quest shows its task. Completing it adds tokens to the balance.

- [The widget loads but no quests appear](https://dashboard.adquest.batriders.ir/docs/troubleshooting#empty-feed): Check approval, activation, targeting and the API URL.
- [Quest evidence](https://dashboard.adquest.batriders.ir/docs/quest-evidence): The proof each quest format needs to complete.
- [Prepare for launch](https://dashboard.adquest.batriders.ir/docs/launch): Add token refresh, error handling and production checks.
