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

> ## Agent Instructions
> Flowy is a node-based AI creative platform: you generate images, video, audio, 3D and vector on an infinite Canvas, refine on the Studio timeline, and export or publish from the same project.
> Prefer the Flowy MCP server (https://mcp.tryflowy.ai/mcp) or the REST API at https://apis.tryflowy.ai/v1 for programmatic work. Install with `flowy mcp install` from the @flowy/cli package.
> Credits are workspace-scoped. Generations reserve credits on start and only deduct on success, so failed runs refund automatically.

# Create a session

> Exchange an OAuth access token for a first-party session (privilege step-up).

`POST /v1/session` mints a backend session: the same access + refresh token
pair the web app gets on sign-in, for the account behind an OAuth access
token. It's how a native or first-party client (the desktop app, for example)
reaches the protected `/api` surface and the realtime collaboration socket
without a second interactive sign-in.

<Warning>
  This is a deliberate **privilege step-up**: the session it mints is **not
  scoped** like the OAuth grant that authorized it. It carries the full
  privileges of the signed-in account, regardless of which
  [scopes](/api/oauth#scopes) the token was granted. Only exchange a token you
  control, and only when your integration genuinely needs the full account
  surface rather than the scoped `/v1` API.
</Warning>

<Note>
  Restricted to OAuth access tokens (`flowy_oat_…`): a workspace **API key**
  (secret or publishable) gets `403`. This is not documented in the public
  [OpenAPI spec](/api/get-openapi); everything below is verified directly
  against the handler.
</Note>

## Request

No request body. Send the OAuth access token as the bearer:

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "$FLOWY_API/session" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Response

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{ "data": {
  "user": {
    "id": "507f1f77bcf86cd799439011",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "workspace_id": "507f191e810c19729de860ea",
    "credits": 1250,
    "available_credits": 1250
  },
  "token": "eyJhbGciOi...",
  "refresh_token": "8f14e45f...",
  "expires_in": 3600,
  "session_id": "sess_01hz..."
} }
```

`user` is the same account object the web app's sign-in returns (id, name,
email, workspace id, credit balances, …), not the leaner object [Get the
account](/api/get-account) returns. `token` and `refresh_token` are a standard
access/refresh pair; use `refresh_token` the same way the web app does to
renew the session before `expires_in` seconds elapse.

## Errors

| Status | When                                                                                                |
| ------ | --------------------------------------------------------------------------------------------------- |
| `401`  | Missing or invalid bearer.                                                                          |
| `403`  | The bearer isn't an OAuth access token (a workspace API key was used), or the account is suspended. |
| `404`  | The account behind the token no longer exists.                                                      |
