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

# API Authentication

> How to authenticate with the PlaneConnection API using JWTs, API keys, and service tokens.

The PlaneConnection API supports multiple authentication methods depending on your use case. All authenticated endpoints return `401 Unauthorized` if no valid credentials are provided.

## Authentication Methods

<Tabs>
  <Tab title="JWT (Recommended)">
    The primary authentication method uses JSON Web Tokens. The API verifies JWT session tokens issued by the platform's authentication provider.

    ### Bearer Token

    Pass the session token in the `Authorization` header:

    ```bash theme={}
    curl -X GET https://api.planeconnection.com/api/v1/safety/reports \
      -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
      -H "Content-Type: application/json"
    ```

    ### Session Cookie

    Browser-based clients can authenticate using the session cookie, which is set automatically during sign-in. No manual header is needed when making requests from the same domain.
  </Tab>

  <Tab title="API Key">
    For service-to-service communication, use the `X-API-Key` header. API keys are verified using constant-time comparison to prevent timing attacks.

    ```bash theme={}
    curl -X GET https://api.planeconnection.com/api/v1/core/health \
      -H "X-API-Key: your-service-api-key" \
      -H "Content-Type: application/json"
    ```

    <Warning>
      API keys provide full access and are intended for trusted backend services only.
      Never expose API keys in client-side code.
    </Warning>
  </Tab>
</Tabs>

## Public Endpoints

The following endpoints do not require authentication:

| Endpoint                            | Description                                  |
| ----------------------------------- | -------------------------------------------- |
| `GET /health`                       | Liveness probe                               |
| `GET /readiness`                    | Deep readiness probe                         |
| `GET /`                             | API documentation (Scalar)                   |
| `GET /llms.txt`                     | LLM-optimized docs                           |
| `POST /api/webhooks/resend`         | Resend email webhooks (signature-verified)   |
| `POST /api/webhooks/stripe`         | Stripe payment webhooks (signature-verified) |
| `POST /api/webhooks/stripe-connect` | Stripe Connect webhooks (signature-verified) |
| `GET /api/v1/aviation/*`            | Public FAA data                              |
| `POST /api/v1/signup/*`             | Self-service signup                          |
| `GET /api/v1/utils/*`               | Utility endpoints (QR codes)                 |
| `POST /api/v1/sms/public/*`         | Anonymous safety report submission           |

## Role-Based Access Control (RBAC)

After authentication, the API enforces role-based access control. The authenticated user's role determines which endpoints and actions they can access.

### Role Hierarchy

Roles are organized in a hierarchy where higher-level roles have more privileges. Some endpoints require a minimum role level.

| Level | Roles                                                                                    |
| :---: | ---------------------------------------------------------------------------------------- |
|   8   | `platform_admin`                                                                         |
|   7   | `system_administrator`, `super_admin`                                                    |
|   6   | `admin`, `director_of_operations`, `accountable_executive`                               |
|   5   | `safety_manager`, `chief_pilot`, `director_of_maintenance`, `manager`, `sole_proprietor` |
|   4   | `investigator`, `dispatcher`, `staff`                                                    |
|   3   | `pilot`, `mechanic`, `cabin_crew`                                                        |
|   2   | `owner`, `auditor`, `inspector`                                                          |
|   1   | `customer`, `external_reporter`, `fbo_customer`                                          |

### Role Guards

The API enforces role-based access on every request:

* Unauthenticated requests receive `401`.
* Authenticated users whose role is below the minimum required level receive `403`.

For example, AI email endpoints require the `staff` role (level 4+), while webhook management requires `admin` (level 6+).

## Auth Context

Once authenticated, route handlers receive an `auth` context object with these fields:

| Field         | Type      | Description                           |
| ------------- | --------- | ------------------------------------- |
| `userId`      | `string`  | Unique user identifier                |
| `workspaceId` | `string`  | Current workspace/tenant ID           |
| `role`        | `string`  | User's role in the current workspace  |
| `isAdmin`     | `boolean` | Whether the user has admin privileges |
| `email`       | `string`  | User's email address                  |

## Token Verification

<Steps>
  ### Obtain a session token

  Obtain a session token from the authentication SDK in your frontend application.

  ### Include the token in your request

  Pass the token as a Bearer token in the `Authorization` header:

  ```bash theme={}
  curl -X GET https://api.planeconnection.com/api/v1/safety/reports \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Tenant-Id: workspace_abc123"
  ```

  ### Handle token expiration

  Session tokens are short-lived. If the API returns `401`, refresh the token using the authentication SDK and retry the request.
</Steps>

## Error Responses

| Status | Code                | Description                                |
| :----: | ------------------- | ------------------------------------------ |
|  `401` | `UNAUTHORIZED`      | Missing or invalid credentials             |
|  `403` | `FORBIDDEN`         | Authenticated but insufficient permissions |
|  `429` | `TOO_MANY_REQUESTS` | Rate limit exceeded on auth endpoints      |

```json theme={}
{
  "error": "Authentication required",
  "code": "UNAUTHORIZED",
  "requestId": "req_a1b2c3d4"
}
```
