# Aether API V3 Frontend Integration Guide (Svelte/TypeScript) This guide explains how to update or create frontend functions to interact with the new **Aether API V3 CRUD** endpoints. V3 introduces a nested URL structure, a powerful POST-based search, and improved performance. --- ## 1. Key Differences (V2 vs V3) | Feature | CRUD V2 (Legacy) | CRUD V3 (Modern) | | --- | --- | --- | | **Base Prefix** | `/v2/crud` | `/v3/crud` | | **List Suffix** | Uses `/list` | **No suffix** (e.g., `/v3/crud/journal/`) | | **Nested Path** | Not supported in URL | **Supported** (e.g., `/v3/crud/journal/{id}/journal_entry/`) | | **View Selection**| `tbl_alt`, `mdl_alt` | **`view` parameter** (e.g., `?view=enriched`) | | **Complex Search**| Limited to GET `jp` | **POST `/search`** (Unlimited size + Hybrid params) | | **Full-Text Search**| Manual column names | **Reserved `q` property** in SearchQuery | --- ## 2. Implementing V3 CRUD Functions ### A. List & Single Object (GET) Support for view selection allows fetching richer data models when needed. ```ts // Example: Get enriched journal details // GET /v3/crud/journal/{id}?view=enriched export async function get_ae_obj_v3({ api_cfg, obj_type, obj_id, view = 'default' }) { const endpoint = `/v3/crud/${obj_type}/${obj_id}`; return await get_object({ api_cfg, endpoint, params: { view } }); } ``` ### B. Advanced & Hybrid Search (POST) The `/search` endpoint combines the power of complex logical bodies with the simplicity of query parameters. ```ts export async function search_ae_obj_v3({ api_cfg, obj_type, search_query, // { q: "search term", and: [...] } enabled = 'enabled', view = 'default', for_obj_type, for_obj_id }) { const endpoint = `/v3/crud/${obj_type}/search`; // Standard filters can be passed as query params const params: any = { enabled, view }; if (for_obj_type) params.for_obj_type = for_obj_type; if (for_obj_id) params.for_obj_id = for_obj_id; return await post_object({ api_cfg, endpoint, params, data: search_query }); } ``` ### C. Standardized Global Search Use the `q` property in your search body for a general keyword search across indexed columns. ```json // POST /v3/crud/journal/search { "q": "Annual Meeting", "and": [ { "field": "enable", "op": "eq", "value": true } ] } ``` ### D. Supported Search Operators The `op` property in a `SearchFilter` supports the following values: | Operator | SQL equivalent | Description | | --- | --- | --- | | `eq` | `=` | Equal to | | `ne` | `!=` | Not equal to | | `gt` | `>` | Greater than | | `gte` | `>=` | Greater than or equal to | | `lt` | `<` | Less than | | `lte` | `<=` | Less than or equal to | | `in` | `IN (...)` | Matches any value in a provided list | | `is_null` | `IS NULL` | Field is null (ignores `value`) | | `is_not_null` | `IS NOT NULL` | Field is not null (ignores `value`) | | `like` | `LIKE` | Standard SQL LIKE (requires manual `%` in `value`) | | `contains` | `LIKE %val%` | Wraps value in `%` automatically | | `startswith` | `LIKE val%` | Appends `%` to value automatically | | `endswith` | `LIKE %val` | Prepends `%` to value automatically | --- ## 3. Create, Update, & Delete (POST, PATCH, DELETE) V3 supports both top-level operations and nested parent/child operations. ### A. Create (POST) When creating objects, V3 strictly validates the incoming JSON against the `mdl_in` Pydantic model. ```ts // POST /v3/crud/{obj_type}/ // POST /v3/crud/journal/ export async function create_ae_obj_v3({ api_cfg, obj_type, data }) { const endpoint = `/v3/crud/${obj_type}/`; return await post_object({ api_cfg, endpoint, data }); } // POST /v3/crud/{parent_obj_type}/{parent_obj_id}/{child_obj_type}/ // POST /v3/crud/journal/EIAC-40-76-82/journal_entry/ // Note: Parent ID is automatically injected into the child record. export async function create_nested_obj_v3({ api_cfg, parent_type, parent_id, child_type, data }) { const endpoint = `/v3/crud/${parent_type}/${parent_id}/${child_type}/`; return await post_object({ api_cfg, endpoint, data }); } ``` ### B. Update (PATCH) V3 uses `PATCH` for partial updates. Only the fields provided in the body will be modified in the database. ```ts // PATCH /v3/crud/{obj_type}/{obj_id} export async function update_ae_obj_v3({ api_cfg, obj_type, obj_id, data }) { const endpoint = `/v3/crud/${obj_type}/${obj_id}`; return await patch_object({ api_cfg, endpoint, data }); } // PATCH /v3/crud/{parent_type}/{parent_id}/{child_type}/{child_id} // Verification: The backend ensures the child actually belongs to the parent before updating. export async function update_nested_obj_v3({ api_cfg, parent_type, parent_id, child_type, child_id, data }) { const endpoint = `/v3/crud/${parent_type}/${parent_id}/${child_type}/${child_id}`; return await patch_object({ api_cfg, endpoint, data }); } ``` ### C. Delete (DELETE) The `DELETE` method is used for removal. The backend may implement soft-delete (hide/disable) depending on the configuration. ```ts // DELETE /v3/crud/{obj_type}/{obj_id} export async function delete_ae_obj_v3({ api_cfg, obj_type, obj_id }) { const endpoint = `/v3/crud/${obj_type}/${obj_id}`; return await delete_object({ api_cfg, endpoint }); } ``` --- ## 4. Authentication in V3 V3 supports multiple authentication methods. The backend resolves these automatically. ### A. Standard Requests (Header) For most API calls, use the standard Bearer token in the `Authorization` header. ```ts // Example: Setting the JWT in headers headers: { "Authorization": `Bearer ${user_jwt_token}` } ``` ### B. Secure File Downloads (URL Parameter) **Crucial for `hosted_file` and `event_file`**: To allow browsers to download files without complex header modifications, you can pass the JWT directly in the URL. ```ts // Example: Creating a secure download link // GET /v3/crud/hosted_file/{id}/?jwt={token} const downloadUrl = `${BASE_URL}/hosted_file/${fileId}/?jwt=${jwtToken}`; ``` ### C. Legacy Fallback (X-Account-ID) For development and backward compatibility, the `X-Account-ID` header is still supported but should be phased out in favor of JWT. --- ## 5. Best Practices for V3 1. **Use `view` for Rich Data**: Instead of manually joining data in separate calls, use `?view=enriched` or `?view=detail` if defined in the backend. 2. **Hybrid Search**: Use query parameters for simple toggles (enabled/hidden) and the POST body for complex logic. 3. **Global Search**: Always prefer the `q` property for text search instead of manually targeting `default_qry_str`. 4. **Singular Nouns**: Always use singular names for `obj_type` (e.g., `journal`).