Docs
Quickstart
Everything below runs against the live API. Keys are issued with waitlist invites while I'm in beta — join here and you'll get one with your invite email.
Prefer not to read docs at all? Point your coding agent at your project with the Plurism skill and it does this whole page for you — behind an approval gate.
01 One key, plain HTTPS
Every service is a resource under api.plurism.dev,
authenticated with a Bearer key scoped per project. Create a support
thread:
curl -X POST https://api.plurism.dev/support/threads \
-H "Authorization: Bearer $PLURISM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "Reset password button does nothing on Safari",
"category": "bug",
"reporter_email": "user@example.com",
"reporter_name": "Alice"
}'
The response includes a ref (like
ACME-42) for a human to quote, and a
lookup_url carrying a capability token. Send the URL,
not the ref: refs are sequential, so the token is what stops one
reporter reading another's thread. On that page they can reply and
attach files.
02 Or the typed SDK
The TypeScript SDK covers support, waitlist, feedback, flags, content, changelog and files. Server-side only — never ship your key to a browser.
Heads up —
@plurism/sdk isn't on npm yet. It ships with your
invite while I'm in beta, and lands on npm at general availability.
The import path below is the shape it'll have either way.
import { createPlurismClient } from "@plurism/sdk";
const plurism = createPlurismClient({
baseUrl: "https://api.plurism.dev",
apiKey: process.env.PLURISM_API_KEY!, // server-side only
});
// Support thread (returns a public ref like ACME-42)
const thread = await plurism.support.threads.create({
body: "Reset password button does nothing on Safari",
category: "bug",
reporter_email: "user@example.com",
reporter_name: "Alice",
});
// Waitlist signup
await plurism.waitlist.add({ email: "early@adopter.dev", referrer: "x" });
// Feedback
await plurism.feedback.submit({ rating: 9, comment: "Love it" });
// Feature flag
const flag = await plurism.flags.evaluate("new-checkout", { user_id: "u_1" });
// Analytics — your own traffic, back out
const { summary } = await plurism.analytics.traffic({ range: "30d" }); 03 Same Cloudflare account? Skip the network
Service bindings are account-scoped, so this applies when your Worker runs in the same Cloudflare account as Plurism — self-hosting, or an arrangement we've set up together. It buys zero-egress, single-digit-ms calls. Everyone else uses plain HTTPS above, which is the normal path:
// wrangler.jsonc — only if your Worker is in the SAME Cloudflare account
{ "services": [{ "binding": "PLURISM", "service": "plurism-api" }] }
// then:
const plurism = createPlurismClient({
binding: env.PLURISM,
apiKey: env.PLURISM_API_KEY,
}); Authentication
One key per project, sent as Authorization: Bearer <key>.
Secret keys (sk_…) are server-side only and unlock the full
SDK. Publishable keys (pa_…) are safe in the browser and carry
only three ingest-side scopes: analytics:ingest,
waitlist:ingest and
feedback:ingest. That is what the drop-in Elements
widgets use, and it is also the key the analytics tracker takes —
analytics never needs a secret key in your pages. Rotating a key is
instant from the admin.
Zero to wired
The agent skill
Plurism ships as a skill for your coding agent. Point it at your project — it reads your stack, proposes the wiring, and only writes the route, the form and the env after you approve. Nothing lands in your codebase without you saying yes.
It's the same three steps above, done for you: pick the service, generate the call in your framework's idiom, drop the key into your environment. The skill is issued alongside your invite while I'm in beta.
What's covered today
-
Support
Threads, replies, statuses, tags, inbound email and a public lookup page. Full REST surface.
-
Analytics
First-party traffic, acquisition, funnel and revenue analytics: a lightweight pixel writes, a dashboard and `plurism.analytics` read. Past your monthly event ceiling, ingest keeps returning 202 but stops storing — watch the usage endpoint.
-
Feedback
0–10 NPS ratings with an optional comment, plus a stats endpoint per project.
-
Feature flags
CRUD plus an edge-cached evaluate with a stable rollout percentage on user_id.
-
Waitlist
Signup, list and invite (fires the invite email); status moves pending → invited → joined.
-
Content
Blog, news, FAQ and how-to served as HTML with schema.org JSON-LD for SEO and AEO.
-
Changelog
A public JSON feed with a 60-second cache — embed it anywhere. Admin CRUD, publish events.
-
Files
Upload and stream in and out; allow-listed content types with an SVG scrub on the way in.
-
Webhooks
HMAC-verified inbound relay and Stripe-style signed outbound, with a retry table for failed deliveries.
-
Notifiers
Rule-based email, Discord and generic HTTP fan-out — SSRF-guarded, with per-event template substitution.
-
Email
Transactional email from your own DKIM-verified domain, on AWS SES. Verify a sending domain in the portal or over the API, then send. Bounce and complaint handling, and a per-project do-not-send list.
Reference
Error envelope
Non-2xx responses carry JSON. Route gates return a flat
{ "error": "message" }; the framework handler
returns { "error": { "code", "message" } }.
The SDK normalises both, so you always read a plain string.
Rate limits
The public Elements endpoints (the <plurism-*>
widgets) are capped per project and return
429 when a window is exceeded. Authenticated API
calls are metered against your plan's quota.
Webhook signing
Outbound webhooks are signed
t=<unix>,v1=<hex> (Stripe-style HMAC).
Verify with verifyWebhookSignature from the SDK and
reject anything more than five minutes old.
Every endpoint is described in the OpenAPI document at api.plurism.dev/openapi.json — no key needed to read it. Point your client generator, your API explorer, or your coding agent straight at it. Anything unclear — ask me, replies usually land same-day.