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

# Authentication

> Session cookies, project API keys, email verification, and tokenized public routes.

# Authentication

PlanSync supports two ways to call protected APIs:

1. **Project API keys** (`x-api-key`) — preferred for integrations and the docs playground
2. **Better Auth session cookies** — used by the signed-in web app

## Project API keys

Create a key in **Project Settings → API keys**. Keys look like `psk_…` and are sent as a header:

```bash theme={null}
curl -X GET "https://api.plansync.dev/api/v1/projects/<projectId>/issues" \
  -H "x-api-key: psk_<your-key>"
```

Notes:

* API keys only work on **project-scoped** routes: `/api/v1/projects/{projectId}/…`
* The `{projectId}` in the path must match the project the key belongs to
* Scopes are enforced (for example `issues:read` to list issues, `issues:write` to create)
* Do **not** paste an API key into the session cookie field in the playground

## Session cookies

For browser/session flows:

* Authenticate through `/api/auth/*`
* Send the Better Auth session cookie with the request

```bash theme={null}
curl -X GET "https://api.plansync.dev/api/v1/me" \
  -H "Cookie: better-auth.session_token=<session-cookie>"
```

## Email verification behavior

Most session-protected routes require verified email status.

Possible responses:

* `401 Unauthorized` when no valid session or API key exists
* `403 Email verification required` when a user is signed in but not verified
* `403 API key missing scope: …` when the key lacks the required scope

Invite acceptance flows are an exception and can run before verification finalization.

## Authorization model

After authentication, route-level checks enforce:

* Workspace membership
* Project membership
* Manager/admin/super-admin requirements for management actions
* Plan requirements for premium features

## Public token routes

Some APIs do not require member sessions but do require opaque tokens:

* Proposal portal endpoints (`/api/v1/public/proposals/:token/*`)
* Occupant endpoints (`/api/v1/occupant/:token/*`)

Treat these tokens as secrets.

Example token route:

```bash theme={null}
curl -X GET "https://api.plansync.dev/api/v1/public/proposals/<token>"
```

## Internal automation routes

Certain routes are intended for your own secure infrastructure and use a secret header/key pattern (for scheduled jobs). Do not expose these routes directly to customer systems.
