# Authentication

FluxiQ Core uses **JWT (JSON Web Token)** authentication for API access. All API requests must include a valid access token in the `Authorization` header.

## Overview

| Method | Use Case | Token Lifetime |
|--------|----------|---------------|
| **API Key** | Server-to-server (merchants) | No expiry (revocable) |
| **JWT** | User sessions (banking, admin) | 15 minutes (access) + 7 days (refresh) |

## API Key Authentication

For merchant integrations, use API keys:

```http
GET /api/v1/accounts
Authorization: Bearer sk_live_abc123def456
Content-Type: application/json
```

### Generate API Key

```http
POST /api/v1/merchants/{merchant_id}/api-keys
Authorization: Bearer {admin_jwt_token}
Content-Type: application/json

{
  "name": "Production Key",
  "permissions": ["accounts:read", "pix:write", "transfers:write"]
}
```

**Response:**

```json
{
  "data": {
    "id": "key_01HQGX...",
    "name": "Production Key",
    "key": "sk_live_abc123def456ghi789",
    "permissions": ["accounts:read", "pix:write", "transfers:write"],
    "created_at": "2026-02-03T12:00:00Z"
  }
}
```

::: warning
The full API key is only shown once at creation time. Store it securely.
:::

## JWT Authentication

For user-facing applications (banking UI, admin console):

### Login

```http
POST /api/v1/auth/login
Content-Type: application/json

{
  "document": "12345678901",
  "password": "your-password"
}
```

**Response:**

```json
{
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
    "token_type": "Bearer",
    "expires_in": 900
  }
}
```

### Using the Token

```http
GET /api/v1/accounts
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
```

### Refresh Token

```http
POST /api/v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
```

### Logout

```http
POST /api/v1/auth/logout
Authorization: Bearer {access_token}
```

## Permissions (RBAC)

| Role | Description | Permissions |
|------|-------------|-------------|
| **owner** | Full access to all resources | `*` |
| **manager** | Manage accounts, view transactions | `accounts:*`, `transactions:read`, `pix:*` |
| **operator** | Execute transactions, view accounts | `accounts:read`, `transactions:read`, `pix:write` |

### Permission Scopes

| Scope | Description |
|-------|-------------|
| `accounts:read` | View account balances and details |
| `accounts:write` | Create and update accounts |
| `pix:read` | View PIX transactions |
| `pix:write` | Send and receive PIX payments |
| `transfers:read` | View internal transfers |
| `transfers:write` | Execute internal transfers |
| `webhooks:read` | View webhook configurations |
| `webhooks:write` | Create and manage webhooks |
| `users:read` | View user profiles |
| `users:write` | Manage user accounts |

## Rate Limiting

| Method | Limit | Window |
|--------|-------|--------|
| API Key | 1,000 req/min | Per key |
| JWT | 100 req/min | Per user |
| Unauthenticated | 10 req/min | Per IP |

Rate limit headers are included in all responses:

```http
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1706961600
```

## Error Responses

### 401 Unauthorized

```json
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired authentication token"
  }
}
```

### 403 Forbidden

```json
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Insufficient permissions for this operation",
    "required_permission": "pix:write"
  }
}
```

### 429 Too Many Requests

```json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 30 seconds",
    "retry_after": 30
  }
}
```
