# 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}/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** | Manual column names | **Reserved `q` property** in SearchQuery | --- ## 2. Authentication and Security (Mandatory) As of January 2026, the V3 architecture enforces strict **Multi-Tenant Isolation** and **Machine Authorization**. Most requests require two levels of validation. ### A. The "Entry Ticket" (API Key) **Mandatory for all requests.** Every request must provide a valid `x-aether-api-key` in the header. This identifies the application or script. * **Header:** `x-aether-api-key: ` * **Status Code:** `403 Forbidden` if missing, invalid, or expired. ### B. The "Visa" (Account Context) Once the API Key is validated, you must specify the context of your request. 1. **Standard User Access**: Provide the `x-account-id` (the random string ID). * **Header:** `x-account-id: ` 2. **Administrative Bypass**: For authorized scripts needing global access. * **Header:** `x-no-account-id: bypass` 3. **Guest / Anonymous Access**: Provide a **Safe Guest JWT**. * **Header:** `x-aether-api-key: ` (No Account Header) * **Query Param:** `?jwt=` * **Benefit:** Allows the backend to track cryptographically signed session state (e.g., site context) without granting full account access. ### C. Public Read Whitelist (Unauthenticated) The V3 architecture allows unauthenticated (**guest**) access to specific objects, provided a valid API Key is present. * **Whitelisted Objects:** `site_domain`, `event`, `event_session`, `event_presentation`, `event_presenter`, `post`, `post_comment`, `archive`, `archive_content`, `hosted_file`. * **Behavior:** Requests to these objects will succeed without a user-level JWT, but are strictly limited to **Read-Only** operations (GET/Search). ### D. Passcode Authentication (Machine/Kiosk Logins) For guest machines or specialized kiosks, use the dedicated passcode endpoint to receive a scoped JWT. * **Endpoint:** `POST /api/authenticate_passcode` * **Payload:** `{ "site_id": "", "passcode": "" }` * **Response:** Returns a JWT containing the site's `account_id` and resolved role flags (`super`, `manager`, `administrator`). ### E. Fail-Fast on Auth Failures (401/403) The frontend implements a **Fail-Fast** policy for 401/403 errors. If the API returns these codes, the frontend **must not retry** automatically. It should stop and redirect the user or display an error. --- ## 3. 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 complex logical bodies with simple query parameters. ```ts export async function search_ae_obj_v3({ api_cfg, obj_type, search_query, // { q: "search term", and: [...] } enabled = 'enabled', view = 'default' }) { const endpoint = `/v3/crud/${obj_type}/search`; const params = { enabled, view }; return await post_object({ api_cfg, endpoint, params, data: search_query }); } ``` ### C. Standardized Global Search (`q`) Use the `q` property in your search body for a keyword search. - **Wildcard**: `q: "%"` returns all records (respecting logical filters). - **Fallback**: Performs a `LIKE` search across all searchable fields if no index exists. ```json { "q": "Annual Meeting", "and": [{ "field": "enable", "op": "eq", "value": true }] } ``` --- ## 4. Create, Update, & Delete ### A. Create (POST) V3 validates incoming JSON against the `mdl_in` Pydantic model. ```ts // POST /v3/crud/{obj_type}/ 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 }); } ``` ### B. Update (PATCH) V3 uses `PATCH` for partial updates. Only provided fields are modified. ```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 }); } ``` ### C. Delete (DELETE) Supports soft-delete (`method=hide`) or hard-delete (`method=delete`). ```ts // DELETE /v3/crud/{obj_type}/{obj_id}?method=hide export async function delete_ae_obj_v3({ api_cfg, obj_type, obj_id, method = 'delete' }) { const endpoint = `/v3/crud/${obj_type}/${obj_id}`; return await delete_object({ api_cfg, endpoint, params: { method } }); } ``` --- ## 5. Specialized Endpoints ### A. Schema Discovery **Path**: `GET /v3/crud/{obj_type}/schema` Returns DB column definitions and Pydantic field rules for dynamic UI builders. ### B. Secure File Downloads (JWT in URL) For browsers downloading files, you can pass the JWT directly in the query string. - `GET /v3/crud/hosted_file/{id}/?jwt={token}` --- ## 6. The "ID Vision" Standard (2026) V3 uses a **String-Only ID Vision**. The frontend and external agents NEVER handle or store internal database integers. ### A. Automatic ID Mapping (Output) Internal `id_random` fields are renamed to clean, short names in the JSON response. - **`id`**: Unique random identifier for the record. - **`account_id`**: Unique random identifier for the parent account. ### B. Intelligent Mapping (Input/Search) You can send string IDs back to the API using the same clean names. - **Search**: Filter by `account_id` using the random string value. - **Save**: Send `account_id: "nqOzejLCDXM"` in a payload; the API resolves it to an integer. --- ## 7. Standard Patterns & Pitfalls ### A. Permissive Update Mode (Available) To simplify state management, V3 supports a **Permissive Update Mode** which ignores unknown extra fields in the payload. - **Header:** `x-ae-ignore-extra-fields: true` - **Use when:** Sending back objects that contain read-only technical metadata. ### B. Structured Error Handling (Rich Bubbling) V3 returns machine-readable error objects in `meta.details` for failures (400/500). **Example Error Response:** ```json { "meta": { "success": false, "status_code": 400, "details": { "category": "database_schema", "code": 1054, "message": "Unknown column 'notes' in 'SET'", "recoverable": false } } } ``` **Common Categories:** - **`database_duplicate`**: Non-unique value (Code 1062). - **`database_constraint`**: Foreign key violation (Codes 1451, 1452). - **`database_schema`**: Invalid column name (Codes 1054, 1146). - **`database_connection`**: Temporary DB issues (`recoverable: true`). - **`validation`**: Pydantic validation failed. ### C. Booleans: 'NULL' vs '0' **Pitfall:** Fields like `hide` can be `NULL` in the DB. **Standard:** Handle `null`, `undefined`, and `0` identically for boolean checks.