# 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)