# Prism

> Source: https://cross-deck.com/docs/prism/ · Crossdeck developer docs (generated from the published page).

Intelligence layer
Bank-grade · scoped keys
·
Read API + AI/MCP connector

**Prism is Crossdeck's intelligence layer.** Ask Prism anything across your whole portfolio — revenue, database read-cost, errors, per-host analytics, and the cross-layer answers *only* Crossdeck can give, because Crossdeck owns the identity that joins them: *"this error hit user_847, who pays you $90/mo."* There are two ways to reach the same intelligence — your backend **reads** Prism (the API), and your AI **talks to** Prism (the MCP connector). Everything is read-only, server-to-server, and behind a scoped key whose scope *is* the security boundary.

## What Prism is

Crossdeck already owns four layers about your users and joins them by identity: **identity** (the SDK), **revenue** (the rails — Stripe, Apple, Google), **errors**, and **database read-cost**. Prism is the surface that hands that joined intelligence back to you. A single-layer tool can tell you "this error happened 400 times." Only Prism can tell you "…and 3 of the people it hit are paying customers worth $230/mo combined" — because it crosses the layers no single tool owns.

**The brand:** developers don't think "API" or "MCP" — they think *"ask Prism."* The MCP connector is one way of talking to Prism; the API is another way of reading it. Same intelligence underneath.

## Two ways to reach Prism

The connector (MCP) The API

Who calls it Your AI — Claude, ChatGPT, Cursor, any MCP-aware tool Your backend / Worker
How "Ask Prism" in natural language GET requests, JSON over HTTPS
Credential Sign in once (OAuth) — no key to paste A secret key ( cd_sk_ )
Reach Every app in your workspace One project (the key's project)

## Keys & permissions

Prism follows Stripe's restricted-key model: **the key's scope is the boundary**, and you grant exactly what a key may read when you mint it. Three key types:

Prefix Type What it is

cd_wk_ Workspace key Your account-level credential. Reads every app you own, full suite (including identity). When you connect an AI it signs in and Crossdeck mints a short-lived, revocable one of these for the session — you never paste a key. Create a long-lived one only for programmatic API use. Server-side only.
cd_sk_ Secret key Scoped to one project . Aggregate reads by default; identity (row-level) is a permission you grant at mint. This is what your backend uses, and what you'd distribute. Server-side only.
cd_pub_ Publishable key Ingest only (the SDKs). Origin-locked, safe in client bundles. Cannot read Prism.

### The two tiers, set on the key at mint

- **Aggregate** (default) — counts and totals, never an individual. Safe to embed. Scopes: `reporting:aggregate`, `revenue:read`, `errors:read`, `buckets:read`.

- **Identity** (row-level — the moat) — who an error hit, a host's people, a person's journey, the cross-match. Scope: `reporting:identity` (and `crossmatch:read`). Granting it on a secret key is a conscious act: you tick it in the Create-key flow and acknowledge the row-level-data terms in the same step. A workspace key holds it by default.

**Identity is granted on the KEY, at mint — not a project-wide switch.** Enabling something in project settings does *not* retroactively add a scope to a key you already minted (scope is fixed at creation). To get identity access, mint a key with the identity permission ticked, or rotate an existing identity key. A key without the scope is rejected with `403 insufficient_scope` before any data is read.

## Connect your AI (the connector)

Prism is a hosted, remote [MCP](https://modelcontextprotocol.io) server. **In ChatGPT it's a listed app — add it by name.** In every other tool you add one URL and sign in. Either way there's no package to install, no key to copy, and no config file to edit.

**1a. In ChatGPT — add it from the app directory.** Prism is an approved ChatGPT app — add it in one click, then sign in (step 2). No developer mode, no URL to paste.

[Add Prism to ChatGPT ↗](https://chatgpt.com/plugins/plugin_asdk_app_6a48cb6545e4819192d92ee3b19a0701)

**1b. Everywhere else — add the connector URL.** Paste this into your AI tool's connector settings:

```
https://api.cross-deck.com/mcp
```

- **Claude** (desktop & web) — Settings → Connectors → *Add custom connector*.

- **Cursor** — Settings → MCP → *Add* → paste the URL.

- **Any MCP-aware tool** — add a custom / remote MCP server with the URL above.

**2. Sign in through Crossdeck.** Your AI opens a Crossdeck sign-in page — Google, GitHub, Apple or email, the same account you use in the dashboard. Approve once and the tools appear. The connection is authorized over OAuth 2.1 with PKCE; Crossdeck issues a **read-only, short-lived** token scoped to your workspace that renews automatically and that you can revoke any time from **Developers → Prism**. Your password and keys never reach the AI tool.

**3. Ask Prism.** The connector sees every app in your workspace; switch between them by naming them in chat (it calls `list_projects` and carries the project id through for you).

**Prefer the API?** The connector needs no key. A `cd_wk_` workspace key is only for calling Prism's read API yourself, server-to-server — see [the API reference](https://cross-deck.com/docs/reporting-api/). Create one in **Developers → Prism**.

## The tools

Every tool is read-only (`readOnlyHint`), scoped, and paginated. `list_projects` shows your apps; the rest answer questions about one (pass its project id, which the AI carries through the conversation).

### Portfolio

- `list_projects` — list every app the connector can read (your portfolio). Call it first; the other tools take a project id.

### Revenue & cost

- `get_revenue` — MRR (cents), paying-customer count, per-rail split (Stripe/Apple/Google). Optional daily trend.

- `get_read_cost` — database read-cost split into per-user vs un-attributed overhead, broken down by operation. Per-user attribution exists because Prism joins read-cost to SDK identity.

### Errors

- `get_error_impact` — for one error: how many distinct users hit it, how many of those pay, plus type/status/occurrences/first-last seen. Counts only.

- `get_error_affected_users` identity — the row-level moat: the paying users an error actually hit, each with your own user id + monthly revenue + last-seen, sorted by revenue at risk.

### Customer & analytics

- `get_customer` identity — one customer across every layer Crossdeck joins: what they pay, active entitlements, and their read-cost. Identify them by your own user id, an anonymous id, a Crossdeck customer id, or a rail transaction id.

- `get_host_analytics` — page views + unique visitors for one host/subdomain you own. Optional daily series.

- `get_host_top_pages` — top pages or referrers for one host, paginated.

## Ask Prism — intents

The point is natural language. A few real ones:

- "Prism, compare revenue across all my apps."

- "Prism, which database operation is costing me the most reads in *app-x*?"

- "Prism, this error — which paying customers did it hit, and what are they worth?"

- "Prism, give me the full picture for customer *[id]* — what they pay and what they cost."

- "Prism, show me the people who came through *tenant.example.com*, then this one's journey."

## Prism as an API

The same intelligence is a API your own backend calls server-to-server — to embed Crossdeck's data inside *your* product, or to compute your own metrics (funnels, cohorts) from the raw events. Authenticate with a secret key:

```
curl https://api.cross-deck.com/v1/revenue \
  -H "Authorization: Bearer cd_sk_live_…"
```

Every response carries a `request_id`; errors are typed (Stripe-style). The `/v1` prefix is canonical. Full request/response schemas, error codes, and rate limits are in the [Prism — the API](https://cross-deck.com/docs/reporting-api/index.html) reference.

## Endpoint reference

Endpoint Scope Returns

GET /v1/workspace/projects workspace key Your apps (the portfolio)
GET /v1/revenue revenue:read MRR, paying count, per-rail split
GET /v1/buckets buckets:read Read-cost: per-user vs overhead, by operation
GET /v1/errors errors:read An issue + how many hit / pay (counts)
GET /v1/reporting/metrics reporting:aggregate Per-host views + unique visitors
GET /v1/reporting/breakdown reporting:aggregate Per-host top pages / referrers
GET /v1/reporting/events reporting:aggregate Event counts grouped by a property — project-wide, or per-host with an optional host
GET /v1/errors/affected identity reporting:identity Who an error hit + what they pay (row-level)
GET /v1/reporting/people identity reporting:identity A host's people, newest-active first (paged)
GET /v1/reporting/people/{id}/journey identity reporting:identity One person's event timeline + raw custom-event payload
GET /v1/crossmatch identity crossmatch:read One customer × revenue × entitlements × read-cost

## Security & trust

Prism is built on one bank-grade gate every endpoint inherits. The eight guarantees:

- **Secret-key only.** Publishable keys are rejected — Prism is server-to-server.

- **Scope is the boundary.** The key carries a per-resource scope map, set at mint; the gate denies anything beyond it with `403 insufficient_scope` before reading data.

- **Server-composed scope.** The project comes from the key (or, for a workspace key, a project you own, validated server-side); a host parameter is validated against origins you own. No caller input is a trust boundary.

- **Fail-closed.** Any error denies; partial data is never served.

- **Aggregate by default.** Identity (row-level) is a deliberate, consciously-minted scope; everything else returns counts.

- **Rate-limited** per key, with an enumeration guard (a host you don't own returns 403, never a 404 that confirms existence).

- **Audited.** Every read is logged; identity-tier reads are hash-chained (tamper-evident).

- **Env-isolated.** A production key cannot read sandbox data, and vice versa.

### Key lifecycle — every key, the same net

- **Revoke** (live) — kills a key immediately, fail-closed. The kill-switch for a suspected leak.

- **Rotate** (live) — mints a successor and grace-windows the old key for 7 days, so a swap never causes an outage. Rotation preserves the key's scope.

- **Leak auto-revoke** *(armed; GitHub Secret-Scanning Partner Program enrolment in review)* — once GitHub onboards Crossdeck, an accidental public commit of a `cd_sk_` or `cd_wk_` key is detected and the key is revoked automatically, with a loud owner alert. Until enrolment completes, this layer is built but not yet active.

## For AI platforms

Prism is a hosted, remote MCP server over **Streamable HTTP**, live at `https://api.cross-deck.com/mcp`. Authentication is **OAuth 2.1** to the current MCP spec: RFC 8414 authorization-server metadata at `/.well-known/oauth-authorization-server` (advertising PKCE S256), RFC 7591 dynamic client registration, RFC 9728 protected-resource metadata, and a Crossdeck-branded consent screen. Every tool ships directory-grade metadata: a `title`, an accurate non-promotional `description`, a `readOnlyHint` annotation (all tools are read-only — no read/write mixing), scoped + paginated output, and actionable errors. Each user authorizes their own account, so the connector never sees another tenant's data.

## Related

- [Prism — the API](https://cross-deck.com/docs/reporting-api/index.html) — full API reference: every endpoint, request/response schema, error codes, rate limits.

- [Security & Trust](https://cross-deck.com/docs/outbound-api-security/index.html) — the security model, point for point, for a CTO's review.

- [API keys](https://cross-deck.com/docs/api-keys/index.html) — minting, scopes/permissions, rotation and revocation.
