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

# How to Authenticate Requests to the Scrubbe API

> Scrubbe supports JWT Bearer tokens and API keys. Learn how to obtain credentials, attach them to requests, refresh tokens, and handle rate limits.

Scrubbe supports two authentication methods: **JWT Bearer tokens** for interactive sessions and user-facing applications, and **API keys** for server-to-server integrations and automation. Both methods are accepted on all protected endpoints using standard HTTP headers.

## JWT Bearer tokens

JWT authentication uses a short-lived access token paired with a longer-lived refresh token. You obtain both by logging in, attach the access token to every request, and exchange the refresh token for a new access token when it expires.

### Log in and retrieve tokens

Send your credentials to `POST /api/v1/auth/login`:

```http theme={null}
POST /api/v1/auth/login
Content-Type: application/json

{
  "email": "you@example.com",
  "password": "SecurePassword1!"
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Login successful",
  "data": {
    "user": {
      "id": "clx1abc2def3ghi4jkl5",
      "email": "you@example.com",
      "firstName": "Ada",
      "roles": ["ENGINEER"]
    },
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}
```

Store both tokens securely. Do not expose them in client-side code or logs.

### Attach the token to requests

Include the access token in the `Authorization` header on every protected request:

```http theme={null}
GET /api/v1/incident-ticket
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

### Token expiry

| Token         | Expiry     |
| ------------- | ---------- |
| Access token  | 15 minutes |
| Refresh token | 7 days     |

### Refresh an access token

When your access token expires, use your refresh token to obtain a new one without requiring the user to log in again:

```http theme={null}
POST /api/v1/auth/refresh-token
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

The response contains a new `accessToken` (and optionally a new `refreshToken`). Update your stored tokens accordingly. If the refresh token itself has expired, the user must log in again.

***

## API keys

API keys are suitable for automated pipelines, CI/CD integrations, and any context where a long-lived credential is preferable to managing token refresh cycles. A key is scoped to specific permissions and optionally tied to an expiry date.

<Warning>
  The raw API key value is returned **only once** at creation time. Store it immediately in a secrets manager. You cannot retrieve the raw key again after this point.
</Warning>

### Create an API key

You must be authenticated with a valid Bearer token to create an API key. Send a `POST` request to `/api/v1/apikey/createapikey`:

```http theme={null}
POST /api/v1/apikey/createapikey
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
  "name": "Production Key",
  "environment": "PRODUCTION",
  "scopes": ["incidents:read", "incidents:write"],
  "expiresAt": "2026-12-31T00:00:00Z"
}
```

The response includes the raw key value. Copy it now:

```json theme={null}
{
  "success": true,
  "message": "API key created",
  "data": {
    "id": "clxkey1abc2def3ghi4",
    "name": "Production Key",
    "key": "sk_live_xxxxxxxxxxxxxxxxxxxx",
    "environment": "PRODUCTION",
    "scopes": ["incidents:read", "incidents:write"],
    "expiresAt": "2026-12-31T00:00:00.000Z",
    "createdAt": "2026-05-22T10:00:00.000Z"
  }
}
```

### Attach the key to requests

Include the API key in the `X-API-Key` header:

```http theme={null}
GET /api/v1/incident-ticket
X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxx
```

### Manage existing keys

All key management endpoints require Bearer token authentication.

| Action        | Method   | Path                        |
| ------------- | -------- | --------------------------- |
| List all keys | `GET`    | `/api/v1/apikey/apikeys`    |
| Rotate a key  | `POST`   | `/api/v1/apikey/:id/rotate` |
| Revoke a key  | `POST`   | `/api/v1/apikey/:id/revoke` |
| Delete a key  | `DELETE` | `/api/v1/apikey/:id`        |

**Rotate** generates a new raw key value for an existing key record and invalidates the previous value. **Revoke** disables the key without deleting it. **Delete** permanently removes the key.

***

## Using both methods side by side

<Tabs>
  <Tab title="Bearer token">
    Use Bearer tokens for user-facing requests and interactive sessions.

    ```http theme={null}
    GET /api/v1/incident-ticket
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    Content-Type: application/json
    ```

    ```bash theme={null}
    curl https://your-api-domain.com/api/v1/incident-ticket \
      -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    ```
  </Tab>

  <Tab title="API key">
    Use API keys for server-to-server calls and automated pipelines.

    ```http theme={null}
    GET /api/v1/incident-ticket
    X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxx
    Content-Type: application/json
    ```

    ```bash theme={null}
    curl https://your-api-domain.com/api/v1/incident-ticket \
      -H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"
    ```
  </Tab>
</Tabs>

***

## Rate limits

Scrubbe enforces rate limits per route group to protect service availability. Requests that exceed a limit receive `429 Too Many Requests`.

| Limiter | Limit        | Window     | Applies to                             |
| ------- | ------------ | ---------- | -------------------------------------- |
| Global  | 200 requests | 15 minutes | All routes                             |
| Auth    | 10 requests  | 15 minutes | `POST /api/v1/auth/login`              |
| Email   | 3 requests   | 1 minute   | `/resend_otp`, `/forgot-password`      |
| API key | 100 requests | 1 minute   | Requests authenticated via `X-API-Key` |

When a limit is exceeded, the response body is:

```json theme={null}
{
  "success": false,
  "message": "Too many requests, please try again later"
}
```

The response includes standard `RateLimit-*` headers so you can inspect the current window and remaining quota programmatically.

<Tip>
  For high-throughput automation, prefer Bearer token authentication — API key requests share the stricter 100 requests/minute limit, while Bearer token requests fall under the broader global limit.
</Tip>

***

## Common authentication errors

| Status                  | Meaning                                          | What to do                                                                                     |
| ----------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| `401 Unauthorized`      | Missing, malformed, or expired token / key       | Re-authenticate to get a fresh access token, or verify your API key is correct and not revoked |
| `403 Forbidden`         | Valid credentials but insufficient role or scope | Check that your user role or API key scopes include the required permission for the endpoint   |
| `429 Too Many Requests` | Rate limit exceeded                              | Back off and retry after the window resets; check `RateLimit-Reset` header for timing          |

All error responses follow the standard format:

```json theme={null}
{
  "success": false,
  "message": "Error description"
}
```
