Embed a custom view
Once you’ve created and published a custom view, you can embed it in your own app: Paid renders the dashboard in a sandboxed iframe, and a signed token scopes the data to exactly one of your customers. The customer never logs into Paid, and the underlying queries are filtered to that customer in the database, not in the browser.
This is the recommended, easiest integration: your backend asks Paid for a short-lived token using your API key, and the @paid-ai/embed SDK handles the rest. You never manage a signing secret.
Custom views are experimental. Routes, token claims, and SDK surface may change without notice and are not covered by the v2 backwards-compatibility guarantees.
Prerequisites
- A published custom view and its
displayId(e.g.view_5oi3qvfaFLK). See create a custom view with Claude. - A Paid API key, used server-side only.
Step 1: Fetch an embed token from your backend
Your backend calls the Paid embed-token endpoint using your API key and returns the token to your frontend. Never expose your API key to the browser.
The endpoint mints a short-lived signed token scoped to a specific customer:
Response:
customerId accepts the customer’s Paid display id (cus_…), external id, or internal UUID.
Option A: use the SDK (recommended)
If Paid publishes an SDK for your stack, use it — the typed method makes the request for you and returns the token and its expiry. Call it from your own authenticated backend route and return token / expiresAt to the frontend.
TypeScript
Python
Go
Ruby
Java
Option B: call the REST endpoint directly
If there’s no SDK for your stack, call the endpoint over HTTP from your backend:
Node.js
Python
Step 2: Embed with the SDK
Install the embed library:
Pass a getToken callback that fetches a fresh token from your backend. The SDK calls getToken for the initial token and again automatically whenever a token expires — you do not need to manage refresh yourself.
renderCustomView returns a handle:
token is the view’s displayId (which dashboard to show); getToken
returns the signed access token (which customer to scope to). They are
different values — do not pass the JWT as token.
How scoping and isolation work
- The customer comes only from the verified token’s
subclaim — never from a client parameter. An unknownsub, a missing or invalid token, or a token signed for the wrong resource is rejected. - The view’s queries run against a per-customer database layer that filters every row to the token’s customer. The author’s SQL contains no customer filter; isolation is enforced in the database.
- The dashboard renders in a sandboxed iframe with no network access of its own. The signed token is never passed into that frame — only the already-scoped data for that one customer.