---
title: "Reset Goal Browser Session"
method: POST
path: "/goals/session/reset"
tags: ["goals"]
---

# Reset Goal Browser Session

`POST /goals/session/reset`

Start over: this browser gets a new session, and so a new conversation.

Field-found on the voice e2e (#1947): there was no way to begin again. ``GET
/goals/session`` keeps a live cookie's session on purpose — that is what makes a
conversation survive a reload — ``GET /goals/conversation`` resumes the durable
one, and nothing rotated either, so "new goal" could only navigate back to the
same conversation forever.

Unsafe, taking the same three signals every unsafe goals route takes, because
from the athlete's point of view this ends their conversation: a cross-site page
that could reach it could throw away work somebody is in the middle of. The
answer is shaped exactly like the bootstrap's — replacement cookie, fresh CSRF
token, the new session's id and expiry — so a client swallows it with the code
it already has for ``GET /goals/session``.

The old goal session is left to its TTL rather than deleted;
:meth:`~cheshire.resources.browser_sessions.BrowserSurface.rotate` says why.

**An active voice conversation is not this route's business.** The audio is held between
the browser and the voice service, so nothing here could end one; the client
hangs up first, and a conversation left running would only be delegating turns onto a
session its own page no longer holds.

## Response `200`

Successful Response

- GoalBrowserSessionResponse — What ``GET /goals/session`` hands the page back. Deliberately thinner than the Routes equivalent: the goals page has no session list to render and no route ancestry to carry, so it gets the two things it actually acts on — the CSRF token every turn must echo, and when the session stops being valid so it knows to bootstrap again. The session id rides along because it is what an operator matches a stored conversation on; it authorizes nothing on its own (the cookie does).
  - `session_id` string, required
  - `expires_at` string, date-time, required
  - `csrf_token` string, required
  - `brain_lane` BrainLanePayload — Which model a service answers goal turns on: the tape's lane (#2317). Read off the model the boundary actually built (:meth:`~cheshire.model_clients.ModelLane.of`), never derived a second time from settings, so what a recording claims and what answered it cannot drift.
    - `model` string, required
    - `provider` string, required
    - `speed` string, required

## Changes

- **2026-09-02** `55d56c4beab4` — 1 info
  - added the optional property `brain_lane` to the response with the `200` status

[Change history](https://skmtc.dev/imperfect/apis/imperfect-api/changes/goals/session/reset/post.md)

---

[API](https://skmtc.dev/imperfect/apis/imperfect-api.md) · [All operations](https://skmtc.dev/imperfect/apis/imperfect-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/imperfect/imperfect-api/revisions/53750ba952fc/schema)
