Migrate clip/convert to V3 actions; add background clip support, redirect legacy route; update frontend guide
This commit is contained in:
164
documentation/GUIDE__AE_API_V3_for_Frontend.md
Normal file
164
documentation/GUIDE__AE_API_V3_for_Frontend.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Aether API V3 Frontend Integration Guide (Svelte/TypeScript)
|
||||
|
||||
This guide defines the standards for interacting with the **Aether API V3 CRUD** and **Action** endpoints.
|
||||
|
||||
---
|
||||
|
||||
## 1. Authentication and Security (Mandatory)
|
||||
|
||||
V3 architecture enforces strict **Multi-Tenant Isolation** and **Machine Authorization**. Requests require two levels of validation.
|
||||
|
||||
### A. The "Entry Ticket" (API Key)
|
||||
**Mandatory for all requests.** identifies the application or client.
|
||||
* **Header:** `x-aether-api-key: <your_app_key>`
|
||||
* **Status Code:** `403 Forbidden` if missing or invalid.
|
||||
|
||||
### B. The "Visa" (Account Context)
|
||||
Required for any non-public data (Journals, Badges, Users, etc.).
|
||||
1. **Standard Access**: Provide the `x-account-id` (the random string ID).
|
||||
* **Header:** `x-account-id: <account_id>`
|
||||
2. **Administrative Bypass**: For authorized scripts needing global access.
|
||||
* **Header:** `x-no-account-id: bypass`
|
||||
3. **Token Access**: Provide a **JWT** in the query string.
|
||||
* **Query Param:** `?jwt=<token>`
|
||||
|
||||
> [!CAUTION]
|
||||
> **UNSUPPORTED HEADERS:** The header `x-aether-api-token` is **NOT recognized** by the V3 API. If you send it, the backend will treat you as a guest and block access to private data.
|
||||
|
||||
---
|
||||
|
||||
## 2. Bootstrapping (The FQDN Handshake)
|
||||
|
||||
When the frontend first loads and doesn't know the `account_id`, it performs a "handshake" using its domain name.
|
||||
|
||||
**Endpoint:** `POST /v3/crud/site_domain/search`
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"and": [
|
||||
{ "field": "fqdn", "op": "eq", "value": "demo.oneskyit.com" }
|
||||
]
|
||||
}
|
||||
```
|
||||
**Results:**
|
||||
* Returns 200 + a list containing the `account_id` (random string ID) and `site_id` (random string ID).
|
||||
* ** デザイン Choice:** If the domain is not found, it returns **200 OK with an empty list `[]`**. It is NOT a 404.
|
||||
|
||||
---
|
||||
|
||||
## 3. Standard CRUD Patterns
|
||||
|
||||
### A. GET by ID
|
||||
Used when the ID is known.
|
||||
* **Endpoint:** `GET /v3/crud/{obj_type}/{id}`
|
||||
* **Security:** Returns 403 if the record doesn't belong to your `x-account-id`.
|
||||
|
||||
### B. POST Search
|
||||
The primary way to retrieve data.
|
||||
* **Endpoint:** `POST /v3/crud/{obj_type}/search`
|
||||
* **Security:** Automatically filters results to only show records belonging to your `x-account-id`. If no account context is provided, it will return **0 records** for private objects.
|
||||
|
||||
### C. POST Create / PATCH Update
|
||||
Modify data in the system.
|
||||
* **Endpoints:**
|
||||
* `POST /v3/crud/{obj_type}/`
|
||||
* `PATCH /v3/crud/{obj_type}/{id}`
|
||||
* **Strict Mode (Default):** The API validates your payload against the Pydantic model. If you send fields that do not exist in the model, the database might return a 400 "Unknown column" error.
|
||||
* **Permissive Mode (Header):** To allow the frontend to send "extra" fields (like local UI state) without causing errors, use the following header:
|
||||
* **Header:** `x-ae-ignore-extra-fields: true`
|
||||
* **Behavior:** When set to `true`, the backend will automatically strip any fields from the payload that are not defined in the object's model before attempting to save to the database.
|
||||
|
||||
---
|
||||
|
||||
## 4. V3 Uniform Lookup System
|
||||
|
||||
The V3 Lookup system provides a hierarchical, deduplicated interface for standardized tables (Countries, Timezones, etc.). It supports global defaults, account overrides, and site-specific whitelisting.
|
||||
|
||||
### A. List Lookups
|
||||
Retrieve a ranked and filtered list of lookup items.
|
||||
* **Endpoint:** `GET /v3/lookup/{lu_type}/list`
|
||||
* **Available Types:** `country`, `country_subdivision`, `time_zone`
|
||||
* **Parameters:**
|
||||
* `site_id` (Optional): Random ID of the site to apply a **Whitelist Policy**.
|
||||
* `only_priority` (Optional): Set to `true` to return only high-priority items (e.g., common time zones).
|
||||
* `for_type` / `for_id` (Optional): Context for object-specific overrides.
|
||||
* `include_disabled` (Optional): Set to `true` to see shadowed/disabled records.
|
||||
|
||||
### B. Resolve Identity
|
||||
Resolves a string (code, group, or name) to a single record.
|
||||
* **Endpoint:** `GET /v3/lookup/{lu_type}/resolve?q=VALUE`
|
||||
* **Usage:** Use this when you have an external code (e.g., ISO "US") and need the full Aether record.
|
||||
|
||||
### C. Site Whitelist Policy
|
||||
To limit lookups for a specific site, add a `lookup_policy` to the `site.cfg_json` field.
|
||||
**Schema:**
|
||||
```json
|
||||
{
|
||||
"lookup_policy": {
|
||||
"country": ["US", "CA", "GB"],
|
||||
"time_zone": ["America/New_York"]
|
||||
}
|
||||
}
|
||||
```
|
||||
*Note: Whitelist values must match the `group` field in the database.*
|
||||
|
||||
---
|
||||
|
||||
## 5. Event File Data Retrieval (Hosted Files)
|
||||
|
||||
Every Event File (`event_file`) **must** have a linked Hosted File (`hosted_file`). The Hosted File itself is a metadata record for binary content (files), which is accessed via separate Action endpoints (e.g., `/v3/action/hosted_file/download`). This API endpoint provides metadata about the associated hosted file. To retrieve this additional metadata:
|
||||
|
||||
* **Endpoint:** `GET /v3/crud/event_file/{event_file_id}`
|
||||
* **Query Parameter:** Add `inc_hosted_file=true`
|
||||
* Example: `/v3/crud/event_file/<event_file_id>?inc_hosted_file=true`
|
||||
|
||||
**Response Impact:**
|
||||
|
||||
1. **Top-Level Convenience Fields:** The response will include top-level fields for commonly needed hosted file data. These are populated directly from the SQL view via JOINs.
|
||||
* `hosted_file_hash_sha256` (string)
|
||||
* `hosted_file_subdirectory_path` (string)
|
||||
* `hosted_file_content_type` (string)
|
||||
* `hosted_file_size` (string - in bytes)
|
||||
2. **Nested Hosted File Object:** A full `hosted_file` object will be nested under the `hosted_file` key. This object (`Hosted_File_Base` model) will contain all its standard fields, including `id` (random string ID), `hash_sha256`, `content_type`, `size`, etc.
|
||||
|
||||
---
|
||||
|
||||
## 6. Hosted File Actions: Convert & Clip (Frontend Notes)
|
||||
|
||||
These helper endpoints let the frontend request small server-side transformations without uploading new blobs. They return a newly-created `hosted_file` metadata object on success.
|
||||
|
||||
- **Convert (PDF → Image)**
|
||||
- Method: `GET`
|
||||
- Path: `/v3/action/hosted_file/{hosted_file_id}/convert_file`
|
||||
- Required query params: `link_to_type`, `link_to_id`
|
||||
- Optional query params: `filename_no_ext` (defaults to `automated_hosted_file_conversion`), `to_type` (defaults to `webp`)
|
||||
- Auth: standard V3 headers (`x-aether-api-key`, `x-account-id` / `x-no-account-id` / `?jwt=`)
|
||||
- Behavior: converts the first page of a PDF to `webp` or `png`, saves a new `hosted_file`, and returns its metadata. Returns 400 on failure.
|
||||
|
||||
- **Clip Video**
|
||||
- Method: `GET`
|
||||
- Path: `/v3/action/hosted_file/{hosted_file_id}/clip_video`
|
||||
- Required query params: `link_to_type`, `link_to_id`, `start_time`, `end_time` (format `HH:MM:SS`)
|
||||
- Optional query params: `filename_no_ext` (defaults to `automated_hosted_file_clip_video`), `reencode` (bool), `scale_down` (bool)
|
||||
- Auth: standard V3 headers
|
||||
- Behavior: extracts a clip using `ffmpeg` and saves it as a new `hosted_file`. Defaults to stream-copying to be fast; set `reencode=true` to force H.264 or `scale_down=true` to resize. Returns 400 on failure.
|
||||
- Behavior: extracts a clip using `ffmpeg` and saves it as a new `hosted_file`.
|
||||
- Defaults to stream-copying to be fast; set `reencode=true` to force H.264 or `scale_down=true` to resize.
|
||||
- For longer-running clips you can schedule the job in the background by adding `?background=true`. When scheduled the API returns `202 Accepted` and the clip runs asynchronously on the server; check the returned `hosted_file` record later via the standard V3 `hosted_file` endpoints.
|
||||
- Returns 400 on synchronous failure; returns 202 when scheduled successfully.
|
||||
|
||||
Frontend guidance:
|
||||
|
||||
- Call these routes with the same `link_to_type` / `link_to_id` you plan to associate the resulting hosted_file with — the server resolves random IDs for you.
|
||||
- After a successful response, use the V3 `hosted_file` action endpoints (download/delete) to manage or retrieve the new file.
|
||||
- These endpoints run synchronously and can take time for large inputs; for heavy or batch workloads use a queued job pattern instead.
|
||||
- These endpoints may take time for large inputs. Prefer using `?background=true` to schedule work and receive a `202 Accepted` response for async processing. For heavy or batch workloads use a queued job pattern instead.
|
||||
|
||||
|
||||
## 5. Troubleshooting 403 Forbidden
|
||||
|
||||
If you receive a 403 on a valid ID:
|
||||
1. Verify `x-aether-api-key` is correct.
|
||||
2. Ensure you are sending `x-account-id` and NOT `x-aether-api-token`.
|
||||
3. Verify the record actually belongs to the account ID you are sending.
|
||||
4. Check if the object is marked `public_read: True` in the registry. (Posts and Archive Content allow guest access; Journals and Badges do not).
|
||||
Reference in New Issue
Block a user