Version: v4 | v5 | v6 (latest)Documentation Index
Fetch the complete documentation index at: https://domoinc-jkreitzman-patch-1.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
A powerful JavaScript SDK for building custom applications within the Domo platform
ryuu.js) is the official JavaScript SDK for building Custom Apps inside the Domo platform. Apps run inside iframes — domo.js handles authenticated HTTP requests, secure messaging with the parent window, mobile WebView bridges, and provides high-level helpers for Data, AppDB, Code Engine, Workflows, and AI services.
Zero runtime dependencies. ~28KB UMD bundle. TypeScript included.
What’s New in v6
| Feature | Description |
|---|---|
domo.intercept() | Register request middleware — logging, retries, custom headers |
| Structured errors | DomoHttpError, DomoAuthError, DomoConnectionError, DomoValidationError, DomoTimeoutError |
RequestOptions.schema | Runtime response validation with a custom parse function |
domo.debug | Category-based debug logging, persisted via localStorage |
| Service namespaces | domo.data, domo.appdb, domo.ai, domo.workflow, domo.codeEngine |
| Optimized bundle | Reduced bundle size, zero runtime dependencies |
Quick Start
Get started with ryuu.js in just a few lines:Features
- Data API — Query datasets with typed options (fields, filters, aggregations, date graining, beast modes)
- AppDB — Full CRUD, MongoDB-style queries, bulk operations, partial updates, collection management
- Code Engine — Run Code Engine functions by manifest alias
- Workflows — Start and monitor Domo Workflows
- AI Services — Text generation and text-to-SQL via Domo’s AI Service Layer
- HTTP API Access — Authenticated requests to Domo datasets, datastores, and APIs
- Real-time Events — Listen for dataset updates, filter changes, and variable updates
- Filter Management — Get and set page-level filters programmatically
- Variable Management — Access and update page variables
- Custom App Data — Send custom data between apps on the same page
- Typed Environment —
domo.envwith userId, userName, host, platform, enriched from the environment API - Navigation — Programmatically navigate within Domo
- Mobile Support — Full iOS and Android compatibility
- TypeScript Ready — Complete type definitions with typed callbacks and generics
- Zero Dependencies — ~28KB UMD bundle with no runtime dependencies
- Extensible —
extend()propagates overrides to all services (data, appdb, ai, etc.) - Structured Errors — Typed error classes (
DomoHttpError,DomoAuthError,DomoConnectionError,DomoValidationError) withinstanceofsupport - Schema Validation — Optional runtime response validation via
{ schema: { parse } }(works with zod, valibot, etc.) - Request Interceptors — Middleware pattern via
domo.intercept()for logging, retry, caching - Debug Mode —
domo.debug.enable()for category-based logging of HTTP, messages, filters, variables
Installation
Requirements:- Node.js 16+ (for local development with the Domo CLI)
- Modern browsers: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
- Zero runtime dependencies — no
npm installrequired inside your app bundle
NPM
CDN / Script Tag
Load the library directly from a CDN. The bundle exposes a globaldomo object:
domo init scaffolds a local domo.js file you can reference with <script src="domo.js"></script> instead.
TypeScript
Type definitions are included automatically:Core Concepts
Architecture
Your Custom App runs in an<iframe> inside a Domo page. domo.js establishes communication between your app and the parent Domo window using two channels:
- MessageChannel (inbound) — The SDK creates a
MessageChanneland transfersport2to the parent on subscribe. The parent sends filter updates, variable changes, and acks throughport2; your app receives them onport1. window.parent.postMessage(outbound) — Outbound messages (filter requests, variable requests, navigate) always usewindow.parent.postMessageso the parent can verifyevent.originfor security.
Domo is a static class — you never call new Domo(). All methods are called directly on the class:
ASK-ACK-REPLY Pattern
Async operations like updating filters and variables use a request-tracking pattern:- ASK — Your app sends a request with a unique ID
- ACK — Parent acknowledges receipt (optional callback)
- REPLY — Parent sends the response when the operation completes (optional callback)
Token Injection
A singleMutationObserver watches document.documentElement with subtree: true. For every DOM node added at any depth, it automatically injects the Domo session token (ryuu_sid) into relative href and src attributes. Token is fetched once per batch — you don’t need to manage auth manually.
Environment Context
domo.env provides typed access to the current user, instance, and page context. Properties are populated immediately from iframe query parameters, then enriched in the background from GET /domo/environment/v1 (which provides authoritative server-side values like host):
loaded property indicates whether the environment API has finished loading. If it fails (e.g. running locally), query params serve as the fallback.
Error Handling
v6 replaces generic errors with a structured hierarchy. Import only what you need:| Class | Thrown When | Key Properties |
|---|---|---|
DomoHttpError | Non-2xx HTTP response | status, statusText, body, headers |
DomoAuthError | 401 or 403 response | Extends DomoHttpError |
DomoConnectionError | Network failure (fetch rejects) | — |
DomoValidationError | Invalid input or schema parse failure | errors[] |
DomoTimeoutError | Request or message timeout | url |
Always check
DomoAuthError before DomoHttpError in your catch block — DomoAuthError extends DomoHttpError, so an instanceof DomoHttpError check will also match auth errors.Validation Errors
When you pass malformed data to filters or variables, ryuu.js throws aDomoValidationError and logs the expected data model to console.error:
API Reference
Service Namespaces
v6 introduces high-level service namespaces that handle URL construction and request formatting for you.domo.data
Query datasets connected to your app via their manifest.json alias. Each dataset must be mapped in manifest.json under datasources before it can be queried by alias.
domo.data.query(alias, options?)
Query a dataset by its manifest alias. Supports all Data API query operators.
Parameters:
alias(string, required) — Dataset alias frommanifest.jsonoptions(object, optional)
fields, filter, avg, count, max, min, sum, unique, groupBy, dateGrain, calendar, orderBy, limit, offset, useBeastMode, format
Returns: Promise<any>
domo.data.sql(alias, sql)
Run a SQL query against an aliased dataset.
Parameters:
alias(string, required) — Dataset alias frommanifest.jsonsql(string, required) — SQL query string. The table name is the dataset alias.
Promise<any>
data.sql uses a POST request with Content-Type: text/plain. Keep this in mind if you’re using interceptors that inspect the request method. The SQL API does not support page filters or JOINs.domo.appdb
Persistent document storage scoped to your Custom App. Each document lives in a collection and has a content field plus system-managed metadata.
appdb.create and appdb.update automatically wrap your document in { content: ... } if you pass a plain object — you don’t need to wrap it yourself.Document CRUD
Query with MongoDB syntax
Partial update (MongoDB operators)
Bulk operations
Collection management & export
domo.ai
Generate text and convert natural language to SQL using Domo’s AI services.
domo.ai.generateText(prompt, options?)
Generate text using Domo’s LLM integration.
Parameters:
prompt(string, required) — The input promptoptions(object, optional) — Model configuration
Promise<string>
domo.ai.textToSQL(question, options?)
Convert a natural language question into a SQL query.
Parameters:
question(string, required) — Natural language questionoptions(object, optional)dataSourceSchemas(array) — Dataset schema hints to improve SQL accuracy
Promise<{ choices: { output: string }[] }>
AI services consume AI credits. See your Domo instance rate card for details.
domo.workflow
Trigger and monitor Domo Workflow automations.
domo.workflow.start(alias, input?)
Trigger a workflow by its alias.
Parameters:
alias(string, required) — Workflow alias defined in your appinput(object, optional) — Input data to pass to the workflow
Promise<{ id: string }> — The workflow instance
domo.workflow.getInstance(alias, instanceId)
Get the current status of a running workflow instance.
Parameters:
alias(string, required) — Workflow aliasinstanceId(string, required) — Instance ID returned byworkflow.start()
Promise<{ state: string, ... }>
Requires a
workflowMapping entry in your manifest.json mapping the alias to a Domo Workflow.domo.codeEngine(alias, input?)
Invoke a Code Engine function by alias.
Parameters:
alias(string, required) — Function alias from your app manifestinput(object, optional) — Input parameters
Promise<any> — The function’s return value
Requires a
packageMapping entry in your manifest.json mapping the alias to a Code Engine function.Event Listeners
All listener methods return an unsubscribe function. Call it to stop listening.domo.onFiltersUpdated(callback)
Listen for page-level filter changes.
Parameters:
callback—(filters: Filter[]) => void
function — Unsubscribe function
"IN"— Value is in list"NOT_IN"— Value is not in list"CONTAINS"— Value contains string"NOT_CONTAINS"— Value doesn’t contain string"STARTS_WITH"— Value starts with string"NOT_STARTS_WITH"— Value doesn’t start with string"ENDS_WITH"— Value ends with string"NOT_ENDS_WITH"— Value doesn’t end with string
"EQUALS"— Equals value"NOT_EQUALS"— Not equals value"GREATER_THAN"— Greater than value"GREAT_THAN_EQUALS_TO"— Greater than or equals value"LESS_THAN"— Less than value"LESS_THAN_EQUALS_TO"— Less than or equals value"BETWEEN"— Between two values
domo.onVariablesUpdated(callback)
Listen for page variable changes.
Parameters:
callback—(variables: Variable[]) => void
function — Unsubscribe function
domo.onDataUpdated(callback)
Listen for dataset update events. Called when a dataset connected to your app is refreshed.
Parameters:
callback—(alias: string) => void
function — Unsubscribe function
domo.onAppDataUpdated(callback)
Listen for custom data sent by other apps on the same Domo page.
Parameters:
callback—(data: any) => void
function — Unsubscribe function
Emitters
domo.requestFiltersUpdate(filters, pageStateUpdate?, onAck?, onReply?)
Push filter changes to the parent Domo page.
Parameters:
filters(Filter[] | null, required) — Filters to apply. Passnullto clear all filters.pageStateUpdate(boolean, optional) — Iffalse, only the card-level filter state is updated (default:true)onAck(function, optional) — Called when request is acknowledgedonReply(function, optional) — Called when request completes
string — Request ID
domo.requestVariablesUpdate(variables, onAck?, onReply?)
Push variable changes to the parent Domo page.
Parameters:
variables(Variable[], required)onAck(function, optional)onReply(function, optional)
string — Request ID
domo.requestAppDataUpdate(data, onAck?, onReply?)
Send custom data to other apps on the same Domo page.
HTTP Methods
All HTTP methods return Promises and support multiple data formats. All methods throw structured errors — see Error Handling. The auth headerX-DOMO-Ryuu-Session is injected automatically.
domo.get(url, options?)
Fetch data from a Domo dataset or API endpoint.
Parameters:
url(string) — API endpoint URLoptions(object, optional) — Request options
Promise<ResponseBody>
Basic Usage:
'array-of-objects'(default) —Record<string, any>[]'array-of-arrays'—ArrayResponseBodywith.columnsand.rows'csv'— CSV string'excel'— Blob'plain'— Plain text string
domo.getAll(urls, options?)
Fetch multiple endpoints in parallel and return results as an array.
domo.post(url, body?, options?)
domo.put(url, body?, options?)
domo.delete(url, options?)
domo.domoHttp(method, url, options?, body?)
Low-level method used internally by all other HTTP helpers. Use this for HTTP methods not covered above (e.g. PATCH).
Request Interceptors
domo.intercept() registers middleware that wraps every HTTP request. Interceptors follow an onion model — each interceptor receives the request and a next function to call the next layer.
Interceptors wrap the
fetch call — headers and auth tokens are already set when your interceptor runs.domo.intercept(fn)
Parameters:
fn—(request: Request, next: (request: Request) => Promise<Response>) => Promise<Response>
() => void — Call to remove the interceptor
The config object passed to each interceptor has { method, url, headers, body }. Headers and auth tokens are already set when interceptors run.
Schema Validation
Pass aschema option to any HTTP request to validate or transform the response at runtime. If parse throws, domo.js wraps it as DomoValidationError.
Navigation
domo.navigate(url, isNewWindow?)
Navigate the parent Domo page from inside your app iframe.
Parameters:
url(string, required) — Domo page URL or routeisNewWindow(boolean, optional) — Open in new tab (default:false)
For mobile web platforms, routes are automatically prefixed with
/m#. External links are restricted to whitelisted domains — configure in Admin > Network Security > Custom Apps authorized domains.Utilities
domo.extend(overrides)
Override static methods or properties of the Domo class. Also updates the shared transport so overrides propagate to all service namespaces (data, appdb, ai, etc.).
domo.getRequests() / domo.getRequest(id)
Inspect the ASK-ACK-REPLY request lifecycle for tracked requests (filter updates, variable updates, etc.).
TypeScript Support
All types are exported fromryuu.js:
Mobile Platform Support
domo.js detects the platform and routes messages through the appropriate bridge automatically. No configuration needed.| Platform | Bridge used |
|---|---|
| Desktop / Web | MessageChannel + window.parent.postMessage |
| iOS | webkit.messageHandlers (domofilter, domovariable) |
| Android / Flutter | Global objects (window.domofilter, window.domovariable) |
- Navigation routes are automatically prefixed with
/m#on mobile web - Test on actual devices or simulators — not just browser DevTools mobile emulation
- Optimize data fetching: mobile devices have limited memory and CPU
Advanced Usage
Debug Mode
Enable category-based logging to inspect HTTP requests, messages, filters, and variables:| Category | What it logs |
|---|---|
http | Every request: method, URL, headers, response status and body |
messages | All MessageChannel and postMessage traffic (inbound and outbound) |
filters | Filter update events and subscriptions |
variables | Variable update events and subscriptions |
all | Everything above |
Retry Logic
Implement retry logic for transient server errors using interceptors or a wrapper function:Custom Fetch
Provide your ownfetch implementation for testing, mocking, or custom network behavior:
Type Guards
Use type guards to validate runtime data before passing it to the SDK:Filters In Depth
First-registration behavior
onFiltersUpdated clears all parent filters on first registration by sending requestFiltersUpdate(null). All subsequent listeners call connect(true) which skips this. If you need to subscribe without clearing:
Wire format
The filter event name on the wire is"filter" (not "filtersUpdated"). Desktop and mobile use different field names which domo.js normalizes for you:
| Field | Desktop | Mobile |
|---|---|---|
| Column | columnName | column |
| Operator | operator | operand |
Complete Example
A real-world Custom App wiring together data, filters, variables, and navigation:Migration from v5
Error handling
v5 — errors were thrown as genericError objects or plain response objects.
v6 — errors are typed classes. Update your catch blocks:
Service namespaces (new in v6)
v6 adds high-level service namespaces. You can still use the low-level HTTP methods — the namespaces are additive:Debug logging
v5 — no built-in debug mode. v6 — usedomo.debug.enable():
Interceptors (new in v6)
Unchanged
- All low-level HTTP methods:
domo.get,domo.post,domo.put,domo.delete,domo.getAll - Event listener APIs:
onFiltersUpdated,onVariablesUpdated,onDataUpdated,onAppDataUpdated - Emitter APIs:
requestFiltersUpdate,requestVariablesUpdate,requestAppDataUpdate domo.navigate()domo.extend()domo.envshape- Static class design — no instantiation
- npm package name (
ryuu.js) and global (Domo)
Getting Help
- GitHub Issues — github.com/DomoApps/domo.js/issues: report bugs, request features, or browse known issues
- Domo Community — dojo.domo.com: community forums, guides, and answers from other Domo developers
- Related docs — Domo Apps CLI | manifest.json reference | App Framework overview