cleanup
This commit is contained in:
514
bitbylaw/docs/API.md
Normal file
514
bitbylaw/docs/API.md
Normal file
@@ -0,0 +1,514 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user