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

# Authentication

> Personal access tokens, OAuth scopes, and security best practices

## Personal access tokens

Create and revoke tokens in the dashboard under **Settings → API tokens**.

### Request headers

Send the token on every request:

<CodeGroup>
  ```http Headers theme={null}
  Authorization: Bearer {access_token}
  Accept: application/json
  ```

  ```javascript JavaScript theme={null}
  const headers = {
    Authorization: 'Bearer {access_token}',
    Accept: 'application/json',
  };
  ```

  ```python Python theme={null}
  headers = {
      'Authorization': 'Bearer {access_token}',
      'Accept': 'application/json',
  }
  ```

  ```go Go theme={null}
  req.Header.Set("Authorization", "Bearer {access_token}")
  req.Header.Set("Accept", "application/json")
  ```

  ```ruby Ruby theme={null}
  request['Authorization'] = 'Bearer {access_token}'
  request['Accept'] = 'application/json'
  ```

  ```php PHP theme={null}
  $headers = [
      'Authorization: Bearer {access_token}',
      'Accept: application/json',
  ];
  ```
</CodeGroup>

For `POST`, `PATCH`, and `PUT` requests with a body, also send:

<CodeGroup>
  ```http Headers theme={null}
  Content-Type: application/json
  ```

  ```javascript JavaScript theme={null}
  headers['Content-Type'] = 'application/json';
  ```

  ```python Python theme={null}
  headers['Content-Type'] = 'application/json'
  ```

  ```go Go theme={null}
  req.Header.Set("Content-Type", "application/json")
  ```

  ```ruby Ruby theme={null}
  request['Content-Type'] = 'application/json'
  ```

  ```php PHP theme={null}
  $headers[] = 'Content-Type: application/json';
  ```
</CodeGroup>

### Token lifetime

Personal access tokens expire six months after they are created. Expired or revoked tokens return `401 Unauthorized`.

## Email verification

All `/api/v1/*` routes require a verified email address on the token owner. Unverified users receive an authentication error.

## OAuth scopes

Each token carries one or more scopes. Routes declare the minimum scope required. If the token lacks that scope, the API returns `403 Forbidden` even when the user would otherwise be allowed in the UI.

### Available scopes

| Scope           | Description                                                       |
| --------------- | ----------------------------------------------------------------- |
| `teams:read`    | Read teams, plan limits, and team monitoring defaults             |
| `teams:write`   | Update team monitoring defaults (cadence, thresholds, escalation) |
| `sites:read`    | Read sites and site monitoring data                               |
| `sites:write`   | Create and update sites                                           |
| `sites:delete`  | Delete sites                                                      |
| `checks:read`   | Read check runs and results                                       |
| `checks:run`    | Queue on-demand check runs                                        |
| `checks:delete` | Delete on-demand check runs                                       |
| `issues:read`   | Read issues (monitoring incidents)                                |

<Info>
  Scopes map to team permissions and team role rules still apply: a member without site-create permission cannot create sites even with `sites:write` on the token.
</Info>

### Recommended scope sets

Different use cases require different scope combinations:

<AccordionGroup>
  <Accordion title="Read-only monitoring">
    ```
    teams:read
    sites:read
    checks:read
    issues:read
    ```

    Perfect for dashboards and monitoring displays.
  </Accordion>

  <Accordion title="Configure team monitoring">
    Add `teams:write` to update team monitoring defaults (cadence, thresholds, escalation):

    ```
    teams:read
    teams:write
    ```
  </Accordion>

  <Accordion title="Deploy / provision sites">
    Add `sites:write` to the read-only set:

    ```
    teams:read
    sites:read
    sites:write
    checks:read
    issues:read
    ```
  </Accordion>

  <Accordion title="CI check runner">
    Add `checks:run` for running checks:

    ```
    teams:read
    sites:read
    checks:read
    checks:run
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  Grant only the scopes you need. This follows the principle of least privilege.
</Warning>

## Team access and billing

Authentication proves **who** is calling. Team routes also enforce:

<Steps>
  <Step title="Membership">
    The user must belong to the team in the URL (or implied by the site/check/issue).

    <Note>
      Otherwise the API returns `404` to avoid leaking cross-tenant resources.
    </Note>
  </Step>

  <Step title="Active subscription">
    The team must have active plan access.

    Otherwise the API returns `402` with:

    ```json theme={null}
    {
      "message": "An active team subscription is required."
    }
    ```
  </Step>

  <Step title="Role permissions">
    Site, check, and issue policies apply on top of token scopes.
  </Step>
</Steps>

## Security practices

<CardGroup cols={2}>
  <Card title="Store securely" icon="vault">
    Store tokens in secrets managers, not source control
  </Card>

  <Card title="Separate environments" icon="layer-group">
    Use separate tokens per environment (staging vs production)
  </Card>

  <Card title="Revoke immediately" icon="trash">
    Revoke tokens immediately when an integration is retired
  </Card>

  <Card title="Narrow scopes" icon="filter">
    Prefer narrow scopes and dedicated service users where your plan allows
  </Card>
</CardGroup>

## Creating a token

Tokens are created under **Settings → API tokens** in the dashboard. Give each token a descriptive name (for example "CI Pipeline") and select the required scopes.

<Warning>
  The token value is shown once at creation. Store it securely - it cannot be retrieved again.
</Warning>

## See also

* [Requests and responses](/api/requests-responses)
* [Endpoints](/api/endpoints)
