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

# API Overview

> Concordia API architecture, authentication, and request patterns

## API Architecture

Concordia uses **Astro API routes** for server-side endpoints. All API routes are located in `/src/pages/api/` and follow RESTful conventions.

### Base URL Structure

All API endpoints are prefixed with `/api/`:

```
https://your-domain.com/api/{resource}
```

#### Endpoint Categories

* **Authentication**: `/api/auth/*` - Better Auth endpoints (login, register, session)
* **Admin Blog**: `/api/admin/blog/*` - Blog management (articles, authors, categories, comments, media)
* **Admin Services**: `/api/admin/services/*` - Services management (services, categories, availability, bookings, media)
* **Admin Organizations**: `/api/admin/organizations/*` - Organization and member management
* **Client Auth**: `/api/auth-client/*` - Client-side auth helpers (verification, password reset)
* **Profile**: `/api/profile/*` - User profile management

***

## Request/Response Patterns

### Request Format

All API endpoints accept JSON payloads:

```json theme={null}
{
  "action": "create",
  "field1": "value1",
  "field2": "value2"
}
```

### Response Format

Successful responses return JSON with HTTP 200/201:

```json theme={null}
{
  "ok": true,
  "id": "xyz123",
  "data": { ... }
}
```

Error responses include descriptive error codes:

```json theme={null}
{
  "error": "not_found",
  "message": "Resource not found"
}
```

### HTTP Status Codes

| Code | Meaning                              |
| ---- | ------------------------------------ |
| 200  | Success                              |
| 201  | Created                              |
| 400  | Bad Request (invalid input)          |
| 401  | Unauthorized (not authenticated)     |
| 403  | Forbidden (insufficient permissions) |
| 404  | Not Found                            |
| 413  | Payload Too Large                    |
| 415  | Unsupported Media Type               |
| 429  | Too Many Requests (rate limited)     |
| 500  | Internal Server Error                |

***

## Authentication Requirements

### Admin Endpoints

All `/api/admin/*` endpoints require:

1. **Active session** (cookie or Bearer token)
2. **Admin role** (checked via `guardAdmin` helper)

```typescript theme={null}
const guard = guardAdmin(locals);
if (guard) return guard; // Returns 403 if not admin
```

### Public Endpoints

* `/api/auth/*` - Open for authentication flows
* `/api/auth-client/*` - Open for email verification and password reset

### Session Management

Sessions are managed by Better Auth with:

* **Cookie-based sessions** (default)
* **Bearer token support** (for API clients)
* **Session duration**: 7 days
* **Session refresh**: Every 24 hours
* **Absolute timeout**: 7 days

***

## Rate Limiting

Concordia implements database-backed rate limiting through Better Auth.

### Configuration

From `/src/lib/auth/auth.ts:105-127`:

```typescript theme={null}
rateLimit: {
  enabled: true,
  storage: "database",
  skipSuccessfulRequests: false,
  skipFailedRequests: false,
  windows: [
    {
      key: "global_ip",
      max: 100,
      window: 60 * 1000, // 1 minute
    },
    {
      key: "sign_in",
      max: 5,
      window: 15 * 60 * 1000, // 15 minutes
    },
    {
      key: "sign_up",
      max: 10,
      window: 60 * 60 * 1000, // 1 hour
    },
  ],
}
```

### Rate Limits

| Endpoint Type   | Max Requests | Window     |
| --------------- | ------------ | ---------- |
| Global (per IP) | 100 requests | 1 minute   |
| Sign In         | 5 attempts   | 15 minutes |
| Sign Up         | 10 attempts  | 1 hour     |

### Rate Limit Headers

When rate limited, responses include:

* **HTTP 429 Too Many Requests**
* Error message: `"Too many login attempts"` or similar

***

## Error Handling

### Common Error Codes

| Error Code       | Description                     |
| ---------------- | ------------------------------- |
| `invalid_body`   | Request body is not valid JSON  |
| `missing_action` | Required `action` field missing |
| `missing_id`     | Required `id` field missing     |
| `not_found`      | Resource does not exist         |
| `forbidden`      | User lacks permission           |
| `unknown_action` | Invalid action specified        |
| `internal_error` | Server error occurred           |

### Error Response Example

```json theme={null}
{
  "error": "missing_action",
  "message": "The 'action' field is required"
}
```

***

## Security Headers

All API responses include security headers:

```typescript theme={null}
const securityHeaders = {
  'content-security-policy': "default-src 'none'; frame-ancestors 'none'; base-uri 'none';",
  'x-frame-options': 'DENY',
  'x-content-type-options': 'nosniff',
  'strict-transport-security': 'max-age=63072000; includeSubDomains; preload',
  'referrer-policy': 'no-referrer',
  'content-type': 'application/json',
};
```

***

## Pagination

List endpoints support pagination via query parameters:

```
GET /api/admin/blog/articles?page=2&perPage=20
```

### Parameters

<ParamField query="page" type="integer" default="1">
  Page number (1-indexed)
</ParamField>

<ParamField query="perPage" type="integer" default="20">
  Items per page (max: 100)
</ParamField>

### Response Format

```json theme={null}
{
  "articles": [...],
  "total": 150,
  "page": 2,
  "perPage": 20,
  "totalPages": 8
}
```

***

## Filtering & Search

Most list endpoints support filtering:

* `q` - Text search (slug, title, email, etc.)
* `status` - Filter by status (draft, published, etc.)
* `featured` - Filter featured items (true/false)
* `category` - Filter by category ID
* `organizationId` - Filter by organization

### Example

```
GET /api/admin/blog/articles?q=welcome&status=published&featured=true
```

***

## Audit Logging

All admin actions are logged to the `audit_log` table:

```typescript theme={null}
await db.insert(auditLog).values({
  id: generateId(),
  action: "blog.article.create",
  userId,
  targetId: id,
  data: { slug, status },
  createdAt: new Date(),
});
```

### Logged Actions

* All CRUD operations (create, update, delete)
* Authentication events (login, logout, signup)
* Member management (invite, remove, role changes)
* Content publication (publish, unpublish)

***

## API Endpoints by Category

### Authentication & Users

* **[Authentication API](/development/api/authentication)** - Login, registration, email verification, password reset
* **[Profile API](/development/api/profile)** - User profile management (GET, PATCH)
* **[Users API](/development/api/users)** - Admin user management, roles, bans, sessions

### Content Management

* **[Blog API](/development/api/blog)** - Articles, authors, categories, comments, media

### Services & Bookings

* **[Services API](/development/api/services)** - Service listings, categories, availability, bookings (admin)
* **[Public Bookings API](/development/api/public-bookings)** - Customer-facing booking creation

### Organizations

* **[Organizations API](/development/api/organizations)** - Organization CRUD, members, invitations, profiles

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication API" icon="key" href="/development/api/authentication">
    Login, register, and session management
  </Card>

  <Card title="Profile API" icon="user-circle" href="/development/api/profile">
    User profile CRUD operations
  </Card>

  <Card title="Blog API" icon="newspaper" href="/development/api/blog">
    Manage articles, authors, and categories
  </Card>

  <Card title="Services API" icon="briefcase" href="/development/api/services">
    Service listings, bookings, and availability
  </Card>

  <Card title="Organizations API" icon="building" href="/development/api/organizations">
    Organization and member management
  </Card>

  <Card title="Users API" icon="users" href="/development/api/users">
    Admin user management and moderation
  </Card>
</CardGroup>
