Skip to main content
Definite can be embedded in other web applications via iframes. There are two embed types: docs (traditional YAML dashboards) and data apps (React-based interactive applications). Both use the same get_embedded_url endpoint with different parameters.

Data App Embeds

Data apps are standalone React applications that run inside an iframe. They support tenant-scoped filtering, where each embedded user only sees their own data.
1

Obtain Your API Key

Get your API key from the menu in the Definite web application. See here for more.
2

Build and Publish the Data App

Build the data app using the Definite data-apps skill. The build produces two artifacts:
  • index.html (full manifest, for internal development)
  • index.embedded.html (stripped manifest, for embedded use)
Upload both files to your team’s Drive (e.g. apps/my-app/dist/).
3

Generate an Embed URL

Call the endpoint to generate a signed embed URL:Endpoint: POST https://api.definite.app/v1/get_embedded_url

Parameters

ParameterTypeRequiredDescription
embed_typestringYesMust be "data_app"
user_identifierstringYesA unique identifier for the visiting user (e.g. tenant ID)
drive_filestringYesPath to the .embedded.html artifact in your team’s Drive
required_filtersarrayNoFilters applied server-side to all queries. Uses Cube filter syntax: [{"member": "...", "operator": "equals", "values": ["..."]}]
expires_inintegerNoToken lifetime in seconds. Default: 86,400 (24 hours). Max: 2,592,000 (30 days). Min: 60.
allowed_hostsarrayNoHostnames allowed to iframe the app (sets frame-ancestors CSP). Default: ["*"] (any host).

Response

{
  "url": "https://api.definite.app/v4/data-apps/embed?t=<signed_token>",
  "expires_at": "2026-04-13T10:00:00Z"
}
4

Present the Iframe

Embed the returned URL in an iframe. The URL serves the data app HTML directly with the signed token injected. No Supabase session or magic link is needed.
<iframe
  src="https://api.definite.app/v4/data-apps/embed?t=<signed_token>"
  width="100%"
  height="800"
  frameborder="0"
></iframe>

Example

import requests

DEF_API_KEY = "your-def-api-key"

embed_options = {
    "embed_type": "data_app",
    "user_identifier": "tenant-123",
    "drive_file": "apps/my-app/dist/index.embedded.html",
    "required_filters": [
        {"member": "customerId", "operator": "equals", "values": ["tenant-123"]}
    ],
    "expires_in": 86400,
    "allowed_hosts": ["app.yourcompany.com"]
}

res = requests.post(
    url="https://api.definite.app/v1/get_embedded_url",
    json=embed_options,
    headers={"Authorization": DEF_API_KEY}
)

data = res.json()
iframe_url = data["url"]
expires_at = data["expires_at"]

Required Filters and Tenant Isolation

Data apps enforce tenant isolation through required_filters. Here’s how it works:
  1. The app’s app.json manifest declares requiredFilters on each resource, mapping a filter member name to a SQL column:
{
  "resources": {
    "transactions": {
      "kind": "dataset",
      "source": {
        "type": "sql",
        "sql": "SELECT * FROM lake.schema.transactions WHERE {{ required_filters }}"
      },
      "requiredFilters": {
        "customerId": { "column": "customer_id" }
      }
    }
  }
}
  1. The SQL must include a {{ required_filters }} marker where the filter predicate should be injected.
  2. When you call get_embedded_url with required_filters: [{"member": "customerId", "operator": "equals", "values": ["A"]}], the server substitutes the marker with a parameterized predicate: (customer_id = $1) with bind var $1 = 'A'.
  3. Filter values are always passed as bind variables, never string-concatenated, so tenant identifiers cannot break out via SQL injection.
  4. For non-embedded users (team members testing via session/API key), the marker is replaced with (TRUE), returning all data.

Important Notes

  • Token expiry: Tokens are stateless HMAC-signed payloads. When a token expires, mint a new one via get_embedded_url. There is no refresh endpoint.
  • Emergency revocation: Rotating the signing key invalidates all outstanding tokens at once.
  • Drive file pinning: The token is pinned to the drive_file specified at mint time. A token minted for one app cannot be used to query a different app.
  • SQL is never sent to the browser. The .embedded.html artifact has SQL and Cube query declarations stripped at build time. The browser only sees {"type": "sql", "embedded": true}. All query execution happens server-side via POST /v4/data-apps/query.
  • Cache headers: The embed HTML response sets Cache-Control: private, no-store and Referrer-Policy: no-referrer to prevent token leakage.
  • Filter options are tenant-scoped. If you build dropdown filters from SELECT DISTINCT queries on the client-side DuckDB dataset, the options will only include values that exist in that tenant’s data.

Doc Embeds

Docs (YAML dashboards) can be embedded in iframes using a Supabase magic link flow.
1

Obtain Your API Key

Get your API key from the menu in the Definite web application. See here for more.
2

Generate an Embedded UI Link

Call the endpoint to generate an embedded UI link:Endpoint: POST https://api.definite.app/v1/get_embedded_url

Parameters

ParameterTypeRequiredDescription
embed_typestringYesMust be "doc"
user_identifierstringYesA user identifier for the visiting user
doc_idstringYesThe UUID of the doc to share (found in the URL after /docs/)
required_filtersarrayNoCube filters applied to all of the user’s queries
redirect_query_paramsstringNoAdditional query params to append to redirect URL
3

Present the Iframe

Present an iframe in your web application with the generated URL. The URL authenticates the user and redirects to a copy of the shared doc.

Example

import requests

DEF_API_KEY = "your-def-api-key"

embed_options = {
    "user_identifier": "your-user-id",
    "doc_id": "doc-uuid",
    "embed_type": "doc"
}

res = requests.post(
    url="https://api.definite.app/v1/get_embedded_url",
    json=embed_options,
    headers={"Authorization": DEF_API_KEY}
)

iframe_url = res.json()["url"]

Important Notes

  • User Identifier: The user_identifier defines a user in your team with limited access. This user cannot view other users’ content, edit integrations or cube models, or execute SQL blocks.
  • Multiple Calls: You can call get_embedded_url multiple times with different docs. The user will have a copy of each.
  • Content Updates: If you update the source doc, all downstream users will receive an updated copy on the next get_embedded_url query or page refresh.