Documentation

Mint a tenant JWT

createJwt() signs an RS256 token with organizationId and tenantId. The browser never receives your workspace private key.

Embedded dashboards authenticate with a short-lived RS256 JWT signed by your workspace private key. Mint the token in your API with createJwt, then pass only that string to QuerypanelEmbedded. QueryPanel verifies the token with your public key and reads organizationId and tenantId from the claims.

createJwt

tenantId is required. Optional userId and scopes further limit what the embed can do. The Node SDK constructor already knows your workspace id and private key; do not put the PEM in a NEXT_PUBLIC_* env var.

Server-only — never call this from React
import { QueryPanelSdkAPI } from "@querypanel/node-sdk";

const qp = new QueryPanelSdkAPI(
  process.env.QUERYPANEL_URL!,
  process.env.PRIVATE_KEY!,
  process.env.QUERYPANEL_WORKSPACE_ID!,
);

const jwt = await qp.createJwt({
  tenantId: session.tenantId,
  userId: session.userId,
  scopes: ["dashboards:read", "charts:read"],
});

// Return jwt to the client. The private key never leaves this process.

What the token carries

Requests are signed with RS256. The payload includes organizationId (your workspace) and tenantId (the customer). Add userId / scopes per call when the embed should be narrower than the tenant. JWT extraction and verification happen server-side in the QueryPanel API — never parse tenantId from a token in frontend code and treat that as the security boundary.

Related