# API-Dokumentation: Risk Intelligence Platform

## 📋 Inhaltsverzeichnis

1. [Übersicht](#übersicht)
2. [API-Spezifikation](#api-spezifikation)
3. [Authentication](#authentication)
4. [Endpoints](#endpoints)
5. [Datenmodelle](#datenmodelle)
6. [Beispiele](#beispiele)
7. [Error Handling](#error-handling)
8. [Rate Limiting](#rate-limiting)
9. [Changelog](#changelog)

---

## Übersicht

Die **Trusted AI Analyst Data API** stellt Daten für das Analyst Dashboard, Transaction Review, Company Search und Company Drill-Down bereit.

### API-Version

**Version:** 1.0.0
**Format:** JSON
**Authentifizierung:** Session-basiert (Laravel Session Cookie)

### Base URLs

| Environment | URL |
|-------------|-----|
| **Development** | `http://trusted_ai.test/api` |
| **Production** | `https://afc.trai.sft.comstack.de/api` |

### OpenAPI Spezifikation

Die vollständige API-Spezifikation ist in [swagger.yaml](../swagger.yaml) dokumentiert.

**Swagger UI:** Die Spezifikation kann mit [Swagger Editor](https://editor.swagger.io) oder Swagger UI visualisiert werden.

---

## API-Spezifikation

### API-Kategorien

| Tag | Beschreibung | Endpoints |
|-----|--------------|-----------|
| **Dashboard** | KPIs und Alert-Übersichten | 1 Endpoint |
| **Transactions** | Portfolio-weite Transaction Review | 2 Endpoints |
| **Companies** | Company Discovery & Drill-Down | 4 Endpoints |

**Gesamt:** 7 API-Endpoints

---

## Authentication

### Session-basierte Authentifizierung

Die API nutzt **Laravel Session Cookies** für die Authentifizierung.

```yaml
securitySchemes:
  sessionCookie:
    type: apiKey
    in: cookie
    name: laravel_session
```

### Login-Flow

1. **Login via Web-Interface:**
```http
POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

email=user@example.com&password=secret
```

2. **Session Cookie erhalten:**
```http
HTTP/1.1 302 Found
Set-Cookie: laravel_session=eyJ....; Path=/; HttpOnly; SameSite=lax
```

3. **API-Request mit Cookie:**
```http
GET /api/dashboard/overview HTTP/1.1
Cookie: laravel_session=eyJ....
```

### Authentifizierungs-Fehler

```json
HTTP/1.1 401 Unauthorized
{
  "message": "Unauthenticated."
}
```

**Wichtig:** Alle API-Endpoints erfordern eine gültige Session!

---

## Endpoints

### 1. Dashboard

#### GET /dashboard/overview

Liefert aggregierte KPIs und Alert-Übersichten für das Dashboard.

**Request:**
```http
GET /api/dashboard/overview HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "generatedAt": "2025-01-19T07:30:00Z",
  "activeAnalysts": 24,
  "totalTransactions": 312,
  "totalVolume": 98765432.10,
  "alertsToday": 56,
  "averageAlertsPerAnalyst": 3,
  "precisionRate": 84,
  "activeAlerts": {
    "count": 128,
    "highRiskCount": 19
  },
  "riskSegments": [
    {
      "label": "Kritisch (≥80)",
      "count": 17,
      "volume": 8900000.0
    },
    {
      "label": "Hoch (60-79)",
      "count": 42,
      "volume": 15200000.0
    },
    {
      "label": "Mittel (40-59)",
      "count": 89,
      "volume": 32100000.0
    }
  ],
  "topCompanies": [
    {
      "companyId": 24,
      "companyName": "Allianz SE",
      "ticker": "ALV",
      "sector": "Insurance",
      "alerts": 6,
      "alertVolume": 1450000.0,
      "avgRiskScore": 82
    }
  ],
  "runbooksExecutedToday": 41
}
```

---

### 2. Transactions

#### GET /transactions

Liste alle Transaktionen mit globalen Filtern (Portfolio-weite Transaction Review).

**Query Parameters:**

| Parameter | Typ | Default | Beschreibung |
|-----------|-----|---------|--------------|
| `search` | string | - | Match gegen Reference, Counterparty, Company |
| `status` | enum | `all` | `all`, `true_positive`, `false_positive`, `cleared` |
| `page` | integer | `1` | Seiten-Nummer (min: 1) |
| `perPage` | integer | `12` | Items pro Seite (min: 1, max: 100) |

**Request:**
```http
GET /api/transactions?status=true_positive&page=1&perPage=12 HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "filters": {
    "statusOptions": [
      {
        "value": "true_positive",
        "label": "Bestätigte Treffer"
      },
      {
        "value": "false_positive",
        "label": "Fehlalarme"
      },
      {
        "value": "cleared",
        "label": "Freigegeben"
      }
    ],
    "perPage": 12
  },
  "metrics": {
    "total": {
      "count": 312,
      "amount": 98765432.10
    },
    "byStatus": {
      "true_positive": {
        "count": 42,
        "amount": 15200000.0
      },
      "false_positive": {
        "count": 89,
        "amount": 32100000.0
      },
      "cleared": {
        "count": 181,
        "amount": 51465432.10
      }
    }
  },
  "data": [
    {
      "id": 512,
      "company": {
        "id": 12,
        "name": "Allianz",
        "legalName": "Allianz SE",
        "ticker": "ALV",
        "sector": "Insurance",
        "country": "Germany",
        "headquarters": "Munich",
        "kycRiskLevel": "high",
        "summary": "Multinational insurance provider with EMEA focus."
      },
      "counterparty": "Alpine Holdings Ltd.",
      "counterpartyCountry": "Switzerland",
      "status": "true_positive",
      "statusLabel": "Bestätigter Treffer",
      "requiresReview": true,
      "riskScore": 87,
      "amount": 245000.75,
      "currency": "EUR",
      "reference": "PAY-2024-10-1942",
      "channel": "SWIFT",
      "executedAt": "2025-01-18T09:14:00Z",
      "flaggedReason": "Counterparty on sanctions watchlist"
    }
  ],
  "pagination": {
    "page": 1,
    "perPage": 12,
    "total": 128,
    "lastPage": 11
  },
  "selectedTransactionId": null,
  "selectedTransaction": null
}
```

---

#### GET /transactions/{transactionId}

Hole detaillierte Transaction Case File.

**Path Parameters:**

| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `transactionId` | integer | Transaction ID |

**Request:**
```http
GET /api/transactions/512 HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "id": 512,
  "company": { ... },
  "counterparty": "Alpine Holdings Ltd.",
  "status": "true_positive",
  "statusLabel": "Bestätigter Treffer",
  "requiresReview": true,
  "riskScore": 87,
  "amount": 245000.75,
  "currency": "EUR",
  "reference": "PAY-2024-10-1942",
  "channel": "SWIFT",
  "executedAt": "2025-01-18T09:14:00Z",
  "flaggedBy": "Screening Engine",
  "flaggedReason": "Counterparty matched to EU sanctions list",
  "signals": [
    {
      "type": "Adverse Media",
      "value": "Enforcement action reported in 2024-11",
      "weight": 0.8
    },
    {
      "type": "Sanctions",
      "value": "EU Sanctions List Match",
      "weight": 1.0
    }
  ]
}
```

**Errors:**
- `401 Unauthorized` - Session ungültig
- `404 Not Found` - Transaction existiert nicht

---

### 3. Companies

#### GET /companies/search

Suche Companies und erhalte Screening-Übersicht.

**Query Parameters:**

| Parameter | Typ | Default | Beschreibung |
|-----------|-----|---------|--------------|
| `q` | string | - | Freitext-Suche (Name, Legal Name, Ticker, Sector) |
| `limit` | integer | `6` | Max. Ergebnisse (min: 1, max: 25) |

**Request:**
```http
GET /api/companies/search?q=Allianz&limit=6 HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "overview": {
    "totalCompanies": 40,
    "openAlerts": 112,
    "openAlertVolume": 5640000.0,
    "averageRiskScore": 71,
    "watchlistHits": 9,
    "automationShare": 82
  },
  "results": [
    {
      "id": 12,
      "name": "Allianz",
      "legalName": "Allianz SE",
      "ticker": "ALV",
      "sector": "Insurance",
      "country": "Germany",
      "headquarters": "Munich",
      "kycRiskLevel": "high",
      "summary": "Multinational insurance provider with EMEA focus.",
      "alertCount": 7,
      "alertVolume": 980000.0,
      "alertRiskScore": 79,
      "latestAlert": {
        "transactionId": 731,
        "counterparty": "Baltic Commodities LLC",
        "executedAt": "2025-01-17T11:48:00Z",
        "channel": "SWIFT",
        "flaggedReason": "Pattern matches sanctions typology",
        "riskScore": 88
      }
    }
  ],
  "meta": {
    "query": "Allianz",
    "resultCount": 6,
    "limit": 6
  }
}
```

---

#### GET /companies/{companyId}

Hole Company-Profil.

**Path Parameters:**

| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `companyId` | integer | Company ID |

**Request:**
```http
GET /api/companies/12 HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "id": 12,
  "name": "Allianz",
  "legalName": "Allianz SE",
  "ticker": "ALV",
  "sector": "Insurance",
  "country": "Germany",
  "headquarters": "Munich",
  "kycRiskLevel": "high",
  "summary": "Multinational insurance provider with EMEA focus.",
  "createdAt": "2024-10-15T08:30:00Z",
  "updatedAt": "2025-01-18T14:22:00Z"
}
```

**Errors:**
- `401 Unauthorized` - Session ungültig
- `404 Not Found` - Company existiert nicht

---

#### GET /companies/{companyId}/transactions

Liste alle Transactions für eine Company.

**Path Parameters:**

| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `companyId` | integer | Company ID |

**Query Parameters:**

| Parameter | Typ | Default | Beschreibung |
|-----------|-----|---------|--------------|
| `status` | enum | `all` | `all`, `true_positive`, `false_positive`, `cleared` |
| `channel` | string | `all` | Channel-Filter (z.B. `SWIFT`, `SEPA`) |
| `page` | integer | `1` | Seiten-Nummer |
| `perPage` | integer | `10` | Items pro Seite (min: 1, max: 100) |

**Request:**
```http
GET /api/companies/12/transactions?status=true_positive&page=1&perPage=10 HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "company": {
    "id": 12,
    "name": "Allianz",
    "legalName": "Allianz SE",
    "ticker": "ALV",
    "sector": "Insurance",
    "country": "Germany",
    "headquarters": "Munich",
    "kycRiskLevel": "high",
    "summary": "Multinational insurance provider..."
  },
  "filters": {
    "statusOptions": [
      {
        "value": "true_positive",
        "label": "Bestätigte Treffer"
      }
    ],
    "channelOptions": [
      {
        "value": "SWIFT",
        "label": "SWIFT"
      },
      {
        "value": "SEPA",
        "label": "SEPA"
      }
    ]
  },
  "metrics": {
    "totalCount": 96,
    "totalVolume": 7200000.0,
    "openAlerts": {
      "count": 12,
      "amount": 1850000.0
    },
    "highRiskShare": 28,
    "last30Days": {
      "count": 15,
      "amount": 980000.0
    },
    "byStatus": {
      "true_positive": {
        "count": 12,
        "amount": 1850000.0
      },
      "false_positive": {
        "count": 24,
        "amount": 2100000.0
      },
      "cleared": {
        "count": 60,
        "amount": 3250000.0
      }
    }
  },
  "data": [
    {
      "id": 877,
      "company": { ... },
      "counterparty": "Alpine Holdings Ltd.",
      "status": "true_positive",
      "riskScore": 87,
      "amount": 245000.75,
      "currency": "EUR",
      "reference": "PAY-2024-10-1942",
      "channel": "SWIFT",
      "executedAt": "2025-01-18T09:14:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "perPage": 10,
    "total": 12,
    "lastPage": 2
  },
  "selectedTransactionId": null,
  "selectedTransaction": null,
  "recentAlerts": [
    {
      "id": 911,
      "counterparty": "Northbridge Trading Ltd.",
      "executedAt": "2025-01-18T14:52:00Z",
      "channel": "SWIFT",
      "status": "true_positive",
      "statusLabel": "Bestätigter Treffer",
      "riskScore": 92
    }
  ]
}
```

**Errors:**
- `401 Unauthorized` - Session ungültig
- `404 Not Found` - Company nicht gefunden oder keine Transactions

---

#### GET /companies/{companyId}/transactions/{transactionId}

Hole Transaction Case File mit Company-Context und History.

**Path Parameters:**

| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `companyId` | integer | Company ID |
| `transactionId` | integer | Transaction ID |

**Request:**
```http
GET /api/companies/12/transactions/877 HTTP/1.1
Cookie: laravel_session=...
```

**Response:** `200 OK`
```json
{
  "id": 877,
  "company": { ... },
  "counterparty": "Alpine Holdings Ltd.",
  "status": "true_positive",
  "statusLabel": "Bestätigter Treffer",
  "requiresReview": true,
  "riskScore": 87,
  "amount": 245000.75,
  "currency": "EUR",
  "reference": "PAY-2024-10-1942",
  "channel": "SWIFT",
  "executedAt": "2025-01-18T09:14:00Z",
  "flaggedBy": "Screening Engine",
  "flaggedReason": "Counterparty matched to EU sanctions list",
  "signals": [
    {
      "type": "Adverse Media",
      "value": "Enforcement action reported in 2024-11",
      "weight": 0.8
    }
  ],
  "recommendedActions": [
    {
      "title": "Verdachtsmeldung vorbereiten",
      "description": "Erstellen Sie den Meldeentwurf für die FIU und sichern Sie Belege."
    },
    {
      "title": "Enhanced Due Diligence",
      "description": "Prüfen Sie zusätzliche Informationsquellen zur Counterparty."
    }
  ],
  "counterpartyHistory": [
    {
      "id": 765,
      "executedAt": "2024-12-22T15:37:00Z",
      "channel": "SWIFT",
      "reference": "PAY-2024-12-1187",
      "amount": 99000.0,
      "currency": "EUR",
      "riskScore": 74
    }
  ]
}
```

**Errors:**
- `401 Unauthorized` - Session ungültig
- `404 Not Found` - Transaction nicht gefunden für diese Company

---

## Datenmodelle

### Transaction Status

```typescript
enum TransactionStatus {
  TRUE_POSITIVE = 'true_positive',    // Kritisches Risiko
  FALSE_POSITIVE = 'false_positive',  // Hohes Risiko
  CLEARED = 'cleared'                 // Geringes Risiko
}
```

### KYC Risk Level

```typescript
enum KycRiskLevel {
  LOW = 'low',
  HIGH = 'high',
  CRITICAL = 'critical'
}
```

### Pagination Meta

```json
{
  "page": 1,
  "perPage": 12,
  "total": 128,
  "lastPage": 11
}
```

### Count Amount Summary

```json
{
  "count": 42,
  "amount": 2750000.50
}
```

### Transaction Signal

```json
{
  "type": "Adverse Media",
  "value": "Enforcement action reported in 2024-11",
  "weight": 0.8
}
```

### Recommended Action

```json
{
  "title": "Verdachtsmeldung vorbereiten",
  "description": "Erstellen Sie den Meldeentwurf für die FIU..."
}
```

---

## Beispiele

### cURL-Beispiele

#### Login & Session Cookie erhalten

```bash
# Login
curl -c cookies.txt -X POST http://trusted_ai.test/login \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=user@example.com&password=secret"

# Session Cookie ist jetzt in cookies.txt gespeichert
```

#### Dashboard Overview abrufen

```bash
curl -b cookies.txt http://trusted_ai.test/api/dashboard/overview
```

#### Transactions filtern

```bash
curl -b cookies.txt "http://trusted_ai.test/api/transactions?status=true_positive&page=1&perPage=12"
```

#### Company suchen

```bash
curl -b cookies.txt "http://trusted_ai.test/api/companies/search?q=Allianz&limit=6"
```

#### Company Transactions abrufen

```bash
curl -b cookies.txt "http://trusted_ai.test/api/companies/12/transactions?status=all&page=1"
```

---

### JavaScript (Fetch API)

```javascript
// Session Cookie wird automatisch vom Browser gesendet

// Dashboard Overview
const overview = await fetch('/api/dashboard/overview', {
  credentials: 'include'  // Wichtig: Session Cookie mitsenden
}).then(r => r.json());

console.log(overview);

// Transactions mit Filter
const transactions = await fetch('/api/transactions?status=true_positive&page=1&perPage=12', {
  credentials: 'include'
}).then(r => r.json());

console.log(transactions.data);

// Company Search
const companies = await fetch('/api/companies/search?q=Allianz', {
  credentials: 'include'
}).then(r => r.json());

console.log(companies.results);
```

---

### TypeScript Types

```typescript
// Dashboard Overview Response
interface DashboardOverview {
  generatedAt: string;
  activeAnalysts: number;
  totalTransactions: number;
  totalVolume: number;
  alertsToday: number;
  averageAlertsPerAnalyst: number;
  precisionRate: number;
  activeAlerts: {
    count: number;
    highRiskCount: number;
  };
  riskSegments: RiskSegment[];
  topCompanies: TopCompanyAlert[];
  runbooksExecutedToday: number;
}

// Transaction Collection Response
interface TransactionCollectionResponse {
  filters: {
    statusOptions: StatusOption[];
    perPage: number;
  };
  metrics: TransactionMetrics;
  data: TransactionPreview[];
  pagination: PaginationMeta;
  selectedTransactionId: number | null;
  selectedTransaction: TransactionDetail | null;
}

// Company Search Response
interface CompanySearchResponse {
  overview: CompanySearchOverview;
  results: CompanySearchResult[];
  meta: {
    query: string | null;
    resultCount: number;
    limit: number;
  };
}
```

---

## Error Handling

### Standard Error Response

```json
{
  "message": "Error message",
  "errors": {
    "field": ["Validation error"]
  }
}
```

### HTTP Status Codes

| Code | Bedeutung | Beschreibung |
|------|-----------|--------------|
| `200` | OK | Request erfolgreich |
| `401` | Unauthorized | Session ungültig oder abgelaufen |
| `404` | Not Found | Resource nicht gefunden |
| `422` | Unprocessable Entity | Validierungsfehler |
| `500` | Internal Server Error | Server-Fehler |

### Beispiel: 401 Unauthorized

```json
HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "message": "Unauthenticated."
}
```

**Aktion:** Redirect zu `/login`

### Beispiel: 404 Not Found

```json
HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "message": "Company not found."
}
```

### Beispiel: 422 Validation Error

```json
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "message": "The given data was invalid.",
  "errors": {
    "status": ["The selected status is invalid."],
    "page": ["The page must be at least 1."]
  }
}
```

---

## Rate Limiting

### Aktueller Status

**Aktuell:** Kein Rate Limiting implementiert.

### Geplant (Future)

```
Rate Limit: 60 Requests pro Minute pro User
Header: X-RateLimit-Limit, X-RateLimit-Remaining
```

**Response bei Überschreitung:**
```json
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60

{
  "message": "Too many requests. Please try again later."
}
```

---

## Changelog

### Version 1.0.0 (2025-01-19)

**Initial Release**

**Endpoints:**
- ✅ `GET /dashboard/overview` - Dashboard KPIs
- ✅ `GET /transactions` - Portfolio-wide Transactions
- ✅ `GET /transactions/{id}` - Transaction Detail
- ✅ `GET /companies/search` - Company Search
- ✅ `GET /companies/{id}` - Company Profile
- ✅ `GET /companies/{id}/transactions` - Company Transactions
- ✅ `GET /companies/{id}/transactions/{id}` - Company Transaction Detail

**Features:**
- Session-basierte Authentifizierung
- Pagination Support
- Filter & Search
- Metrics & Aggregationen
- OpenAPI 3.1 Spezifikation

---

## Implementierungs-Status

### ⚠️ Wichtig: API noch nicht implementiert!

Die in diesem Dokument beschriebenen Endpoints sind **aktuell noch nicht implementiert**.

**Status:**
- ✅ OpenAPI Spezifikation vorhanden ([swagger.yaml](../swagger.yaml))
- ❌ API Routes noch nicht definiert (`routes/api.php` ist leer)
- ❌ API Controllers noch nicht erstellt
- ❌ API Responses noch nicht implementiert

### Nächste Schritte zur Implementierung

1. **API Routes definieren:**
```php
// routes/api.php
Route::middleware(['auth:sanctum'])->group(function () {
    Route::get('/dashboard/overview', [DashboardController::class, 'overview']);
    Route::get('/transactions', [TransactionController::class, 'index']);
    Route::get('/transactions/{transaction}', [TransactionController::class, 'show']);
    Route::get('/companies/search', [CompanyController::class, 'search']);
    Route::get('/companies/{company}', [CompanyController::class, 'show']);
    Route::get('/companies/{company}/transactions', [CompanyController::class, 'transactions']);
});
```

2. **API Controllers erstellen:**
```bash
php artisan make:controller Api/DashboardController
php artisan make:controller Api/TransactionController
php artisan make:controller Api/CompanyController
```

3. **API Resources erstellen:**
```bash
php artisan make:resource TransactionResource
php artisan make:resource CompanyResource
```

4. **Tests schreiben:**
```bash
php artisan make:test Api/DashboardTest
php artisan make:test Api/TransactionTest
php artisan make:test Api/CompanyTest
```

---

## Zusammenfassung

### API-Übersicht

| Kategorie | Endpoints | Status |
|-----------|-----------|--------|
| Dashboard | 1 | ⚠️ Spezifiziert, nicht implementiert |
| Transactions | 2 | ⚠️ Spezifiziert, nicht implementiert |
| Companies | 4 | ⚠️ Spezifiziert, nicht implementiert |
| **Gesamt** | **7** | - |

### Datenmodelle

- **DashboardOverview** - Dashboard-KPIs
- **TransactionCollectionResponse** - Paginierte Transactions
- **TransactionDetail** - Detaillierte Transaction
- **CompanySearchResponse** - Company-Suchergebnisse
- **CompanyDetail** - Company-Profil
- **CompanyTransactionsResponse** - Company-spezifische Transactions

### Authentifizierung

**Session-basiert** via Laravel Session Cookie
- Login erforderlich
- Cookie-basierte Authentifizierung
- CSRF-Protection

---

**Erstellt:** 2025-11-24
**Version:** 1.0.0
**Autor:** Risk Intelligence Platform Team
**OpenAPI Spec:** [swagger.yaml](../swagger.yaml)
