Create a custom view with Claude
A custom view is a per-customer dashboard authored in Paid. Each view is a set of named SQL queries over your analytics data plus a self-contained HTML bundle that renders them. Once published, you can embed it in your own app, scoped to exactly one customer.
You don’t write the SQL or the dashboard by hand. You describe what you want to Claude, which authors the queries and the render bundle for you over the Paid MCP server, saves the view to Paid, and lets you preview it before publishing.
Custom views are experimental. Routes, token claims, MCP tools, and the SDK surface may change without notice and are not covered by the v2 backwards-compatibility guarantees.
Step 1: Connect Paid to Claude
Custom-view authoring runs through the Paid MCP server. If you haven’t already, connect it to your MCP client.
For Claude Code:
For Claude Desktop, Cursor, Windsurf, and other clients, see the MCP quickstart for the exact configuration. Your API key authenticates and scopes every tool call to your organization.
Step 2: Ask Claude to build a dashboard
Describe the dashboard you want in plain language. For example:
Using Paid, build a custom view for my customers that shows their monthly signal volume, total delivered value, and a usage trend over the last three months. Make it interactive with a daily/cumulative toggle.
Behind the scenes, Claude follows a fixed authoring flow using the Paid MCP tools:
- Reads the authoring guide (
paid_get_custom_view_authoring_guide) to load the query and render-bundle contract and a sample bundle to start from. - Explores your analytics data (
paid_get_analytics_schema,paid_execute_analytics_query) to find the right tables and columns. - Writes one or more named SQL queries plus a self-contained HTML render bundle that visualizes them.
- Previews the exact bundle (
paid_get_custom_view_preview_harness) — the same bundle it will save, rendered the way Paid does, so the preview and the saved view can’t drift apart. - Creates the view (
paid_create_custom_view). The view is saved to Paid as a draft with a stabledisplayId(e.g.view_5oi3qvfaFLK), and Claude shares a preview link so you can open it directly.
You can iterate conversationally — ask Claude to add a chart, change a metric, or adjust the layout, and it updates the bundle.
Step 3: Preview the view
Open the view — use the preview link Claude gives you when it creates the view, or find it in the Paid dashboard under Custom views. Choose a sample customer, and review how the dashboard renders against real, customer-scoped data. The preview uses the exact sandbox the embed will use, so what you see is what your customers will see.
If something looks off, go back to Claude and refine.
Step 4: Publish
Only published views can be embedded — a draft is treated as not found on the public embed surface, so a draft’s existence is never revealed to an end customer.
When you’re happy with the preview, publish it. Either:
-
Click Publish on the view’s preview page in the dashboard, or
-
Ask Claude to publish it (
paid_publish_custom_view), or -
Call the API:
Publishing is idempotent — re-publishing an already-published view is a safe no-op.
Once published, head to Embed a custom view to drop it into your app.
The authoring contract
You don’t need to know these rules to use a custom view — Claude follows them automatically — but they explain why a custom view is safe to embed for any of your customers:
- No customer filter in the SQL. The author writes queries that select across your organization; Paid scopes every query to the viewing customer in the database at run time. Isolation is enforced by the database, not by the query or the browser. See the analytics schema reference for the tables available to queries.
- The render bundle is self-contained and sandboxed. It runs in a network-less, opaque-origin iframe — no fetch, no CDN. All CSS, JavaScript, and charting libraries are inlined (budget: 512 KB). The dashboard receives its data via a
paid:datamessage, never over the network. - The timeframe is an org-controlled default. Queries use
{period_start:DateTime}/{period_end:DateTime}placeholders with a default period, so you can change the default later (paid_update_custom_view_period) without re-authoring SQL. The dashboard receives data already filtered to that range — there is no separate date picker inside the view, and end customers see the range you set.