Dynamic Query
Overview
Section titled “Overview”The /api/v1/dynamic/query namespace provides a set of endpoints for building flexible SQL-like queries from JSON. The engine maps request payloads to SQLAlchemy queries and supports, among other things:
SELECTWHEREJOINGROUP BYORDER BY- subqueries in filters
Available endpoints:
GET /api/v1/dynamic/query/tablesGET /api/v1/dynamic/query/attributesPOST /api/v1/dynamic/queryPOST /api/v1/dynamic/query/bulkPOST /api/v1/dynamic/query/default-configuration
Model naming and registry keys
Section titled “Model naming and registry keys”For query_model and target_model, the engine registers both:
- the lowercased class name
- the lowercased table name
This means both forms are often valid.
Examples:
tenantortenantsuserorusersfileorfilesfileagentorfile_agentsallowedextensionsorallowed_extensionsagentphonenumberoragent_phone_numbers
Use /api/v1/dynamic/query/tables as the source of truth for the exact keys available in your environment.
Basic request structure
Section titled “Basic request structure”A dynamic query request typically contains:
query_modelquery_attributes- optional
query_filter - optional
joins - optional
group_by - optional
order_by - optional
page
curl https://api.livoi.de/api/v1/dynamic/query \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_TOKEN' \ --data '{ "query_model": "user", "query_attributes": ["id", "email"], "page": { "page": 1, "size": 10 }}'Schema & metadata
Section titled “Schema & metadata”List available queryable tables
Section titled “List available queryable tables”curl 'https://api.livoi.de/api/v1/dynamic/query/tables?include_attributes=true' \ --header 'Authorization: Bearer YOUR_SECRET_TOKEN'Example response:
{ "tables": { "user": ["id","email","created_at"], "users": ["id","email","created_at"], "fileagent": ["id","file_id","agent_id"], "file_agents": ["id","file_id","agent_id"] }}Get attributes for a specific model
Section titled “Get attributes for a specific model”curl 'https://api.livoi.de/api/v1/dynamic/query/attributes?query_model=file' \ --header 'Authorization: Bearer YOUR_SECRET_TOKEN'Example response:
{ "attributes": [ "content_type", "created_at", "file_name", "id", "size", "tags", "title", "updated_at", "uri" ]}SQL operations
Section titled “SQL operations”SELECT
Section titled “SELECT”{ "query_model": "user", "joins": [ { "target_model": "tenant", "on": "tenant_id=id" } ], "query_attributes": [ "id", "email", "tenant.domain" ]}{ "query_model": "agent", "query_attributes": [ ["name","agent_name"], ["tenant.domain","tenant_domain"] ], "joins": [ { "target_model": "tenant", "on": "tenant_id=id" } ]}{ "query_model": "history", "query_attributes": [ "model_name", ["COUNT(id)","message_count"], ["SUM(usage_output_tokens)","total_tokens"] ], "group_by": ["model_name"]}WHERE filtering
Section titled “WHERE filtering”Format:
field__operatorSupported operators:
| Suffix | SQL |
|---|---|
__eq | = |
__ne | != |
__lt | < |
__lte | <= |
__gt | > |
__gte | >= |
__like | LIKE |
__ilike | ILIKE |
__in | IN |
__not_in | NOT IN |
__isnull | IS NULL |
Example:
{ "query_model": "user", "query_filter": { "permission_level__in": ["ADMIN","OWNER"], "last_login__gte": "2024-01-01T00:00:00Z" }}Subqueries
Section titled “Subqueries”Example:
{ "id__in": { "subquery": { "query_model": "fileagent", "query_attributes": ["file_id"] } }}- target_model
Example:
tenantfileagentcalendaragent - ON clause
Format:
left_field=right_fieldExample:
id=file_id - Join type"isouter": true
produces a LEFT OUTER JOIN.
Example:
{ "query_model": "file", "joins": [ { "target_model": "fileagent", "on": "id=file_id", "isouter": true } ], "query_attributes": [ "id", "file_name", ["ARRAY_AGG(fileagent.agent_id)","agent_ids"] ], "group_by": ["id","file_name"]}ORDER BY
Section titled “ORDER BY”{ "query_model": "user", "order_by": [ "permission_level", "-last_login" ]}field→ ascending-field→ descending
GROUP BY
Section titled “GROUP BY”{ "query_model": "chat", "query_attributes": [ "user_id", ["COUNT(id)","chat_count"] ], "group_by": ["user_id"]}Bulk queries
Section titled “Bulk queries”curl https://api.livoi.de/api/v1/dynamic/query/bulk \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_SECRET_TOKEN'Example body:
{ "queries": [ { "query_model": "user", "query_attributes": ["id","email"] }, { "query_model": "history", "query_attributes": [ "model_name", ["COUNT(id)","message_count"] ], "group_by": ["model_name"] } ]}Default configuration
Section titled “Default configuration”POST /api/v1/dynamic/query/default-configurationFilters:
referencefunction
Error handling
Section titled “Error handling”{ "status_code": "403", "status_message": "Forbidden"}{ "status_code": "404", "status_message": "Not Found"}{ "status_code": "422", "status_message": "Unprocessable Content"}{ "status_code": "500", "status_message": "Internal Server Error"}