# API Overview This document describes the conventions and patterns used throughout the B12 SIS API. ## Base URL ``` Production: https://api.yourschool.edu/api Development: http://localhost:8080/api ``` ## HTTP Methods | Method | Usage | |--------|-------| | GET | Retrieve a single resource | | POST | Create resource(s) or list with filters | | PUT | Update a resource | | DELETE | Soft-delete a resource | ## Request Headers ### Required Headers | Header | Description | Example | |--------|-------------|---------| | `Authorization` | JWT Bearer token | `Bearer eyJhbGci...` | | `X-Team-ID` | Current team/campus UUID | `550e8400-e29b-41d4-a716-446655440000` | | `Content-Type` | Request content type | `application/json` | ### Optional Headers | Header | Description | |--------|-------------| | `X-Academic-Session-ID` | Current academic session UUID | | `Accept-Language` | Preferred language (`en`, `vi`) | ## Response Format ### Success Response ```json { "success": true, "message": "Operation description", "data": { ... } } ``` ### Error Response ```json { "success": false, "message": "Error description", "errors": "Detailed error information" } ``` ### List Response ```json { "success": true, "message": "Records retrieved successfully", "data": { "list": [ ... ], "pagination": { "page": 1, "limit": 20, "total": 100 }, "metadata": { "field_definitions": { ... } } } } ``` ## Standard CRUD Endpoints Every module follows this endpoint pattern: | Endpoint | Method | Description | |----------|--------|-------------| | `/{module}` | POST | Create a single record | | `/{module}/bulk` | POST | Create multiple records | | `/{module}/list` | POST | List records with pagination/filtering | | `/{module}/:id` | GET | Get a single record by ID | | `/{module}/:id` | PUT | Update a record | | `/{module}/:id` | DELETE | Soft-delete a record | | `/{module}/bulk` | DELETE | Bulk soft-delete records | | `/{module}/export` | POST | Export records to Excel | | `/{module}/import` | POST | Import records from Excel | ### Relationship Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/{module}/list_relate/:id/:field/:relatedModule` | POST | List related records | | `/{module}/list_relate/:id/:field/:relatedModule` | PUT | Add relationships | | `/{module}/list_relate/:id/:field/:relatedModule` | DELETE | Remove relationships | ## List Request Format All list endpoints accept a POST request with this body: ```json { "page": 1, "limit": 20, "search": "search term", "sort_field": "created_at", "sort_direction": "desc", "filter": { "group": "AND", "conditions": [ {"field": "status", "operator": "=", "value": "active"} ] }, "preloads": ["Class", "Program"] } ``` ### Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `page` | int | 1 | Page number | | `limit` | int | 20 | Records per page (max 100) | | `search` | string | "" | Full-text search across searchable fields | | `sort_field` | string | "created_at" | Field to sort by | | `sort_direction` | string | "desc" | Sort direction: `asc` or `desc` | | `filter` | object | null | Filter conditions (see Filter System) | | `preloads` | array | [] | Related data to include | ## Filter System The filter system supports complex queries with AND/OR grouping: ### Simple Filter ```json { "filter": { "group": "AND", "conditions": [ {"field": "status", "operator": "=", "value": "active"} ] } } ``` ### Nested Filter (AND + OR) ```json { "filter": { "group": "AND", "conditions": [ {"field": "status", "operator": "=", "value": "active"}, { "group": "OR", "conditions": [ {"field": "grade_level", "operator": "=", "value": "10"}, {"field": "grade_level", "operator": "=", "value": "11"} ] } ] } } ``` ### Filter Operators | Operator | Description | Example | |----------|-------------|---------| | `=` | Equals | `{"field": "status", "operator": "=", "value": "active"}` | | `!=` | Not equals | `{"field": "status", "operator": "!=", "value": "inactive"}` | | `>` | Greater than | `{"field": "age", "operator": ">", "value": 18}` | | `<` | Less than | `{"field": "age", "operator": "<", "value": 65}` | | `>=` | Greater than or equal | `{"field": "score", "operator": ">=", "value": 60}` | | `<=` | Less than or equal | `{"field": "score", "operator": "<=", "value": 100}` | | `contains` | Contains substring | `{"field": "name", "operator": "contains", "value": "john"}` | | `starts_with` | Starts with | `{"field": "code", "operator": "starts_with", "value": "STD"}` | | `ends_with` | Ends with | `{"field": "email", "operator": "ends_with", "value": "@school.edu"}` | | `is_null` | Is NULL | `{"field": "deleted_at", "operator": "is_null", "value": true}` | | `is_not_null` | Is not NULL | `{"field": "assigned_to", "operator": "is_not_null", "value": true}` | | `in` | In array | `{"field": "status", "operator": "in", "value": ["active", "pending"]}` | | `not_in` | Not in array | `{"field": "status", "operator": "not_in", "value": ["deleted"]}` | ## Pagination List responses include pagination metadata: ```json { "pagination": { "page": 1, "limit": 20, "total": 150, "total_pages": 8 } } ``` ## Field Definitions List responses include field definitions for dynamic form generation: ```json { "metadata": { "field_definitions": { "name": { "type": "text", "label": "Name", "required": true }, "status": { "type": "enum", "label": "Status", "options": ["active", "inactive"] }, "class_id": { "type": "relate", "label": "Class", "module": "Class" } } } } ``` ### Field Types | Type | Description | |------|-------------| | `text` | Single-line text input | | `textarea` | Multi-line text input | | `html` | Rich text editor | | `int` | Integer number | | `float` | Decimal number | | `bool` | Boolean checkbox | | `date` | Date picker | | `datetime` | Date and time picker | | `enum` | Single select dropdown | | `multienum` | Multi-select dropdown | | `relate` | Foreign key relation (single) | | `multirelate` | Many-to-many relation | | `image` | Image upload | | `file` | File upload | | `email` | Email input | | `phone` | Phone number input | | `address` | Address input with autocomplete | | `password` | Password input | ## Error Codes | HTTP Code | Description | |-----------|-------------| | 200 | Success | | 201 | Created | | 400 | Bad Request - Invalid input | | 401 | Unauthorized - Invalid or expired token | | 403 | Forbidden - Insufficient permissions | | 404 | Not Found - Resource doesn't exist | | 409 | Conflict - Duplicate entry | | 422 | Unprocessable Entity - Validation failed | | 429 | Too Many Requests - Rate limited | | 500 | Internal Server Error | ## Rate Limiting API requests are rate limited: - **Default**: 100 requests per minute per user - **Bulk operations**: 10 requests per minute When rate limited, you'll receive: ```json { "error": "Rate limit exceeded", "retry_after": 60 } ``` ## Soft Delete All records use soft delete. Deleted records: - Have `deleted_at` timestamp set - Are excluded from normal queries - Can be restored by admin - Are permanently purged after retention period ## Audit Trail All create, update, and delete operations are logged with: - User ID who performed the action - Timestamp - Before/after data snapshots - IP address and user agent ## Multi-tenancy Data is isolated by team (organization/campus): 1. `X-Team-ID` header identifies the current team 2. All queries automatically filter by team 3. New records inherit the team ID 4. Child teams can access parent team data ## Preloading Relations Request related data using the `preloads` parameter: ```json { "preloads": ["Class", "Class.GradeLevel", "Program"] } ``` This returns nested related objects: ```json { "id": "student-id", "name": "John Doe", "class": { "id": "class-id", "name": "Class 10A", "grade_level": { "id": "grade-id", "name": "Grade 10" } }, "program": { "id": "program-id", "name": "Academic Program" } } ```