Multi-agent AI laboratory with ASP.NET Core 8.0 backend and Flutter frontend. Implements CQRS architecture, OpenAPI contract-first API design. BACKEND: Agent management, conversations, executions with PostgreSQL + Ollama FRONTEND: Cross-platform UI with strict typing and Result-based error handling Co-Authored-By: Jean-Philippe Brule <jp@svrnty.io>
3.6 KiB
API Quick Reference
Quick reference for common API integration tasks. See api-contract.md for complete documentation.
Status: No Authentication Required (R&D Phase)
Connection
Base URL (Development): http://localhost:5246
Swagger UI: http://localhost:5246/swagger
CORS Allowed Origins:
- http://localhost:3000
- http://localhost:54952
- http://localhost:62000
Endpoint Patterns
| Type | Pattern | Method | Purpose |
|---|---|---|---|
| Query | /api/query/{name} |
POST/GET | Single value queries |
| Dynamic Query | /api/dynamicquery/{typename} |
POST | Paginated queries |
| Command | /api/command/{name} |
POST | Write operations |
Naming: HealthQuery → /api/query/health (suffix removed, lowercased)
Dynamic Query Request
{
"page": 1,
"pageSize": 20,
"filters": [
{
"path": "propertyName",
"type": "Equal",
"value": "searchValue"
}
],
"sorts": [
{
"path": "propertyName",
"ascending": true
}
]
}
Critical: Use path (not field), type (not operator), ascending boolean (not direction string)
Dynamic Query Response
{
"data": [...],
"totalRecords": 100,
"aggregates": []
}
Critical: Use totalRecords (not totalItems). Calculate totalPages yourself.
Filter Types
Equal, NotEqual, Contains, StartsWith, EndsWith, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual, In
Case-sensitive: Use exact capitalization (e.g., Equal not equal)
Validation Error (400)
{
"status": 400,
"title": "One or more validation errors occurred.",
"errors": {
"fieldName": ["Error message 1", "Error message 2"]
},
"traceId": "00-abc123-def456-00"
}
Critical: errors contains field-specific arrays of error messages
Common Mistakes to Avoid
Wrong: /api/query/userlist for paginated queries
Right: /api/dynamicquery/userlist
Wrong: { "field": "name", "operator": "Contains" }
Right: { "path": "name", "type": "Contains" }
Wrong: { "field": "name", "direction": "Ascending" }
Right: { "path": "name", "ascending": true }
Wrong: Reading response.totalItems
Right: Reading response.totalRecords
Wrong: Frontend on port 3000 or 5173 Right: Frontend on port 54952 (for CORS)
TypeScript Types
interface DynamicQueryCriteria {
page?: number;
pageSize?: number;
filters?: Array<{
path: string;
type: 'Equal' | 'NotEqual' | 'Contains' | 'StartsWith' | 'EndsWith' |
'GreaterThan' | 'GreaterThanOrEqual' | 'LessThan' | 'LessThanOrEqual' | 'In';
value: unknown;
}>;
sorts?: Array<{
path: string;
ascending: boolean;
}>;
}
interface DynamicQueryResponse<T> {
data: T[];
totalRecords: number;
aggregates: unknown[];
}
Dart Types
class DynamicQueryCriteria {
final int? page;
final int? pageSize;
final List<Filter>? filters;
final List<Sort>? sorts;
}
class Filter {
final String path;
final FilterType type; // enum: equal, contains, etc.
final dynamic value;
}
class Sort {
final String path;
final bool ascending;
}
class DynamicQueryResponse<T> {
final List<T> data;
final int totalRecords;
final List<dynamic> aggregates;
}
Testing
# Health check
curl -X POST http://localhost:5246/api/query/health \
-H "Content-Type: application/json" \
-d "{}"
# Expected response: true
For complete documentation, examples, and error handling, see frontend-api-integration.md.