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

# Session renewal

> Tokens last 15 minutes. Conversations last much longer. onSessionExpired bridges the two.

Pass `onSessionExpired`. When the token stops working, the assistant calls it, waits for a new token, and replays the question that was pending. The customer sees nothing.

```js theme={"system"}
Concatflow.init({
  session: token,
  onSessionExpired: async () => {
    const res = await fetch("/api/concatflow/session", { method: "POST" });
    if (!res.ok) throw new Error("Could not open a Concatflow session");
    return (await res.json()).token;
  },
});
```

The function returns a `Promise<string>`: the new token. It calls the same server route that opened the first one. See [Per-user door](https://docs.concatflow.com/guides/per-user-door.md).

## When it runs

The assistant asks for a new token when Concatflow refuses the current one:

* when the iframe loads, on first use, if the page has been open longer than 15 minutes;
* when the customer asks a question after the token expired.

There is no timer. A page left open all day costs nothing until the customer comes back to it.

Only one renewal runs at a time. If the pending question fails again with the new token, the assistant shows an error instead of retrying.

## When renewal fails

If your function throws, rejects, or returns something that is not a non-empty string, the assistant ignores it and keeps the panel open. Make your route return `401` when the customer is no longer logged in, and throw on it, as above.

> [!WARNING]
>
> Renewal cannot fix everything that looks like an expired token. Concatflow answers the same way to an expired token, an unpublished assistant, a closed per-user door and an origin missing from **Allowed origins**: it never tells which. If renewals keep happening, check those first.

## Without `onSessionExpired`

The token expires after 15 minutes, and the assistant stops answering until the page reloads. Always pass it on the per-user door. It does not apply to the public door: the site token does not expire.

## Renew it yourself

You can also push a token at any time, for example right after your own session refresh:

```js theme={"system"}
assistant.setSession(newToken);
```

Only for the **same** customer. When the customer changes, see [When the customer changes](https://docs.concatflow.com/guides/per-user-door.md#when-the-customer-changes).

## Lifetimes

| What | Lives |
| - | - |
| Session token | 15 minutes from `sessions.create` |
| Conversation | Until you erase it. See [Conversations](https://docs.concatflow.com/guides/conversations.md). |
| Site token | Until the assistant is deleted |


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