# API Reference

---
title: API Reference
description: Vollständige API-Dokumentation für bitbylaw Motia Installation
date: 2026-02-07
version: 1.1.0
---

## Base URL

**Production (via KONG)**: `https://api.bitbylaw.com`  
**Development**: `http://localhost:3000`

---

## Authentication

### KONG API Gateway

Alle Produktions-API-Calls laufen über KONG mit API-Key-Authentifizierung:

```bash
curl -H "apikey: YOUR_API_KEY" https://api.bitbylaw.com/advoware/proxy?endpoint=employees
```

**Header**: `apikey: <your-api-key>`

### Development

Entwicklungs-Environment: Keine Authentifizierung auf Motia-Ebene erforderlich.

---

## Advoware Proxy API

### Universal Proxy Endpoint

Alle Advoware-API-Aufrufe laufen über einen universellen Proxy.

#### GET Request

**Endpoint**: `GET /advoware/proxy`

**Query Parameters**:
- `endpoint` (required): Advoware API endpoint (ohne Base-URL)
- Alle weiteren Parameter werden an Advoware weitergeleitet

**Example**:
```bash
curl -X GET "http://localhost:3000/advoware/proxy?endpoint=employees&limit=10"
```

**Response**:
```json
{
  "status": 200,
  "body": {
    "result": {
      "data": [...],
      "total": 100
    }
  }
}
```

#### POST Request

**Endpoint**: `POST /advoware/proxy`

**Query Parameters**:
- `endpoint` (required): Advoware API endpoint

**Request Body**: JSON data für Advoware API

**Example**:
```bash
curl -X POST "http://localhost:3000/advoware/proxy?endpoint=appointments" \
  -H "Content-Type: application/json" \
  -d '{
    "datum": "2026-02-10",
    "uhrzeitVon": "09:00:00",
    "text": "Meeting"
  }'
```

**Response**:
```json
{
  "status": 200,
  "body": {
    "result": {
      "id": "12345"
    }
  }
}
```

#### PUT Request

**Endpoint**: `PUT /advoware/proxy`

**Query Parameters**:
- `endpoint` (required): Advoware API endpoint (inkl. ID)

**Request Body**: JSON data für Update

**Example**:
```bash
curl -X PUT "http://localhost:3000/advoware/proxy?endpoint=appointments/12345" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Updated Meeting"
  }'
```

#### DELETE Request

**Endpoint**: `DELETE /advoware/proxy`

**Query Parameters**:
- `endpoint` (required): Advoware API endpoint (inkl. ID)

**Example**:
```bash
curl -X DELETE "http://localhost:3000/advoware/proxy?endpoint=appointments/12345"
```

**Response**:
```json
{
  "status": 200,
  "body": {
    "result": null
  }
}
```

### Error Responses

**400 Bad Request**:
```json
{
  "status": 400,
  "body": {
    "error": "Endpoint required as query param"
  }
}
```

**500 Internal Server Error**:
```json
{
  "status": 500,
  "body": {
    "error": "Internal server error",
    "details": "Error message"
  }
}
```

## Calendar Sync API

### Trigger Full Sync

**Endpoint**: `POST /advoware/calendar/sync`

**Request Body**:
```json
{
  "kuerzel": "ALL",
  "full_content": true
}
```

**Parameters**:
- `kuerzel` (optional): Mitarbeiter-Kürzel oder "ALL" (default: "ALL")
- `full_content` (optional): Volle Details vs. anonymisiert (default: true)

**Examples**:

Sync all employees:
```bash
curl -X POST "http://localhost:3000/advoware/calendar/sync" \
  -H "Content-Type: application/json" \
  -d '{"full_content": true}'
```

Sync single employee:
```bash
curl -X POST "http://localhost:3000/advoware/calendar/sync" \
  -H "Content-Type: application/json" \
  -d '{"kuerzel": "SB", "full_content": true}'
```

Sync with anonymization:
```bash
curl -X POST "http://localhost:3000/advoware/calendar/sync" \
  -H "Content-Type: application/json" \
  -d '{"full_content": false}'
```

**Response**:
```json
{
  "status": "triggered",
  "kuerzel": "ALL",
  "message": "Calendar sync triggered for ALL"
}
```

**Status Codes**:
- `200`: Sync triggered successfully
- `400`: Invalid request (z.B. lock aktiv)
- `500`: Internal error

## VMH Webhook Endpoints

Diese Endpoints werden von EspoCRM aufgerufen.

### Beteiligte Create Webhook

**Endpoint**: `POST /vmh/webhook/beteiligte/create`

**Request Body**: Array von Entitäten
```json
[
  {
    "id": "entity-123",
    "name": "Max Mustermann",
    "createdAt": "2026-02-07T10:00:00Z"
  }
]
```

**Response**:
```json
{
  "status": "received",
  "action": "create",
  "new_ids_count": 1,
  "total_ids_in_batch": 1
}
```

### Beteiligte Update Webhook

**Endpoint**: `POST /vmh/webhook/beteiligte/update`

**Request Body**: Array von Entitäten
```json
[
  {
    "id": "entity-123",
    "name": "Max Mustermann Updated",
    "modifiedAt": "2026-02-07T11:00:00Z"
  }
]
```

**Response**:
```json
{
  "status": "received",
  "action": "update",
  "new_ids_count": 1,
  "total_ids_in_batch": 1
}
```

### Beteiligte Delete Webhook

**Endpoint**: `POST /vmh/webhook/beteiligte/delete`

**Request Body**: Array von Entitäten
```json
[
  {
    "id": "entity-123",
    "deletedAt": "2026-02-07T12:00:00Z"
  }
]
```

**Response**:
```json
{
  "status": "received",
  "action": "delete",
  "new_ids_count": 1,
  "total_ids_in_batch": 1
}
```

### Webhook Features

**Batch Support**: Alle Webhooks unterstützen Arrays von Entitäten

**Deduplication**: Redis-basiert, verhindert Mehrfachverarbeitung

**Async Processing**: Events werden emittiert und asynchron verarbeitet

## Event Topics

Interne Event-Topics für Event-Driven Architecture (nicht direkt aufrufbar).

### calendar_sync_all

**Emitted by**: `calendar_sync_cron_step`, `calendar_sync_api_step`
**Subscribed by**: `calendar_sync_all_step`

**Payload**:
```json
{}
```

### calendar_sync_employee

**Emitted by**: `calendar_sync_all_step`, `calendar_sync_api_step`
**Subscribed by**: `calendar_sync_event_step`

**Payload**:
```json
{
  "kuerzel": "SB",
  "full_content": true
}
```

### vmh.beteiligte.create

**Emitted by**: `beteiligte_create_api_step`
**Subscribed by**: `beteiligte_sync_event_step`

**Payload**:
```json
{
  "entity_id": "123",
  "action": "create",
  "source": "webhook",
  "timestamp": "2026-02-07T10:00:00Z"
}
```

### vmh.beteiligte.update

**Emitted by**: `beteiligte_update_api_step`
**Subscribed by**: `beteiligte_sync_event_step`

**Payload**:
```json
{
  "entity_id": "123",
  "action": "update",
  "source": "webhook",
  "timestamp": "2026-02-07T11:00:00Z"
}
```

### vmh.beteiligte.delete

**Emitted by**: `beteiligte_delete_api_step`
**Subscribed by**: `beteiligte_sync_event_step`

**Payload**:
```json
{
  "entity_id": "123",
  "action": "delete",
  "source": "webhook",
  "timestamp": "2026-02-07T12:00:00Z"
}
```

## Rate Limits

### Google Calendar API

**Limit**: 600 requests/minute (enforced via Redis token bucket)

**Behavior**: 
- Requests wait if rate limit reached
- Automatic backoff on 403 errors
- Max retry: 4 attempts

### Advoware API

**Limit**: Unknown (keine offizielle Dokumentation)

**Behavior**:
- 30s timeout per request
- Automatic token refresh on 401
- No retry logic (fail fast)

## Error Handling

### Standard Error Response

```json
{
  "status": 400,
  "body": {
    "error": "Error description",
    "details": "Detailed error message"
  }
}
```

### HTTP Status Codes

- `200` - Success
- `400` - Bad Request (invalid input)
- `401` - Unauthorized (Advoware token invalid)
- `403` - Forbidden (rate limit)
- `404` - Not Found
- `500` - Internal Server Error
- `503` - Service Unavailable (Redis down)

### Common Errors

**Redis Connection Error**:
```json
{
  "status": 503,
  "body": {
    "error": "Redis connection failed"
  }
}
```

**Advoware API Error**:
```json
{
  "status": 500,
  "body": {
    "error": "Advoware API call failed",
    "details": "401 Unauthorized"
  }
}
```

**Lock Active Error**:
```json
{
  "status": 400,
  "body": {
    "error": "Sync already in progress for employee SB"
  }
}
```

## API Versioning

**Current Version**: v1 (implicit, no version in URL)

**Future**: API versioning via URL prefix (`/v2/api/...`)

## Health Check

**Coming Soon**: `/health` endpoint für Load Balancer

Expected response:
```json
{
  "status": "healthy",
  "services": {
    "redis": "up",
    "advoware": "up",
    "google": "up"
  }
}
```

## Testing

### Postman Collection

Import diese Collection für schnelles Testing:

```json
{
  "info": {
    "name": "bitbylaw API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "Advoware Proxy GET",
      "request": {
        "method": "GET",
        "url": "http://localhost:3000/advoware/proxy?endpoint=employees"
      }
    },
    {
      "name": "Calendar Sync Trigger",
      "request": {
        "method": "POST",
        "url": "http://localhost:3000/advoware/calendar/sync",
        "header": [{"key": "Content-Type", "value": "application/json"}],
        "body": {
          "mode": "raw",
          "raw": "{\"full_content\": true}"
        }
      }
    }
  ]
}
```

## Related Documentation

- [Architecture](ARCHITECTURE.md)
- [Development Guide](DEVELOPMENT.md)
- [Configuration](CONFIGURATION.md)
