Skip to main content
Basedash supports two types of embedding:
  • Dashboard embedding: Embed a dashboard as a read-only, interactive view in an iframe.
  • Full app embedding: Embed the full Basedash app (dashboards + chat) inside your product with JWT SSO.

Dashboard embedding

Dashboard embedding is best when you want to show a specific dashboard inside another app.

Create an embed

  1. Open the dashboard in Basedash
  2. Click Share in the dashboard header
  3. Enable the Embedding toggle
  4. Copy the iframe snippet (or copy the plain URL)
Embeds use a share link with the /shared/{id} path.
<iframe
  src="https://charts.basedash.com/shared/xyz789"
  width="100%"
  height="600"
  frameborder="0"
  allowfullscreen
></iframe>

Dashboard filters

Visibility

Filters are hidden by default on embedded dashboards. To show a filter, edit the filter and enable the “Show on public dashboard” option. This is configured per-filter, allowing you to choose exactly which filters viewers can interact with. For more information on configuring filters, see the filters and variables documentation.
When a filter is shown on a public dashboard, any viewer can provide arbitrary values. If the filter is used in a SQL query, viewers can inject any value into that query. Ensure this is acceptable for your use case, and always use read-only database credentials. For sensitive data, consider using secure filtering instead.

Secure filtering

Secure filtering allows you to lock filter values in public dashboard URLs using JWT tokens. This prevents viewers from modifying certain filter values, making it safe to share dashboards that filter data by tenant, user, or other sensitive parameters. When to use secure filtering When a filter is hidden (via “Show on public dashboard” disabled), the filter uses its default value and viewers cannot override it via URL parameters—those values are enforced server-side. Use secure filtering when you need to dynamically set different filter values for different viewers:
  • Multi-tenant applications: Lock a company_id or tenant_id filter so each customer only sees their own data
  • User-specific dashboards: Lock a user_id filter to show personalized data
  • Sensitive data access: Ensure viewers cannot modify filters that control access to restricted information
How it works Instead of allowing viewers to select filter values, you generate a signed JWT containing the locked values and append it to the public dashboard URL. Basedash verifies the JWT signature and applies the locked values server-side, so viewers cannot tamper with them. URL format The secure filtering URL follows this pattern:
https://charts.basedash.com/shared/{publicSharingLinkId}/{jwtToken}
  • publicSharingLinkId: The ID from your public share link. When you enable sharing on a dashboard and copy the link, it looks like https://charts.basedash.com/shared/abc123. The abc123 part is your publicSharingLinkId.
  • jwtToken: A signed JWT containing the locked filter values.
JWT payload Your JWT must include these claims:
ClaimTypeRequiredDescription
dashboardLinkIdstringYesMust match the publicSharingLinkId in the URL
paramsobjectYesKey-value pairs of filter syntax names to locked values
expnumberYesExpiration timestamp (Unix seconds)
iatnumberNoIssued-at timestamp (Unix seconds)
The params object keys should match your filter’s syntax name (e.g., user_id, company_id). Values can be strings, numbers, booleans, or arrays of strings. Example Here’s an example JWT payload that locks a company_id filter:
{
  "dashboardLinkId": "abc123",
  "params": {
    "company_id": "comp_456"
  },
  "exp": 1735689600,
  "iat": 1735686000
}
And example code to generate the token:
import jwt from "jsonwebtoken";

function generateSecureDashboardUrl(publicSharingLinkId, lockedParams) {
  const token = jwt.sign(
    {
      dashboardLinkId: publicSharingLinkId,
      params: lockedParams,
    },
    process.env.BASEDASH_EMBED_JWT_SECRET,
    { expiresIn: "1h" },
  );

  return `https://charts.basedash.com/shared/${publicSharingLinkId}/${token}`;
}

// Usage
const url = generateSecureDashboardUrl("abc123", { company_id: "comp_456" });
JWT secret The JWT secret used to sign tokens is the same secret used for full app embedding. You can find it at Settings → Security.
Store your JWT secret securely in environment variables. Never expose it in client-side code.
Behavior When a JWT is provided in the URL:
  • Locked filters are applied server-side and cannot be changed by viewers
  • Locked filters are hidden from the filter bar on the dashboard
  • Other filters (not included in the JWT) remain interactive if configured to show on public dashboards
  • If the JWT is invalid, expired, or the signature doesn’t match, the dashboard returns an error

Full app embedding

Full app embedding lets you embed the entire Basedash experience inside your product. Your users can view dashboards, build new charts, and chat with the AI assistant—all without leaving your application. This is ideal for customer portals, partner dashboards, or any scenario where you want to give users a complete BI experience powered by their own data.

How it works

Full app embedding uses JWT-based single sign-on (SSO) inside an iframe:
  1. Your server generates a JWT containing the user’s identity and your Basedash organization ID
  2. The iframe loads the SSO endpoint (/api/sso/jwt?jwt=...) with the token
  3. Basedash validates the JWT against your organization’s secret
  4. A session is created for the user (creating their account if needed)
  5. The user is redirected to your organization’s home page inside the iframe

Setup overview

Setting up full app embedding involves these steps:
  1. Enable embedding and get your JWT secret
  2. Generate JWTs server-side for your users
  3. Load the iframe with the SSO URL

Step 1: Enable embedding

Enable embedding for your organization by going to Settings → Embedding → Enable full app embedding. You’ll also need your JWT secret to sign tokens that authenticate users into the embedded app. You can find this at Settings → Security.
Store your jwtSecret securely in your environment variables. Never expose it in client-side code.
You can also configure allowed origins on this page to restrict which domains can embed your organization.

Step 2: Generate JWTs server-side

Your backend must generate a signed JWT for each user who accesses the embed. Here are examples in common languages:
import jwt from "jsonwebtoken";

function generateBasedashToken(user) {
  return jwt.sign(
    {
      email: user.email,
      orgId: process.env.BASEDASH_ORG_ID,
      firstName: user.firstName,
      lastName: user.lastName,
      role: "MEMBER", // or 'ADMIN'
    },
    process.env.BASEDASH_EMBED_JWT_SECRET,
    { expiresIn: "10m" },
  );
}

// Express route example
app.get("/embed/basedash", (req, res) => {
  const token = generateBasedashToken(req.user);
  const embedUrl = `https://charts.basedash.com/api/sso/jwt?jwt=${token}`;

  res.render("embed", { embedUrl });
});

Step 3: Load the iframe

In your frontend, render an iframe pointing to the SSO URL:
<iframe
  src="https://charts.basedash.com/api/sso/jwt?jwt=YOUR_JWT_TOKEN"
  width="100%"
  height="800"
  frameborder="0"
></iframe>

Customization options

You can customize the appearance of the embedded app by appending query parameters to the SSO URL:
<iframe
  src="https://charts.basedash.com/api/sso/jwt?jwt=YOUR_JWT_TOKEN&theme=dark&hide_org_name=true"
  width="100%"
  height="800"
  frameborder="0"
></iframe>
ParameterValuesDefaultDescription
themelight, dark, autoautoOverride the theme for the embedded app. auto uses the system preference.
hide_org_nametruefalseHide the organization name in the sidebar
hide_suggested_promptstruefalseHide the suggested prompts in the AI chat input

JWT claims reference

Your JWT must include these claims:
ClaimTypeRequiredDescription
emailstringYesThe user’s email address
orgIdstringYesYour Basedash organization ID
expnumberYesExpiration timestamp (Unix seconds)
iatnumberYesIssued-at timestamp (Unix seconds)
firstNamestringNoUser’s first name
lastNamestringNoUser’s last name
rolestringNoADMIN or MEMBER (defaults to MEMBER)
The role claim is only used when creating new members. It doesn’t change the role of existing members.

Allowed origins

For security, you can restrict which domains can embed your Basedash organization. Configure this at Settings → Embedding You can add specific origins (e.g., https://app.example.com) or use wildcard patterns to allow all subdomains of a domain (e.g., https://*.example.com).
Wildcard patterns must include a full domain name. Overly broad patterns like https://*.com are not allowed.
If no origins are configured, embeds are allowed from any domain.

Security best practices

Never expose the jwtSecret in client-side code. Generate JWTs only on your backend.
JWTs should expire within 10-60 minutes. Users only need a valid token when loading the iframe—once authenticated, they use a Basedash session cookie.
Always set embedAllowedOrigins in production to prevent unauthorized sites from embedding your organization.
When connecting data sources, use database credentials with read-only permissions to minimize risk.
Before generating a JWT, verify that the current user should have access to the embedded analytics.

Troubleshooting

Error: “The embed URL is missing the required JWT token”Make sure your iframe src includes the ?jwt= query parameter with your signed token.
Error: “Embedding is not enabled for this organization”Enable embedding when creating the organization by setting fullEmbedEnabled: true, or update an existing organization via the API.
Error: “This embed is not authorized to load from [origin]”Add your domain to the embedAllowedOrigins array. You can add a specific origin (e.g., https://app.example.com) or use a wildcard pattern to allow all subdomains (e.g., https://*.example.com).
Error: “The JWT token is invalid or has expired”
  • Verify you’re using the correct jwtSecret for the organization
  • Check that the JWT hasn’t expired (tokens should be short-lived)
  • Ensure you’re signing with the HS256 algorithm
  • Verify the clock on your server is accurate (JWT validation allows 30 seconds of clock skew)
Error: “Unable to verify the request origin”This happens when allowed origins are configured but the browser doesn’t send a Referer header. Check that:
  • Your page doesn’t have Referrer-Policy: no-referrer
  • You’re not loading the iframe from a file:// URL during development
Error: “The organization ID in your JWT does not match any Basedash organization”Verify that the orgId claim in your JWT matches an existing Basedash organization ID.