Authentication and API Client
The MATIH API client architecture is built on the native Fetch API with httpOnly cookie authentication, CSRF protection, automatic retries with exponential backoff, configurable timeouts, and unified pagination normalization across Java (Spring Boot) and Python (FastAPI) backends. The base ApiClient class at frontend/shared/src/api/client.ts serves as the foundation for 16 domain-specific service clients.
Base API Client
Configuration
interface ApiConfig {
baseUrl: string;
tenantId: string;
userId?: string;
accessToken?: string; // @deprecated - use httpOnly cookies
onUnauthorized?: () => void;
withCredentials?: boolean; // Default: true
timeout?: number; // Default: 30000ms
retries?: number; // Default: 2
}Authentication Model
The API client uses httpOnly cookies for authentication. Tokens are set by the backend and sent automatically with credentials: 'include'. CSRF protection is provided via the X-XSRF-TOKEN header extracted from a cookie set by the backend.
Retry Strategy
Automatic retries with exponential backoff for 5xx and 429 responses:
| Attempt | Delay |
|---|---|
| 1st retry | 1000ms |
| 2nd retry | 2000ms |
| 3rd retry | 4000ms |
Unified Pagination
The normalizePagedResponse function handles pagination differences between Spring Boot (content/totalElements) and FastAPI (items/total) backends, plus cursor-based pagination.
Service Client Modules
| Client | Backend Service | Port | Key Operations |
|---|---|---|---|
BIApiClient | bi-service | 8084 | Dashboards, widgets, filters, exports |
QueryApiClient | query-engine | 8080 | SQL execution, query history |
SemanticApiClient | semantic-layer | 8086 | Models, entities, metrics |
AIApiClient | ai-service | 8000 | Chat sessions, agent execution |
MLApiClient | ml-service | 8000 | Experiments, models, deployments |
DataApiClient | catalog-service | 8086 | Assets, lineage, quality |
PipelineApiClient | pipeline-service | 8092 | Pipeline CRUD, runs |
DbtApiClient | pipeline-service | 8092 | dbt projects, models, runs |
DataQualityApiClient | data-quality-service | 8000 | Rules, profiles, SLA |
GovernanceApiClient | governance-service | 8080 | Policies, access requests |
OntologyApiClient | ontology-service | 8101 | Object types, properties |
RenderApiClient | render-service | 8098 | PDF/PNG export |
OpsAgentApiClient | ops-agent-service | 8080 | Chat, actions, health |
AgentStudioApiClient | ai-service | 8000 | Templates, configs |
NotificationApiClient | notification-service | 8085 | Notifications, channels |
BillingApiClient | billing-service | 8087 | Plans, subscriptions, invoices |
Singleton Pattern
let apiClientInstance: ApiClient | null = null;
export function initializeApiClient(config: ApiConfig): ApiClient {
apiClientInstance = new ApiClient(config);
return apiClientInstance;
}
export function getApiClient(): ApiClient {
if (!apiClientInstance) {
throw new Error('API client not initialized.');
}
return apiClientInstance;
}For detailed API client internals, see Shared Library - API Clients.