# Luzmo Core API Documentation > Complete reference for the Luzmo Core API. Use this to interact with Luzmo resources programmatically: manage dashboards, datasets, users, permissions, and query data. ## API Basics ### Authentication All API calls require an API key and token pair. Obtain these from your Luzmo account at https://app.luzmo.com/start/profile/integration **Security**: Never expose API credentials in client-side code. Use server-side SDKs or generate short-lived embed tokens for frontend access. ### Endpoints | Region | Base URL | |--------|----------| | EU (Default) | `https://api.luzmo.com/0.1.0` | | US | `https://api.us.luzmo.com/0.1.0` | | VPC | `https://api.{your-vpc}.luzmo.com/0.1.0` | ### Rate Limits - Maximum 10 calls per second per authorization token - Burstable up to 200 calls - Returns `429 Too Many Requests` when exceeded ### Action-Based API Design **IMPORTANT**: The Luzmo API uses an action-based design, NOT traditional REST HTTP verbs. - All operations use **POST** requests (never GET, PUT, or DELETE HTTP methods) - The operation type is specified via an `action` field in the request body - This unified approach provides consistent behavior and simplifies integration **Do NOT use:** - GET requests to fetch data - PUT/PATCH requests to update - DELETE requests to remove resources **Instead, always use POST with the appropriate action.** ### Request Format All requests use POST with JSON body: ```json { "action": "", "key": "", "token": "", "version": "0.1.0", ...action-specific properties } ``` ### OpenAPI Schema Reference The OpenAPI schema (`/assets/oas/oas-luzmo-full.json`) documents endpoints using the pattern `/{resource}?{action}` (e.g., `/dashboard?create`, `/user?get`). This reflects the action-based design where: - The URL path identifies the resource type - The query parameter indicates the action - The request body contains credentials and operation-specific data When using Luzmo SDKs, you don't need to construct URLs manually - the SDK methods handle this automatically. ## SDK Installation & Setup | Language | Package | GitHub | |----------|---------|--------| | Node.js | [npm](https://www.npmjs.com/package/@luzmo/nodejs-sdk) | [GitHub](https://github.com/luzmo-official/luzmo-sdk-nodejs) | | Python | [PyPI](https://pypi.org/project/luzmo-sdk/) | [GitHub](https://github.com/luzmo-official/luzmo-sdk-python) | | PHP | [Packagist](https://packagist.org/packages/luzmo/luzmo-sdk-php) | [GitHub](https://github.com/luzmo-official/luzmo-sdk-php) | | Java | [Maven](https://search.maven.org/artifact/com.luzmo/sdk) | [GitHub](https://github.com/luzmo-official/luzmo-sdk-java) | | C# | [NuGet](https://www.nuget.org/packages/LuzmoSDK) | [GitHub](https://github.com/luzmo-official/luzmo-sdk-csharp) | ### Node.js ```bash npm install @luzmo/nodejs-sdk ``` ```javascript const Luzmo = require('@luzmo/nodejs-sdk'); const client = new Luzmo({ api_key: '', api_token: '', host: 'https://api.luzmo.com' // or api.us.luzmo.com }); ``` ### Python ```bash pip install luzmo-sdk ``` ```python from luzmo.luzmo import Luzmo client = Luzmo( "", "", "https://api.luzmo.com" ) ``` ### PHP ```bash composer require luzmo/luzmo-sdk-php ``` ```php ', '', 'https://api.luzmo.com' ); ?> ``` ### Java Maven dependency: `com.luzmo:sdk` ```java Luzmo client = new Luzmo( "", "", "https://api.luzmo.com" ); ``` ### C# ```bash dotnet add package LuzmoSDK ``` ```csharp Luzmo client = new Luzmo( "https://api.luzmo.com", "", "" ); ``` ### cURL ```bash curl https://api.luzmo.com/0.1.0/ \ -H "Content-Type: application/json" \ -d '{ "action": "", "key": "", "token": "", "version": "0.1.0", ... }' ``` ## API Actions The Luzmo API provides a consistent set of actions across all resources. These use POST requests with an `action` field - this design enables powerful features like associations and complex queries in a single request. ### Create Create a new resource instance. The `create` action allows you to set initial properties and optionally establish relationships with other resources in a single call. **Request body fields:** - `action`: "create" - `key`, `token`, `version`: Authentication - `properties`: Object with resource-specific fields - `associations` (optional): Array of relationships to create ```javascript // Node.js SDK - Create a dashboard (use 'securable' with type: 'dashboard') const dashboard = await client.create('securable', { type: 'dashboard', name: { en: 'My Dashboard' } }); // With associations - link to dataset in the same call const dashboard = await client.create('securable', { type: 'dashboard', name: { en: 'My Dashboard' } }, [{ role: 'Securables', id: '' }] ); ``` ```python # Python SDK dashboard = client.create('securable', { 'type': 'dashboard', 'name': { 'en': 'My Dashboard' } }) ``` ```php // PHP SDK $dashboard = $client->create('securable', [ 'type' => 'dashboard', 'name' => ['en' => 'My Dashboard'] ]); ``` **Raw cURL example:** ```bash curl -X POST https://api.luzmo.com/0.1.0/securable \ -H "Content-Type: application/json" \ -d '{ "action": "create", "key": "", "token": "", "version": "0.1.0", "properties": { "type": "dashboard", "name": { "en": "My Dashboard" } } }' ``` ### Get / Search Retrieve resources with optional filters, includes, and ordering. Both single-resource lookup and multi-resource queries use the same `get` action. **Request body fields:** - `action`: "get" - `key`, `token`, `version`: Authentication - `find`: Object containing query parameters (where, include, attributes, order, limit) **IMPORTANT**: For raw HTTP requests, query parameters must be wrapped in a `find` object. SDKs handle this automatically. **IMPORTANT**: When using `include` to fetch related models, the response returns them as **lowercase** property names. For example, `include: [{ model: 'Column' }]` returns the data in a `columns` property (not `Columns`). Similarly, `model: 'Securable'` → `securables`, `model: 'User'` → `users`, etc. **IMPORTANT**: Dashboards and datasets are both "securables". All operations (create, get, update, delete) must use the `securable` resource with `type: 'dashboard'` or `type: 'dataset'`. There is no `/dashboard` endpoint - using `client.get('dashboard', ...)` or similar will fail. ```javascript // Node.js SDK - Get user by ID const user = await client.get('user', { where: { id: '' } }); // Node.js SDK - List dashboards (must use 'securable' with type filter) const dashboards = await client.get('securable', { where: { type: 'dashboard' }, attributes: ['id', 'name', 'created_at'], order: [['updated_at', 'desc']], limit: 10, offset: 0 }); // Node.js SDK - Get specific dashboard by ID with includes const dashboard = await client.get('securable', { where: { id: '', type: 'dashboard' }, include: [{ model: 'Securable' }], attributes: ['id', 'name', 'created_at'] }); ``` ```python # Python SDK - List dashboards dashboards = client.get('securable', { 'where': { 'type': 'dashboard' } }) ``` **Raw cURL example:** ```bash curl -X POST https://api.luzmo.com/0.1.0/securable \ -H "Content-Type: application/json" \ -d '{ "action": "get", "key": "", "token": "", "version": "0.1.0", "find": { "where": { "type": "dashboard" }, "include": [{ "model": "Securable" }], "attributes": ["id", "name", "created_at"] } }' ``` Query operators for `where`: - Exact match: `{ column: 'value' }` - Array: `{ column: ['value1', 'value2'] }` - Greater than: `{ column: { '>': 100 } }` - Less than: `{ column: { '<': 100 } }` - Like: `{ column: { 'like': '%pattern%' } }` ### Pagination & Limits Control result set size with `limit` and `offset`: ```javascript const dashboards = await client.get('securable', { where: { type: 'dashboard' }, order: [['updated_at', 'desc']], // Always specify order when using limit limit: 25, offset: 0 // Skip this many records (for pagination) }); // Page 2: skip first 25 results const page2 = await client.get('securable', { where: { type: 'dashboard' }, order: [['updated_at', 'desc']], limit: 25, offset: 25 }); ``` **Default behavior**: If no `limit` is specified, all matching resources are returned. When using `limit`, always specify `order` to ensure consistent pagination results. **Note**: The Data Query API uses a different format: `limit: { by: 10, offset: 0 }` instead of separate `limit` and `offset` properties. ### Text Search on Localized Names Use `search` with `match_types` and `keyphrase` to search resources by their localized name fields. This is useful for finding dashboards, datasets, and other resources by name when you don't know the exact value. ```javascript // Search datasets by name const datasets = await client.get('securable', { search: { match_types: ['name'], keyphrase: 'Sales Data' } }); // Search dashboards by name const dashboards = await client.get('securable', { search: { match_types: ['name'], keyphrase: 'Monthly Report' } }); // Combine search with other query options const results = await client.get('securable', { search: { match_types: ['name'], keyphrase: 'Revenue' }, attributes: ['id', 'name', 'description'], order: [['updated_at', 'desc']], limit: 10 }); ``` **Note**: The `search` parameter performs text matching on localized name fields, which is different from the `where` clause that does exact matching on specific locale keys (e.g., `where: { name: { en: 'Exact Name' } }`). ### Advanced Include Options The `include` parameter supports advanced features beyond basic related model fetching, including permission checking, aliased includes, nested includes, and aggregations. #### Permission Checking with Aggregations Check user permissions on resources using `aggregations` within `include`. Permission flags are: `flagRead`, `flagUse`, `flagModify`, `flagOwn`. ```javascript // Check what permissions a specific user has on dashboards const dashboards = await client.get('securable', { where: { type: 'dashboard' }, attributes: ['id', 'name', 'updated_at'], include: [{ model: 'User', attributes: ['id'], aggregations: [ { field: 'user_has_flag_read', type: 'bool_or', attribute: 'flagRead', where: { id: '' } }, { field: 'user_has_flag_use', type: 'bool_or', attribute: 'flagUse', where: { id: '' } }, { field: 'user_has_flag_modify', type: 'bool_or', attribute: 'flagModify', where: { id: '' } }, { field: 'user_has_flag_own', type: 'bool_or', attribute: 'flagOwn', where: { id: '' } } ] }] }); // Returns dashboards with user_has_flag_read, user_has_flag_use, etc. boolean fields ``` #### Aliased Includes Use `as` to include the same model multiple times with different filters or purposes: ```javascript const dashboards = await client.get('securable', { where: { type: 'dashboard' }, include: [ // Include User for permission aggregations { model: 'User', attributes: ['id'], aggregations: [...] }, // Include User again as "Owner" to get owner details { model: 'User', as: 'Owner', attributes: ['id', 'name', 'email'] } ] }); // Response contains both 'users' array and 'owner' object ``` #### Nested Includes Include models within included models for deep data fetching: ```javascript include: [{ model: 'User', as: 'Owner', attributes: ['id', 'name'], include: [{ model: 'Thumbnail', attributes: ['id', 'url', 'size'], where: { size: '64px' } }] }] // Returns owner with nested thumbnail data ``` #### Count Aggregations Get counts of related records using aggregations: ```javascript include: [{ model: 'View', aggregations: [{ type: 'count', field: 'dashboardViews' }] }] // Returns dashboardViews count for each dashboard ``` #### Query Options Use `options` to filter by ownership: ```javascript const myDashboards = await client.get('securable', { where: { type: 'dashboard' }, options: { owned: true // Only dashboards I own }, limit: 25 }); ``` #### Complete Example ```javascript // Get dashboards with full permission info and owner details const dashboards = await client.get('securable', { where: { type: 'dashboard', is_variant: false }, attributes: ['id', 'name', 'type', 'updated_at', 'created_at'], include: [ { model: 'User', attributes: ['id'], aggregations: [ { field: 'user_has_flag_read', type: 'bool_or', attribute: 'flagRead', where: { id: '' } }, { field: 'user_has_flag_use', type: 'bool_or', attribute: 'flagUse', where: { id: '' } }, { field: 'user_has_flag_modify', type: 'bool_or', attribute: 'flagModify', where: { id: '' } }, { field: 'user_has_flag_own', type: 'bool_or', attribute: 'flagOwn', where: { id: '' } } ] }, { model: 'User', as: 'Owner', attributes: ['id', 'name'], include: [{ model: 'Thumbnail', attributes: ['url'], where: { size: '64px' } }] }, { model: 'View', aggregations: [{ type: 'count', field: 'dashboardViews' }] }, { model: 'Thumbnail', attributes: ['id'], where: { size: '256px' } } ], options: { owned: true }, order: [['updated_at', 'desc']], limit: 25 }); ``` ### Update Modify an existing resource. The `update` action takes the resource ID and the properties to change. Only specified properties are updated - others remain unchanged. **Request body fields:** - `action`: "update" - `key`, `token`, `version`: Authentication - `id`: UUID of the resource to update - `properties`: Object with fields to update (partial update supported) ```javascript // Node.js SDK - Update a dashboard (use 'securable') await client.update('securable', '', { name: { en: 'Updated Name' } }); ``` ```python # Python SDK client.update('securable', '', { 'name': { 'en': 'Updated Name' } }) ``` **Raw cURL example:** ```bash curl -X POST https://api.luzmo.com/0.1.0/securable \ -H "Content-Type: application/json" \ -d '{ "action": "update", "key": "", "token": "", "version": "0.1.0", "id": "", "properties": { "name": { "en": "Updated Name" } } }' ``` ### Delete Remove a resource. Uses POST with action "delete" (not HTTP DELETE method). ```javascript // Node.js SDK - Delete a dashboard (use 'securable') await client.delete('securable', ''); ``` **Raw cURL example:** ```bash curl -X POST https://api.luzmo.com/0.1.0/securable \ -H "Content-Type: application/json" \ -d '{ "action": "delete", "key": "", "token": "", "version": "0.1.0", "id": "" }' ``` ### Associate Link two resources together. Luzmo uses associations to model relationships between resources (e.g., dashboard-to-dataset, user-to-group). The `associate` action creates these links. **Request body fields:** - `action`: "associate" - `key`, `token`, `version`: Authentication - `id`: UUID of the primary resource - `resource`: Object with `role` (relationship type) and `id` (target resource UUID) Common association roles: - `Securables`: Link datasets to dashboards or columns - `Groups`: Link users to groups - `Collections`: Link dashboards to collections - `Users`: Link users to organizations ```javascript // Node.js SDK - Link a dataset to a dashboard (use 'securable') await client.associate('securable', '', { role: 'Securables', id: '' }); // Link a user to a group await client.associate('user', '', { role: 'Groups', id: '' }); ``` ```python # Python SDK client.associate('securable', '', { 'role': 'Securables', 'id': '' }) ``` **Raw cURL example:** ```bash curl -X POST https://api.luzmo.com/0.1.0/securable \ -H "Content-Type: application/json" \ -d '{ "action": "associate", "key": "", "token": "", "version": "0.1.0", "id": "", "resource": { "role": "Securables", "id": "" } }' ``` ### Dissociate Remove the link between two resources. This is the inverse of `associate` - it removes the relationship without deleting either resource. **Request body fields:** - `action`: "dissociate" - `key`, `token`, `version`: Authentication - `id`: UUID of the primary resource - `resource`: Object with `role` (relationship type) and `id` (target resource UUID) ```javascript // Node.js SDK - Unlink a dataset from a dashboard (use 'securable') await client.dissociate('securable', '', { role: 'Securables', id: '' }); ``` ```python # Python SDK client.dissociate('securable', '', { 'role': 'Securables', 'id': '' }) ``` **Raw cURL example:** ```bash curl -X POST https://api.luzmo.com/0.1.0/securable \ -H "Content-Type: application/json" \ -d '{ "action": "dissociate", "key": "", "token": "", "version": "0.1.0", "id": "", "resource": { "role": "Securables", "id": "" } }' ``` ## API Entities (Resources) ### Authorization Generate embed tokens for secure frontend access. ```javascript const token = await client.create('authorization', { type: 'embed', expiry: '24 hours', username: '', name: 'User Name', email: 'user@example.com', access: { dashboards: [ { id: '', rights: 'use' } ], datasets: [ { id: '', rights: 'use' } ] }, metadata: { // Optional: parameter overrides for multi-tenant filtering } }); // Returns: { id, token } - use these as authKey/authToken in frontend ``` Token types: - `embed`: Short-lived tokens for frontend embedding - `login`: User login tokens - `api`: Long-lived API tokens Access rights: `use`, `view`, `modify`, `own` Docs: https://developer.luzmo.com/api/createAuthorization ### Dashboard Analytics dashboards containing visualizations. > **Dashboard Versioning**: Dashboard `contents` (layout, items, and their configurations) are versioned. The structure of dashboard contents changes between versions. Luzmo automatically upgrades dashboards to newer versions when accessed. When programmatically creating or modifying dashboard contents, ensure you use the correct structure for your target schema version (current: **v0.1.97**). Reference the JSON schemas at `https://developer.luzmo.com/assets/json-schemas-dereferenced/0.1.97/` for the exact structure. > **IMPORTANT - Dashboards use the `securable` resource**: All dashboard operations (create, get, update, delete) must use the `securable` resource with `type: "dashboard"`. There is no separate `/dashboard` endpoint. Using `client.get('dashboard', ...)` or similar will fail with "route does not exist". ```javascript // Create dashboard - uses 'securable' with type: 'dashboard' const dashboard = await client.create('securable', { type: 'dashboard', name: { en: 'Sales Dashboard' }, description: { en: 'Monthly sales overview' }, css: '' // Optional custom CSS }); // List/search dashboards - uses 'securable' with type: 'dashboard' const dashboards = await client.get('securable', { where: { type: 'dashboard' }, attributes: ['id', 'name', 'description', 'created_at', 'updated_at'], order: [['created_at', 'desc']], limit: 10, offset: 0 }); // Get a specific dashboard by ID - uses 'securable' with type: 'dashboard' const dashboard = await client.get('securable', { where: { id: '', type: 'dashboard' }, include: [ { model: 'Securable' }, { model: 'User', attributes: ['id', 'name', 'email'] } ] }); // Note: Included models are returned as lowercase properties: dashboard.securables, dashboard.users // Update dashboard - uses 'securable' await client.update('securable', '', { name: { en: 'Updated Name' } }); // Delete dashboard - uses 'securable' await client.delete('securable', ''); // WRONG: These will NOT work - there is no 'dashboard' resource // await client.create('dashboard', { ... }); // ERROR! // await client.get('dashboard', { ... }); // ERROR! // await client.update('dashboard', ...); // ERROR! // await client.delete('dashboard', ...); // ERROR! ``` Key properties: - `name`: Object with locale keys `{ en: 'Name', nl: 'Naam' }` - `description`: Localized description - `contents`: Dashboard layout and items (JSON) - `css`: Custom CSS overrides #### Handling Localized Fields Localized fields (`name`, `description`) may be objects, strings, or null. Always safely extract: ```javascript const getName = (field) => field?.en || (typeof field === 'string' ? field : '') || ''; ``` Docs: https://developer.luzmo.com/api/createDashboard ### Dataset (Securable) Data sources for visualizations. ```javascript // Create dataset const dataset = await client.create('securable', { name: { en: 'Sales Data' }, description: { en: 'Product sales records' }, type: 'dataset' }); // Push data to dataset await client.create('data', { securable_id: '', type: 'append', // or 'replace' data: [ ['Product A', 100, '2024-01-01'], ['Product B', 200, '2024-01-02'] ] }); ``` Dataset types: - `dataset`: Regular dataset - `view`: SQL view over other datasets Data operations: - `append`: Add rows to existing data - `replace`: Replace all data - `delete`: Remove matching rows ```javascript // Get dataset with its columns (include related model with attributes) // IMPORTANT: You must include type: 'dataset' in the where clause for includes to work const dataset = await client.get('securable', { where: { id: '', type: 'dataset' // Required when using include }, include: [{ model: 'Column', attributes: ['id', 'name', 'type', 'format', 'order'] }], attributes: ['id', 'name', 'description', 'type'] }); // IMPORTANT: Included models are returned as LOWERCASE property names in the response. // Even though you specify model: 'Column' (uppercase), the response contains 'columns' (lowercase). // Examples: include model: 'Column' → response.columns, model: 'Securable' → response.securables // Returns dataset with nested columns array containing specified attributes ``` Docs: https://developer.luzmo.com/api/createSecurable ### Column Dataset column definitions. ```javascript const column = await client.create('column', { name: { en: 'Revenue' }, type: 'numeric', format: '$,.2f' }, [ { role: 'Securables', id: '' } ]); ``` Column types: - `numeric`: Numbers with optional format (D3 format) - `hierarchy`: Categorical/text data - `datetime`: Date/time values with levels Datetime levels: 1=year, 2=quarter, 3=month, 4=week, 5=day, 6=hour, 7=minute, 8=second, 9=millisecond Docs: https://developer.luzmo.com/api/createColumn ### User User account management. ```javascript const user = await client.create('user', { name: 'John Doe', email: 'john@example.com', password: 'securepassword' }); ``` Docs: https://developer.luzmo.com/api/createUser ### Group User groups for access control. ```javascript const group = await client.create('group', { name: { en: 'Analysts' } }); // Add user to group await client.associate('user', '', { role: 'Groups', id: '' }); ``` Docs: https://developer.luzmo.com/api/createGroup ### Formula Calculated metrics using aggregation expressions. ```javascript const formula = await client.create('formula', { name: { en: 'Profit Margin' }, expression: '(SUM(:) - SUM(:)) / SUM(:)' }); ``` Supported aggregations: `SUM`, `AVG`, `COUNT`, `DISTINCTCOUNT`, `MIN`, `MAX`, `MEDIAN`, `STDDEV`, `RATE`, `WEIGHTEDAVERAGE`, `CUMULATIVESUM` Docs: https://developer.luzmo.com/api/createFormula ### Theme Visual styling for dashboards. ```javascript const theme = await client.create('theme', { name: 'Corporate Theme', colors: ['#1a73e8', '#34a853', '#fbbc04', '#ea4335'], font: { family: 'Inter' } }); ``` Docs: https://developer.luzmo.com/api/createTheme ### Collection Dashboard organization and grouping. ```javascript const collection = await client.create('collection', { name: { en: 'Finance Reports' } }); // Add dashboard to collection (use 'securable') await client.associate('securable', '', { role: 'Collections', id: '' }); ``` Docs: https://developer.luzmo.com/api/createCollection ## Data Query API Query aggregated data from datasets. ```javascript const result = await client.query({ queries: [{ dimensions: [ { column_id: '', dataset_id: '' } ], measures: [ { column_id: '', dataset_id: '', aggregation: { type: 'sum' } } ], where: [ // AND: all top-level items must match { expression: '? >= ?', parameters: [ { column_id: '', dataset_id: '' }, '2024-01-01T00:00:00.000Z' ] }, { // OR: at least one must match or: [ { expression: '? = ?', parameters: [ { column_id: '', dataset_id: '' }, 'North' ] }, { expression: '? = ?', parameters: [ { column_id: '', dataset_id: '' }, 'South' ] } ] }, { expression: '? > ?', parameters: [ { column_id: '', dataset_id: '' }, 100 ] } ], // SQL equivalent: WHERE date >= '2024-01-01' AND (region = 'North' OR region = 'South') AND amount > 100 order: [ { column_id: '', dataset_id: '', aggregation: { type: 'sum' }, order: 'desc' } ], limit: { by: 10, offset: 0 }, options: { rollup_data: true, timezone_id: 'America/New_York' } }] }); // Returns: { data: [['Category A', 1000], ['Category B', 800], ...] } ``` ### Filter Expressions | Expression | Description | Example | |------------|-------------|---------| | `? = ?` | Equals | `{ expression: '? = ?', parameters: [column, 'value'] }` | | `? != ?` | Not equals | `{ expression: '? != ?', parameters: [column, 'value'] }` | | `? in ?` | In array | `{ expression: '? in ?', parameters: [column, ['a', 'b']] }` | | `? not in ?` | Not in array | `{ expression: '? not in ?', parameters: [column, ['a', 'b']] }` | | `? > ?` | Greater than | `{ expression: '? > ?', parameters: [column, 100] }` | | `? >= ?` | Greater or equal | `{ expression: '? >= ?', parameters: [column, 100] }` | | `? < ?` | Less than | `{ expression: '? < ?', parameters: [column, 100] }` | | `? <= ?` | Less or equal | `{ expression: '? <= ?', parameters: [column, 100] }` | | `? like ?` | Contains | `{ expression: '? like ?', parameters: [column, 'pattern'] }` | | `? is null` | Is null | `{ expression: '? is null', parameters: [column] }` | | `? is not null` | Is not null | `{ expression: '? is not null', parameters: [column] }` | | `? between ?` | Between | `{ expression: '? between ?', parameters: [column, [min, max]] }` | | `last_now` | Last N periods | `{ expression: 'last_now', parameters: [column, { unit: 5, quantity: 6 }] }` | Column reference format: `{ column_id: '', dataset_id: '' }` Datetime filter units: 1=year, 2=quarter, 3=month, 4=week, 5=day, 6=hour, 7=minute, 8=second ### Filter Groups (AND/OR) ```javascript where: [ { or: [ { expression: '? = ?', parameters: [column1, 'A'] }, { expression: '? = ?', parameters: [column1, 'B'] } ] }, { expression: '? > ?', parameters: [column2, 100] } ] // SQL: WHERE (column1 = 'A' OR column1 = 'B') AND column2 > 100 ``` Docs: https://developer.luzmo.com/guide/guides--querying-data ## Complete Entity List > **Note on Dashboards and Datasets**: Both dashboards and datasets are "securables". **All operations** (create, get, update, delete, associate) must use the `securable` resource with `type: 'dashboard'` or `type: 'dataset'`. There is no separate `/dashboard` endpoint - using it will fail with "route does not exist". | Entity | Create | Search | Update | Delete | Description | |--------|--------|--------|--------|--------|-------------| | Acceleration | Yes | Yes | Yes | Yes | Scheduled data sync configuration | | Account | No | Yes | Yes | No | Account settings | | Alert | Yes | Yes | Yes | Yes | Data alerts and notifications | | Authorization | Yes | Yes | No | Yes | Embed and API tokens | | Channel | Yes | Yes | Yes | Yes | Communication channels | | Collection | Yes | Yes | Yes | Yes | Dashboard groupings | | Column | Yes | Yes | Yes | Yes | Dataset columns | | Country | No | Yes | No | No | Country reference data | | Dashboard | **Via Securable** | **Via Securable** | **Via Securable** | **Via Securable** | Analytics dashboards (all operations use `securable` with `type: 'dashboard'`) | | Dashboard Version | No | Yes | No | Yes | Dashboard version history | | Data | Yes | Yes | No | Yes | Data operations and queries | | Dataexport | Yes | Yes | Yes | Yes | Export configurations | | Dataprovider | No | Yes | No | No | Data source connectors | | Dataset (Securable) | Yes | **Via Securable** | Yes | Yes | Data sources (search via `securable` with `type: 'dataset'`) | | EmbedFilterGroup | Yes | Yes | Yes | Yes | Shared filter groups | | Export | Yes | Yes | No | No | Export generation | | Formula | Yes | Yes | Yes | Yes | Calculated metrics | | Group | Yes | Yes | Yes | Yes | User groups | | Hierarchy | Yes | Yes | Yes | Yes | Column hierarchies | | Hierarchy Level | Yes | Yes | Yes | Yes | Hierarchy level definitions | | Integration | Yes | Yes | Yes | Yes | Third-party integrations | | IQConversation | Yes | Yes | No | Yes | AI chat conversations | | IQMessage | Yes | Yes | No | No | AI chat messages | | IQFormula | No | Yes | No | No | AI-generated formulas | | Locale | No | Yes | Yes | No | Language settings | | Organization | No | Yes | Yes | No | Multi-tenant organizations | | Plugin | Yes | Yes | Yes | Yes | Custom data source plugins | | Schedule | Yes | Yes | Yes | Yes | Report schedules | | Share | Yes | Yes | Yes | Yes | Sharing configurations | | SSOConfig | Yes | Yes | Yes | Yes | Single sign-on settings | | Tag | Yes | Yes | Yes | Yes | Resource tags | | Theme | Yes | Yes | Yes | Yes | Visual themes | | User | Yes | Yes | Yes | Yes | User accounts | ## Error Handling API errors return JSON with error details: ```json { "error": { "code": "INVALID_REQUEST", "message": "Description of the error" } } ``` Common HTTP status codes: - `200`: Success - `400`: Bad request (invalid parameters) - `401`: Unauthorized (invalid credentials) - `403`: Forbidden (insufficient permissions) - `404`: Not found - `429`: Rate limit exceeded - `500`: Internal server error ## Resources - Full API Documentation: https://developer.luzmo.com/guide/api--introduction - OpenAPI Schema: https://developer.luzmo.com/assets/oas/oas-luzmo-full.json - **Note**: The OpenAPI schema documents the action-based API. Endpoints use patterns like `/dashboard?create`, `/user?get` - these are all POST endpoints where the query parameter indicates the action type. Use this schema for understanding request/response structures, not for generating HTTP requests with REST verbs. - API Schema Diagram: https://developer.luzmo.com/guide/api--schema - Rate Limits: https://developer.luzmo.com/guide/api--rate-limits - Academy Tutorials: https://academy.luzmo.com - Academy AI Search: For AI-powered answers about Luzmo, use: ```bash POST https://ai-knowledge-base.luzmo.com/ask-question Content-Type: application/json {"question": "your query", "stream": true} ```