# API Reference

Base path: `/api/v1` (all endpoints below are relative to this unless noted).

## Authentication

Most endpoints require a Bearer token in the `Authorization` header:

```
Authorization: Bearer <access_token>
```

Obtain tokens via the auth endpoints (no auth required):

| Method | Path | Description |
|--------|------|-------------|
| POST | `/auth/register` | Create account (if registration enabled) |
| POST | `/auth/login` | Login, returns access + refresh tokens |
| POST | `/auth/refresh` | Refresh access token |
| POST | `/auth/logout` | Invalidate refresh token |
| GET | `/auth/oidc/login` | OIDC login redirect (when `AUTH_MODE=oidc`) |
| GET | `/auth/oidc/callback` | OIDC callback handler |

## Error Format

All errors return JSON:

```json
{"error": "description of what went wrong"}
```

Standard HTTP status codes: 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 500 (server error).

## Pagination

List endpoints accept query parameters:

| Param | Default | Description |
|-------|---------|-------------|
| `limit` | 50 | Max items to return |
| `offset` | 0 | Number of items to skip |

## Endpoints by Category

### Profile & Settings

| Method | Path | Description |
|--------|------|-------------|
| GET | `/profile` | Current user profile |
| PUT | `/profile` | Update profile |
| POST | `/profile/password` | Change password |
| GET | `/settings` | User settings |
| PUT | `/settings` | Update user settings |
| GET | `/profile/permissions` | List granted permissions |
| GET | `/profile/bootstrap` | Bootstrap data for frontend |

### Surfaces & Extensions

| Method | Path | Description |
|--------|------|-------------|
| GET | `/surfaces` | List enabled surfaces |
| GET | `/extensions` | List user extensions |
| POST | `/extensions/:id/settings` | Update extension settings |
| GET | `/extensions/:id/manifest` | Get extension manifest |
| GET | `/settings/public` | Public platform settings |

### Notifications

| Method | Path | Description |
|--------|------|-------------|
| GET | `/notifications` | List notifications |
| GET | `/notifications/unread-count` | Unread count |
| PATCH | `/notifications/:id/read` | Mark as read |
| POST | `/notifications/mark-all-read` | Mark all read |
| DELETE | `/notifications/:id` | Delete notification |
| GET | `/notifications/preferences` | Notification preferences |
| PUT | `/notifications/preferences/:type` | Set preference |

### Workflows

| Method | Path | Description |
|--------|------|-------------|
| GET | `/workflows` | List workflows |
| POST | `/workflows` | Create workflow |
| GET | `/workflows/:id` | Get workflow |
| PATCH | `/workflows/:id` | Update workflow |
| DELETE | `/workflows/:id` | Delete workflow |
| POST | `/workflows/:id/publish` | Publish version |
| POST | `/workflows/:id/clone` | Clone workflow |
| POST | `/workflows/:id/instances` | Start instance |
| GET | `/workflows/:id/instances` | List instances |
| GET | `/assignments/mine` | My assignments |

### Teams

| Method | Path | Description |
|--------|------|-------------|
| GET | `/teams/mine` | List my teams |
| GET | `/teams/:id/members` | Team members |
| POST | `/teams/:id/members` | Add member |
| GET | `/teams/:id/roles` | Team roles |

### Connections

| Method | Path | Description |
|--------|------|-------------|
| GET | `/connections` | List connections |
| POST | `/connections` | Create connection |
| GET | `/connections/resolve` | Resolve connection by type |
| PUT | `/connections/:id` | Update connection |
| DELETE | `/connections/:id` | Delete connection |

### Packages (User)

| Method | Path | Description |
|--------|------|-------------|
| GET | `/packages` | List visible packages |
| POST | `/packages/install` | Install personal package |
| DELETE | `/packages/:id` | Delete personal package |

### Admin Endpoints

All under `/api/v1/admin/` -- require `surface.admin.access` permission.

| Method | Path | Description |
|--------|------|-------------|
| GET | `/admin/users` | List users |
| POST | `/admin/users` | Create user |
| GET | `/admin/stats` | Platform statistics |
| GET | `/admin/settings` | Global settings |
| PUT | `/admin/settings/:key` | Update setting |
| GET | `/admin/packages` | List all packages |
| POST | `/admin/packages/install` | Install package (.pkg upload) |
| POST | `/admin/packages/:id/update` | Update package |
| GET | `/admin/packages/:id/export` | Export package as .pkg |
| PUT | `/admin/packages/:id/enable` | Enable package |
| PUT | `/admin/packages/:id/disable` | Disable package |
| DELETE | `/admin/packages/:id` | Delete package |
| GET | `/admin/cluster` | Cluster node list (Postgres only) |
| POST | `/admin/backup` | Create backup |
| GET | `/admin/backups` | List backups |
| POST | `/admin/restore` | Restore from backup |

### Health & Monitoring

These are at the base path (not under `/api/v1`):

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Basic health check |
| GET | `/healthz/live` | Liveness probe (Kubernetes) |
| GET | `/healthz/ready` | Readiness probe (Kubernetes) |
| GET | `/metrics` | Prometheus metrics |
| GET | `/api/docs` | OpenAPI documentation UI (Swagger) |
| GET | `/api/docs/openapi.json` | Dynamic OpenAPI 3.0 spec (includes extension routes) |
| GET | `/api/docs/openapi.yaml` | Static kernel-only OpenAPI spec (YAML) |

### Webhooks (Public)

| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/api/v1/hooks/:package_id/:slug` | Inbound webhook for extensions |
| POST | `/api/v1/workflows/public/:id/start` | Public workflow entry |

## WebSocket

Connect to `/ws` with a ticket-based auth flow:

1. POST `/api/v1/ws/ticket` with Bearer token to get a one-time ticket.
2. Connect to `/ws?ticket=<ticket>`.

The WebSocket carries JSON-framed events. Subscribe to channels with:

```json
{"type": "subscribe", "channel": "notifications"}
```

Kernel event prefixes: `user.*`, `team.*`, `workflow.*`, `notification.*`, `presence.*`, `extension.*`, `admin.*`, `system.*`.

### Presence

| Method | Path | Description |
|--------|------|-------------|
| POST | `/presence/heartbeat` | Update presence status |
| GET | `/presence` | Query online users |
| GET | `/users/search` | Search users |

### Forms (v0.9.5)

| Method | Path | Description |
|--------|------|-------------|
| POST | `/forms/validate` | Validate form data against a typed template |

**Request body:**

```json
{
  "template": {
    "fields": [
      {"key": "name", "type": "text", "label": "Name", "required": true}
    ]
  },
  "data": {"name": "Alice"}
}
```

**Response:**

```json
{"valid": true, "errors": []}
```

On validation failure, `errors` contains `[{"key": "name", "message": "Name is required"}]`.
