# API Documentation

Complete REST API documentation for the Feuerwehr Dashboard backend.

## Table of Contents

- [Base URL](#base-url)
- [Authentication](#authentication)
- [Rate Limiting](#rate-limiting)
- [Response Format](#response-format)
- [Error Codes](#error-codes)
- [Health Check](#health-check)
- [Authentication Endpoints](#authentication-endpoints)
- [User Endpoints](#user-endpoints)
- [Request Examples](#request-examples)

## Base URL

### Development
```
http://localhost:3000
```

### Production
```
https://start.feuerwehr-rems.at
```

## Authentication

The API uses JWT (JSON Web Token) bearer authentication for protected endpoints.

### Authentication Header Format

```http
Authorization: Bearer <your-jwt-token>
```

### How to Get Tokens

1. User authenticates via Authentik OAuth flow
2. Frontend receives authorization code
3. Frontend sends code to `/api/auth/callback`
4. Backend returns `accessToken` and `refreshToken`
5. Frontend includes `accessToken` in subsequent requests

### Token Expiration

- **Access Token**: 1 hour (3600 seconds)
- **Refresh Token**: 24 hours (86400 seconds)

Use `/api/auth/refresh` endpoint to get a new access token before it expires.

## Rate Limiting

All `/api/*` endpoints are rate-limited to prevent abuse.

### Limits

- **Window**: 15 minutes
- **Max Requests**: 100 requests per IP

### Rate Limit Headers

```http
RateLimit-Limit: 100
RateLimit-Remaining: 95
RateLimit-Reset: 1645564800
```

### Rate Limit Exceeded Response

```http
HTTP/1.1 429 Too Many Requests
```

```json
{
  "success": false,
  "message": "Too many requests from this IP, please try again later."
}
```

## Response Format

All API responses follow a consistent format:

### Success Response

```json
{
  "success": true,
  "message": "Operation completed successfully",
  "data": {
    // Response data here
  }
}
```

### Error Response

```json
{
  "success": false,
  "message": "Error description",
  "error": "Optional error details"
}
```

## Error Codes

### HTTP Status Codes

| Code | Meaning | Description |
|------|---------|-------------|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Authentication required or failed |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error occurred |

### Common Error Messages

```json
// Missing authentication
{
  "success": false,
  "message": "No token provided"
}

// Invalid token
{
  "success": false,
  "message": "Invalid or expired token"
}

// Inactive user
{
  "success": false,
  "message": "User account is inactive"
}
```

## Health Check

Check if the API is running and healthy.

### GET /health

**Authentication**: Not required

**Request**:
```http
GET /health HTTP/1.1
Host: start.feuerwehr-rems.at
```

**Response**:
```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "status": "ok",
  "timestamp": "2026-02-23T10:30:00.000Z",
  "uptime": 3600.5,
  "environment": "production"
}
```

**Response Fields**:
- `status` (string): Always "ok" if server is running
- `timestamp` (string): Current server time in ISO 8601 format
- `uptime` (number): Server uptime in seconds
- `environment` (string): Current environment (development/production)

## Authentication Endpoints

### POST /api/auth/callback

Handle OAuth callback and exchange authorization code for tokens.

**Authentication**: Not required

**Request Body**:
```json
{
  "code": "authorization_code_from_authentik"
}
```

**Request Example**:
```http
POST /api/auth/callback HTTP/1.1
Host: start.feuerwehr-rems.at
Content-Type: application/json

{
  "code": "abc123def456ghi789"
}
```

**Success Response**:
```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "success": true,
  "message": "Authentication successful",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "email": "john.doe@feuerwehr.de",
      "name": "John Doe",
      "preferredUsername": "john.doe",
      "givenName": "John",
      "familyName": "Doe",
      "profilePictureUrl": "https://auth.example.com/media/avatars/john.jpg",
      "isActive": true
    }
  }
}
```

**Error Responses**:

```http
HTTP/1.1 400 Bad Request
```
```json
{
  "success": false,
  "message": "Authorization code is required"
}
```

```http
HTTP/1.1 403 Forbidden
```
```json
{
  "success": false,
  "message": "User account is inactive"
}
```

```http
HTTP/1.1 500 Internal Server Error
```
```json
{
  "success": false,
  "message": "Authentication failed"
}
```

**Response Fields**:
- `accessToken` (string): JWT access token for API authentication
- `refreshToken` (string): JWT refresh token for getting new access tokens
- `user` (object): User profile information
  - `id` (number): User database ID
  - `email` (string): User email address
  - `name` (string): Full name
  - `preferredUsername` (string): Preferred username
  - `givenName` (string): First name
  - `familyName` (string): Last name
  - `profilePictureUrl` (string): URL to profile picture
  - `isActive` (boolean): Whether user account is active

---

### POST /api/auth/refresh

Refresh an expired access token using a refresh token.

**Authentication**: Not required (uses refresh token)

**Request Body**:
```json
{
  "refreshToken": "your_refresh_token"
}
```

**Request Example**:
```http
POST /api/auth/refresh HTTP/1.1
Host: start.feuerwehr-rems.at
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

**Success Response**:
```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "success": true,
  "message": "Token refreshed successfully",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}
```

**Error Responses**:

```http
HTTP/1.1 400 Bad Request
```
```json
{
  "success": false,
  "message": "Refresh token is required"
}
```

```http
HTTP/1.1 401 Unauthorized
```
```json
{
  "success": false,
  "message": "Invalid refresh token"
}
```

```http
HTTP/1.1 403 Forbidden
```
```json
{
  "success": false,
  "message": "User account is inactive"
}
```

**Response Fields**:
- `accessToken` (string): New JWT access token

---

### POST /api/auth/logout

Logout the current user.

**Authentication**: Optional (for logging purposes)

**Request Headers**:
```http
Authorization: Bearer <access-token>
```

**Request Example**:
```http
POST /api/auth/logout HTTP/1.1
Host: start.feuerwehr-rems.at
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

**Success Response**:
```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "success": true,
  "message": "Logout successful"
}
```

**Note**: Since this API uses stateless JWT authentication, logout is primarily handled client-side by discarding the tokens. This endpoint exists for audit logging purposes.

---

## User Endpoints

### GET /api/user/me

Get the currently authenticated user's profile.

**Authentication**: Required

**Request Headers**:
```http
Authorization: Bearer <access-token>
```

**Request Example**:
```http
GET /api/user/me HTTP/1.1
Host: start.feuerwehr-rems.at
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

**Success Response**:
```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "success": true,
  "data": {
    "id": 1,
    "email": "john.doe@feuerwehr.de",
    "name": "John Doe",
    "preferredUsername": "john.doe",
    "givenName": "John",
    "familyName": "Doe",
    "profilePictureUrl": "https://auth.example.com/media/avatars/john.jpg",
    "isActive": true,
    "lastLoginAt": "2026-02-23T10:30:00.000Z",
    "createdAt": "2026-01-01T12:00:00.000Z"
  }
}
```

**Error Responses**:

```http
HTTP/1.1 401 Unauthorized
```
```json
{
  "success": false,
  "message": "Not authenticated"
}
```

```http
HTTP/1.1 404 Not Found
```
```json
{
  "success": false,
  "message": "User not found"
}
```

**Response Fields**:
- `id` (number): User database ID
- `email` (string): User email address
- `name` (string): Full name
- `preferredUsername` (string): Preferred username
- `givenName` (string): First name
- `familyName` (string): Last name
- `profilePictureUrl` (string): URL to profile picture
- `isActive` (boolean): Whether user account is active
- `lastLoginAt` (string): Last login timestamp (ISO 8601)
- `createdAt` (string): Account creation timestamp (ISO 8601)

---

## Request Examples

### Full Authentication Flow Example

#### Step 1: User Clicks Login

Frontend redirects to Authentik:
```javascript
const authentikAuthUrl = `https://auth.firesuite.feuerwehr-rems.at/application/o/authorize/`;
const params = new URLSearchParams({
  client_id: 'your_client_id',
  redirect_uri: 'https://start.feuerwehr-rems.at/auth/callback',
  response_type: 'code',
  scope: 'openid profile email'
});

window.location.href = `${authentikAuthUrl}?${params}`;
```

#### Step 2: Authentik Redirects Back

After authentication, Authentik redirects to:
```
https://start.feuerwehr-rems.at/auth/callback?code=abc123def456
```

#### Step 3: Exchange Code for Tokens

```bash
curl -X POST https://start.feuerwehr-rems.at/api/auth/callback \
  -H "Content-Type: application/json" \
  -d '{
    "code": "abc123def456"
  }'
```

Response:
```json
{
  "success": true,
  "message": "Authentication successful",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImVtYWlsIjoiam9obkBleGFtcGxlLmNvbSIsImlhdCI6MTcwODY5MTQwMCwiZXhwIjoxNzA4Njk1MDAwfQ.signature",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImVtYWlsIjoiam9obkBleGFtcGxlLmNvbSIsImlhdCI6MTcwODY5MTQwMCwiZXhwIjoxNzA4Nzc3ODAwfQ.signature",
    "user": {
      "id": 1,
      "email": "john.doe@feuerwehr.de",
      "name": "John Doe",
      "preferredUsername": "john.doe",
      "givenName": "John",
      "familyName": "Doe",
      "profilePictureUrl": null,
      "isActive": true
    }
  }
}
```

#### Step 4: Access Protected Resources

```bash
curl -X GET https://start.feuerwehr-rems.at/api/user/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

#### Step 5: Refresh Token When Expired

```bash
curl -X POST https://start.feuerwehr-rems.at/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'
```

### JavaScript/TypeScript Examples

#### Using Axios

```typescript
import axios from 'axios';

const API_URL = 'https://start.feuerwehr-rems.at';

// Create axios instance with auth
const api = axios.create({
  baseURL: API_URL,
  headers: {
    'Content-Type': 'application/json',
  },
});

// Add auth token to requests
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('accessToken');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Handle authentication
export const handleCallback = async (code: string) => {
  const response = await api.post('/api/auth/callback', { code });
  const { accessToken, refreshToken, user } = response.data.data;

  // Store tokens
  localStorage.setItem('accessToken', accessToken);
  localStorage.setItem('refreshToken', refreshToken);

  return user;
};

// Refresh token
export const refreshAccessToken = async () => {
  const refreshToken = localStorage.getItem('refreshToken');
  const response = await api.post('/api/auth/refresh', { refreshToken });
  const { accessToken } = response.data.data;

  localStorage.setItem('accessToken', accessToken);
  return accessToken;
};

// Get current user
export const getCurrentUser = async () => {
  const response = await api.get('/api/user/me');
  return response.data.data;
};

// Logout
export const logout = async () => {
  await api.post('/api/auth/logout');
  localStorage.removeItem('accessToken');
  localStorage.removeItem('refreshToken');
};
```

### cURL Examples

#### Health Check
```bash
curl -X GET https://start.feuerwehr-rems.at/health
```

#### Login Callback
```bash
curl -X POST https://start.feuerwehr-rems.at/api/auth/callback \
  -H "Content-Type: application/json" \
  -d '{"code":"your_auth_code"}'
```

#### Get Current User
```bash
curl -X GET https://start.feuerwehr-rems.at/api/user/me \
  -H "Authorization: Bearer your_access_token"
```

#### Refresh Token
```bash
curl -X POST https://start.feuerwehr-rems.at/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refreshToken":"your_refresh_token"}'
```

#### Logout
```bash
curl -X POST https://start.feuerwehr-rems.at/api/auth/logout \
  -H "Authorization: Bearer your_access_token"
```

## Security Considerations

### HTTPS Required in Production

Always use HTTPS for API requests in production to protect tokens and sensitive data.

### Token Storage

- **Access Token**: Store in memory or sessionStorage (more secure)
- **Refresh Token**: Can be stored in httpOnly cookie or localStorage
- **Never**: Store tokens in unencrypted cookies or URL parameters

### CORS Configuration

The API is configured to only accept requests from allowed origins:

```javascript
// Backend CORS configuration
cors({
  origin: process.env.CORS_ORIGIN, // e.g., https://start.feuerwehr-rems.at
  credentials: true
})
```

Ensure `CORS_ORIGIN` environment variable matches your frontend URL exactly.

### Rate Limiting

Respect rate limits to avoid being temporarily blocked. Implement exponential backoff for failed requests.

## Additional Notes

### Timestamps

All timestamps are in ISO 8601 format with UTC timezone:
```
2026-02-23T10:30:00.000Z
```

### JSON Format

All request bodies and responses use JSON format with `Content-Type: application/json`.

### Versioning

API versioning is currently not implemented. All endpoints are under `/api/` prefix.

Future versions may use:
- `/api/v1/` for version 1
- `/api/v2/` for version 2

## Support

For API support:

1. Check this documentation
2. Review [DEVELOPMENT.md](DEVELOPMENT.md) for debugging tips
3. Check backend logs for detailed error messages
4. Consult [ARCHITECTURE.md](ARCHITECTURE.md) for system design
5. Create an issue with detailed request/response information

## Changelog

### Version 1.0.0 (2026-02-23)

Initial API release:
- OAuth 2.0 authentication with Authentik
- JWT-based session management
- User profile endpoints
- Health check endpoint
- Rate limiting
- Security headers
