---
title: "Refresh a browser session"
method: POST
path: "/v1/sessions/refresh"
---

# Refresh a browser session

`POST /v1/sessions/refresh`

## Request

- Base URL: `https://api.runbear.io`
- URL: `https://api.runbear.io/v1/sessions/refresh`
- Auth: HTTP bearer

Exchange a resume token for a fresh session pass. Call this from YOUR server when the browser reports its pass is about to expire — you decide whether the visitor is still entitled to the session. The resume token is never rotated: keep using the one POST /v1/sessions returned until it expires, then create a new session.

## Request body

- RefreshSessionRequest
  - `resumeToken` string, required: The `resumeToken.token` returned by POST /v1/sessions. Required — a missing or empty value is a 400 from the validator, never a silent new session.
  - `endUser` string: Required when the session was minted with `endUser`; must be byte-identical to that value. Omitted otherwise.

## Response `200`

Default Response

- SessionCredentials
  - `session` Session, required
    - `id` string, uuid, required: Stable id for this visitor session. Log it — it is the join key across the session's requests.
    - `assistant_id` string, uuid, required: The one agent this session may talk to.
    - `thread_id` string, uuid, required: The one thread this session may read and run. Created by this call unless you passed `thread_id`. Always present — the browser must never create a thread itself.
    - `expiresAt` string, required: The resume token's expiry: the last instant at which a fresh pass can be obtained. Refreshing issues a new pass but never moves it. A pass issued just before this instant keeps its own full lifetime, so chat can continue for up to 15 minutes past it — after that the session is over and you must create a new one.
  - `pass` SessionCredential, required
    - `token` string, required: Send as `Authorization: Bearer <token>`. Never place it in a URL or query parameter.
    - `expiresAt` string, required: Instant after which this token is rejected.
    - `expiresInSeconds` integer, required: Seconds from issuance until `expiresAt`, measured by the server. Prefer this over comparing `expiresAt` to a browser clock.
  - `resumeToken` SessionCredential
    - `token` string, required: Send as `Authorization: Bearer <token>`. Never place it in a URL or query parameter.
    - `expiresAt` string, required: Instant after which this token is rejected.
    - `expiresInSeconds` integer, required: Seconds from issuance until `expiresAt`, measured by the server. Prefer this over comparing `expiresAt` to a browser clock.

## Other responses

- `400`: The request body failed validation (`FST_ERR_VALIDATION`), or the resume token cannot be exchanged (`resume_token_invalid` / `resume_token_expired`). A bad token is never a 401 — your API key authenticated fine.
- `401`: The organization API key is missing or invalid.
- `403`: The key lacks the chat capability, its agent allowlist no longer covers the agent this session is bound to, or a browser session pass was presented — a pass can never renew itself (`forbidden_for_session_pass`).
- `429`: Refresh rate limit exceeded, or this session has been renewed as many times as it may be (`session_refresh_cap_exhausted` — terminal; create a new session).

---

[API](https://skmtc.dev/runbear/apis/runbear-api.md) - [All operations](https://skmtc.dev/runbear/apis/runbear-api/llms.txt) - [OpenAPI document](https://skmtc.dev/runbear/apis/runbear-api/revisions/c6a9c3066a5a?raw)
