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

# Authentication

> How to authenticate with the Credentials Portal API using session tokens or API keys.

The Credentials Portal API supports two authentication methods: **session tokens** (for user sessions) and **API keys** (for programmatic integrations).

## API keys (recommended for integrations)

API keys are long-lived credentials designed for server-to-server integrations. Create and manage them from **Settings → API Keys** in the app (admin access required).

API keys use the prefix `ck_` followed by a random string:

```
ck_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
```

### Using an API key

Include the key as a Bearer token in the `Authorization` header:

```http theme={null}
Authorization: Bearer ck_your_api_key_here
```

### API key scopes

Each key is created with specific scopes that limit what it can do:

| Scope              | Access                       |
| ------------------ | ---------------------------- |
| `read:people`      | List and get people          |
| `write:people`     | Create and update people     |
| `read:interviews`  | List and get interviews      |
| `write:interviews` | Create and update interviews |

<Warning>
  Store API keys securely. They grant access to your district's data. Revoke any key that may have been compromised from Settings → API Keys.
</Warning>

## Session tokens (for user-facing apps)

Session tokens are issued after a user completes email verification. They expire after 30 days.

### Request a login code

```bash theme={null}
curl -X POST https://app.credentialsportal.com/api/auth/request \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'
```

**Response:**

```json theme={null}
{
  "ok": true,
  "message": "Check your email"
}
```

### Verify the code

```bash theme={null}
curl -X POST https://app.credentialsportal.com/api/auth/verify \
  -H "Content-Type: application/json" \
  -d '{"code": "123456"}'
```

**Response:**

```json theme={null}
{
  "ok": true,
  "token": "your_session_token_here",
  "person": {
    "id": "abc12",
    "first": "Jane",
    "last": "Doe",
    "email": "user@example.com",
    "language": "en",
    "roles": { "1a": 1 },
    "district_id": "xyz99"
  },
  "district": {
    "id": "xyz99",
    "name": { "en": "My District" },
    "accent": "#6e5dec",
    "languages": ["en"],
    "billing_plan": "pro"
  }
}
```

### Verify via magic link

Users clicking the magic link in their email hit:

```
GET /api/auth/verify/:token
```

This returns the same response as code verification.

### Sign out

```bash theme={null}
curl -X POST https://app.credentialsportal.com/api/auth/logout \
  -H "Authorization: Bearer your_session_token"
```

**Response:**

```json theme={null}
{ "ok": true }
```

## Token TTLs

| Token type    | Lifetime                        |
| ------------- | ------------------------------- |
| Session token | 30 days                         |
| Login code    | 10 minutes                      |
| Magic link    | 30 minutes                      |
| API key       | Does not expire (until revoked) |

## Get the current user

```bash theme={null}
curl https://app.credentialsportal.com/api/me \
  -H "Authorization: Bearer your_token"
```

**Response:**

```json theme={null}
{
  "person": {
    "id": "abc12",
    "first": "Jane",
    "last": "Doe",
    "email": "user@example.com",
    "language": "en",
    "roles": { "1a": 1 },
    "district_id": "xyz99"
  },
  "districtId": "xyz99"
}
```
