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

# Authenticate with the Masker API using OAuth cookies

> How Masker uses GitHub OAuth and HTTP-only session cookies, with guidance for browser sessions, CLI scripting, and webhook signature verification.

Masker authenticates API calls using a **GitHub OAuth session cookie**. There is no password login and no API key issuance today — long-lived scoped tokens are on the May 30 roadmap. Until then, the session cookie is the credential for all `/api/v1/*` endpoints.

## How the session cookie works

When you complete the GitHub OAuth flow, Masker sets a cookie on your browser:

```
Set-Cookie: masker_session=<opaque>; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=2592000
```

| Property     | Value                                                     |
| ------------ | --------------------------------------------------------- |
| **Name**     | `masker_session`                                          |
| **HttpOnly** | Yes — JavaScript cannot read it                           |
| **Secure**   | Yes — HTTPS only                                          |
| **SameSite** | `Lax`                                                     |
| **Lifetime** | 30 days, sliding — renewed on every authenticated request |
| **Domain**   | Bound to the API host                                     |

The cookie value is an opaque token. On the server it maps to a session record containing your user ID, GitHub login, and last-seen timestamp. You cannot decode or forge it.

## Authenticating API requests

Send the cookie value in a `Cookie` request header:

<CodeGroup>
  ```bash curl theme={null}
  curl -H "Cookie: masker_session=ey..." \
    https://masker-voice.fly.dev/api/v1/agents
  ```
</CodeGroup>

For scripting and CI, copy the cookie from your browser's DevTools after signing in to the portal (Application → Cookies → `masker_session`), then export it as an environment variable:

```bash theme={null}
export MASKER_SESSION=ey...
curl -H "Cookie: masker_session=$MASKER_SESSION" \
  https://masker-voice.fly.dev/api/v1/agents
```

This is not the long-term answer for automation, but it works for one-off scripts and CI checks today.

## The OAuth flow

The OAuth handshake is browser-driven. Masker does not expose an API endpoint that lets you complete it headlessly.

<Steps>
  <Step title="Start the OAuth flow">
    Navigate to `GET /api/v1/auth/github`. Masker redirects your browser to GitHub's authorization page.
  </Step>

  <Step title="Approve the GitHub request">
    GitHub asks you to authorize Masker. Once you approve, GitHub redirects back to Masker.
  </Step>

  <Step title="Masker completes the exchange">
    Masker receives the authorization code at `GET /api/v1/auth/github/callback`, exchanges it for a GitHub access token, creates a session, sets the `masker_session` cookie, and redirects you to `/portal`.
  </Step>
</Steps>

For headless automation, complete the OAuth flow in a real browser once, then copy the resulting cookie for use in scripts.

## Logging out

```bash theme={null}
curl -X POST -H "Cookie: masker_session=ey..." \
  https://masker-voice.fly.dev/api/v1/auth/logout
```

Returns `204 No Content`, clears the cookie, and permanently invalidates the server-side session row. The cookie value cannot be reused after logout.

## Identifying the current user

```bash theme={null}
curl -H "Cookie: masker_session=ey..." \
  https://masker-voice.fly.dev/api/v1/me
```

Returns the user record associated with the current session, including your GitHub login and account details.

## What 401 and 403 mean

* **401 `unauthenticated`** — The request arrived with no `masker_session` cookie, or with a cookie that has expired or been invalidated. Sign in again to get a fresh session.
* **403 `forbidden`** — Your session is valid, but you are not permitted to perform this action. For example, deleting an agent requires admin access; a non-admin user's request will be rejected with 403.

## Webhook endpoints

Two endpoints are called by external systems and therefore cannot use the `masker_session` cookie:

* `POST /proxy/{agent_id}/v1/chat/completions`
* `POST /vapi/webhook/{agent_id}`

These endpoints use **HMAC signature verification** instead. The voice platform signs each request with a shared secret; Masker validates the `X-Vapi-Signature` header against the `MASKER_VAPI_WEBHOOK_SECRET` environment variable. Configure the same secret value on both sides — a mismatch returns `401`.

## Coming soon

<Note>
  **Scoped API tokens** are targeting the May 30 release. Tokens will be issuable from the portal with explicit scopes (`agents:read`, `sessions:read`, `reports:read`) and will be the recommended credential for CI and machine-to-machine access. OIDC and mTLS support are on the longer-term roadmap.
</Note>
