# Short-lived Avatar Tokens (Advanced)

### When should I use this?

* You do not want to expose your Sentifyd `AVATAR_API_KEY` in JavaScript or in a static HTML file.
* Your site already calls your own backend before rendering most pages (typical SSR / Next.js, remix, Flask, Rails, etc.).
* You need full control over who may request a token (e.g. only logged-in customers).

If you simply need to embed a public avatar on a static site, consider the **no-backend** integration described in the *Quick Start* guide instead.

### 1 — Add an endpoint in your backend

Create a lightweight route that:

1. Receives a **GET** (or POST) from the browser.
2. Calls the Sentifyd Authentication API with your **`AVATAR_API_KEY`**.
3. Returns a JSON payload containing:
   * an `accessToken` (JWT)
   * a `refreshToken`
   * `avatarParameters` (theme, voice, etc.)

#### Reference endpoint implementation

{% tabs %}
{% tab title="Python (Flask)" %}

```
from flask import Blueprint, current_app, jsonify, request
import requests

blueprint = Blueprint("sentifyd", __name__)

@blueprint.route("/request_tokens", methods=["GET"])
def request_tokens():
    sentifyd_backend_url = current_app.config["SENTIFYD_BACKEND"] + "/api/login"
    avatar_api_key = current_app.config["AVATAR_API_KEY"]

    payload = {"avatar_api_key": avatar_api_key}
    try:
        response = requests.post(sentifyd_backend_url, json=payload)
        if response.status_code != 200:
            return jsonify({"error": "Authentication failed", "details": response.json()}), response.status_code

        data = response.json()["data"]
        frontend_payload = {
            "tokens": {
                "accessToken": data["access_token"],
                "refreshToken": data["refresh_token"],
            },
            "avatarParameters": data["avatar_params"],
        }
        return jsonify(frontend_payload), 200

    except Exception as e:
        current_app.logger.exception("Error while requesting Sentifyd tokens")
        return jsonify({"error": "Internal server error"}), 500
```

{% endtab %}

{% tab title="Typescript (Express.js)" %}

```
import express, { Request, Response } from "express";
import axios from "axios";

const router = express.Router();

// Example configuration values (could also come from process.env)
const SENTIFYD_BACKEND = process.env.SENTIFYD_BACKEND || "https://backend.sentifyd.io";
const AVATAR_API_KEY = process.env.AVATAR_API_KEY || "your-avatar-api-key-here";

router.get("/request_tokens", async (req: Request, res: Response) => {
  const sentifydBackendUrl = `${SENTIFYD_BACKEND}/api/login`;
  const payload = { avatar_api_key: AVATAR_API_KEY };

  try {
    const response = await axios.post(sentifydBackendUrl, payload);

    if (response.status !== 200) {
      return res.status(response.status).json({
        error: "Authentication failed",
        details: response.data,
      });
    }

    const data = response.data.data;
    const frontendPayload = {
      tokens: {
        accessToken: data.access_token,
        refreshToken: data.refresh_token,
      },
      avatarParameters: data.avatar_params,
    };

    return res.status(200).json(frontendPayload);
  } catch (error: any) {
    console.error("Error while requesting Sentifyd tokens:", error);
    return res.status(500).json({ error: "Internal server error" });
  }
});

export default router;

```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Secure config :** store `AVATAR_API_KEY` and `SENTIFYD_BACKEND` in environment variables or a secrets store—never commit them to git.
{% endhint %}

**Tips**

* **Cache** the refresh token server‑side if you have many concurrent clients; this reduces traffic to Sentifyd.
* Make sure CORS allows your own origin (`Access‑Control‑Allow‑Origin`).
* Add auth middleware if only signed‑in users may chat with the avatar.

### 2 — Serve the Sentifyd web component

1. Load the Sentifyd component loader **once** on every page that needs an avatar:

```
<script src="https://frontend.sentifyd.io/sentifyd-bot/main.js" defer></script>
```

2. Place the `<sentifyd-bot>` element where you want the avatar to appear. Provide **both** the URL of the endpoint you just created *and* the `avatar_id` you received from the Sentifyd dashboard.

```
<sentifyd-bot
    token_endpoint="https://your-backend.com/request_tokens"
    avatar_id="YOUR-AVATAR-ID">
</sentifyd-bot>
```

* `token_endpoint` — full, publicly reachable URL of the route that returns the JSON payload shown above.
* `avatar_id` — the unique identifier of the avatar you created in the Sentifyd console.

> **Avoid duplicates:** keep each attribute only once; browsers ignore later duplicates.

***

### 3 — How it works

1. The web component boots and issues a **GET** to `token_endpoint`.
2. Your backend exchanges the `AVATAR_API_KEY` for fresh tokens.
3. The frontend receives `{ tokens, avatarParameters }` and opens a WebSocket to Sentifyd.
4. When the access token expires, the component transparently calls your endpoint again with `?refreshToken=...`.

***

### 4 — Minimal example (static HTML)

```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Sentifyd BFF demo</title>
    <script src="https://cdn.sentifyd.io/element/bot.js" defer></script>
  </head>
  <body>
    <h1>Hello, Sentifyd!</h1>

    <sentifyd-bot
      token_endpoint="https://demo.example.com/request_tokens"
      avatar_id="avtr_1234abcd">
    </sentifyd-bot>
  </body>
</html>
```
