Files
AFC-Demo/docs/api-documentation.md
T
cbazza 2f7bd923df
Build and Push Docker Image only on Conventional Commits / build (push) Has been cancelled
local-docker-db branch openend
2025-12-03 12:59:30 +01:00

21 KiB

API-Dokumentation: Risk Intelligence Platform

📋 Inhaltsverzeichnis

  1. Übersicht
  2. API-Spezifikation
  3. Authentication
  4. Endpoints
  5. Datenmodelle
  6. Beispiele
  7. Error Handling
  8. Rate Limiting
  9. 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 dokumentiert.

Swagger UI: Die Spezifikation kann mit Swagger Editor 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.

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

Login-Flow

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

email=user@example.com&password=secret
  1. Session Cookie erhalten:
HTTP/1.1 302 Found
Set-Cookie: laravel_session=eyJ....; Path=/; HttpOnly; SameSite=lax
  1. API-Request mit Cookie:
GET /api/dashboard/overview HTTP/1.1
Cookie: laravel_session=eyJ....

Authentifizierungs-Fehler

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:

GET /api/dashboard/overview HTTP/1.1
Cookie: laravel_session=...

Response: 200 OK

{
  "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:

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

Response: 200 OK

{
  "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:

GET /api/transactions/512 HTTP/1.1
Cookie: laravel_session=...

Response: 200 OK

{
  "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:

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

Response: 200 OK

{
  "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:

GET /api/companies/12 HTTP/1.1
Cookie: laravel_session=...

Response: 200 OK

{
  "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:

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

Response: 200 OK

{
  "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:

GET /api/companies/12/transactions/877 HTTP/1.1
Cookie: laravel_session=...

Response: 200 OK

{
  "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

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

KYC Risk Level

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

Pagination Meta

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

Count Amount Summary

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

Transaction Signal

{
  "type": "Adverse Media",
  "value": "Enforcement action reported in 2024-11",
  "weight": 0.8
}
{
  "title": "Verdachtsmeldung vorbereiten",
  "description": "Erstellen Sie den Meldeentwurf für die FIU..."
}

Beispiele

cURL-Beispiele

# 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

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

Transactions filtern

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

Company suchen

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

Company Transactions abrufen

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

JavaScript (Fetch API)

// 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

// 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

{
  "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

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

{
  "message": "Unauthenticated."
}

Aktion: Redirect zu /login

Beispiel: 404 Not Found

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

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

Beispiel: 422 Validation Error

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:

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)
  • 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:
// 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']);
});
  1. API Controllers erstellen:
php artisan make:controller Api/DashboardController
php artisan make:controller Api/TransactionController
php artisan make:controller Api/CompanyController
  1. API Resources erstellen:
php artisan make:resource TransactionResource
php artisan make:resource CompanyResource
  1. Tests schreiben:
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