Bug reporting API
Catch runtime bugs on your website and send them to Sapient for triage and fixing. Drop in ready-made, skinnable bug-report and feature-request widgets. Works on any JS/TS site.
Errors are grouped by fingerprint, de-duplicated, and triaged by your support seat; real regressions become engineering work. User-submitted bugs and feature requests land in the same place, so the roadmap sees what your users actually ask for.
1. Get a publishable key
Section titled “1. Get a publishable key”In your factory Settings → API keys, create a key under Publishable keys (browser). You’ll
get a key that looks like dfpk_…. Copy it now — it’s shown only once.
When you create the key, list the website origins that may send data (e.g.
https://app.acme.com). Requests from other origins are rejected. Leave the list empty only for local
experiments — set it before production.
Publishable keys are safe to ship in your browser bundle (that’s what they’re for). They can only report errors; they can’t read your data. If a key leaks, our backend rate-limits and de-duplicates aggressively so it can’t be used to flood you or us — and you can revoke and re-issue it any time.
2. Install
Section titled “2. Install”npm install @sapient/browser # core (any framework)npm install @sapient/react # + React components (optional)# bun add / pnpm add work tooOr via CDN (no build step):
<script src="https://cdn.sapient.works/browser/v1/sapient.min.js"></script><script>Sapient.init({ key: 'dfpk_…', environment: 'production', release: 'web@2026.06.25' })</script>3. Quickstart
Section titled “3. Quickstart”import * as Sapient from '@sapient/browser'
Sapient.init({ key: 'dfpk_…', environment: 'production', release: 'web@2026.06.25',})That’s it — uncaught errors and unhandled promise rejections are now captured automatically. Report something manually:
try { doRiskyThing()} catch (err) { Sapient.captureException(err, { tags: { feature: 'checkout' } })}
Sapient.captureMessage('payment retried', 'warning')Verify it works: throw a test error (Sapient.captureException(new Error('sapient test'))) and
confirm it appears in your factory’s support surface within a few seconds.
4. Configuration
Section titled “4. Configuration”Sapient.init({ key: 'dfpk_…', // required environment: 'production', // 'production' | 'staging' | 'development' | … release: 'web@2026.06.25', // your build/version, for grouping by release
// capture enableGlobalHandlers: true, // window.onerror + unhandledrejection enableConsoleBreadcrumbs: true, enableNavigationBreadcrumbs: true, enableClickBreadcrumbs: true, maxBreadcrumbs: 30,
// volume controls (protect your users' browsers and your bill) sampleRate: 1.0, // 0..1 — fraction of events sent maxEventsPerSecond: 5, // client-side self-rate-limit batchSize: 10, flushIntervalMs: 5000,
// privacy (see §6) sendDefaultPii: false, denyList: [/x-internal-secret/i], // extra patterns to scrub before send beforeSend: (event) => event, // mutate, or return null to drop
// reliability offlineQueue: true, // persist failed sends, retry on reconnect
// identify the current user (optional) user: { id: 'u_123', email: 'jane@acme.com' }, tags: { tenant: 'acme', plan: 'pro' },})Runtime API: captureException, captureMessage, addBreadcrumb, setUser, setTags, setContext,
flush, close.
Events are batched and flushed on a timer and on page-hide (via navigator.sendBeacon, so the last
errors before a navigation aren’t lost). Failed sends are queued and retried when the user comes back
online.
5. React components
Section titled “5. React components”import { SapientProvider, ErrorBoundary, BugReportWidget, FeatureRequestWidget } from '@sapient/react'
function App() { return ( <SapientProvider options={{ key: 'dfpk_…', environment: 'production', release: 'web@2026.06.25' }}> <ErrorBoundary fallback={({ error, reset }) => <Crash error={error} onRetry={reset} />}> <YourApp /> <BugReportWidget /> {/* floating "Report a bug" launcher + modal */} <FeatureRequestWidget /> {/* "Request a feature" form */} </ErrorBoundary> </SapientProvider> )}ErrorBoundarycatches React render errors and reports them automatically (with the component stack), then shows your fallback.BugReportWidgetis a floating button that opens a form (title, description, reporter email, optional recent-activity capture). Submissions land in your support queue alongside auto-captured errors.FeatureRequestWidgetcollects feature ideas; they’re clustered (duplicates merged, votes counted) and routed to the product roadmap.
The widgets are rendered inside a shadow DOM, so your site’s CSS can’t break them and theirs can’t leak into your site.
6. Theming & customization (skin it for your brand)
Section titled “6. Theming & customization (skin it for your brand)”Every visual is driven by CSS custom properties. Pass a theme (or set the variables on the host) to
match your brand — no CSS overrides needed, no specificity wars:
<BugReportWidget theme={{ '--sap-color-accent': '#6d28d9', '--sap-color-bg': '#ffffff', '--sap-color-text': '#0f172a', '--sap-radius': '12px', '--sap-font': 'Inter, system-ui, sans-serif', }} position="bottom-right" label="Report a bug"/>Defaults ship a clean light and dark theme. For environments where shadow DOM is undesirable, pass
encapsulation="scoped" to use hashed class names instead.
7. Privacy & security
Section titled “7. Privacy & security”- Scrubbing is on by default, both ends. The SDK strips obvious secrets (authorization headers,
cookies, tokens, password-like fields) before sending, and our backend re-scrubs (emails, card
numbers, JWTs, API keys, your publishable key) before anything is stored or shown to a triage agent.
Add your own patterns with
denyList, or transform/drop any event withbeforeSend. sendDefaultPii: falsekeeps user emails/IPs out unless you opt in.- Content Security Policy: allow our ingest host — add
connect-src https://api.sapient.works(and your factory’s API domain) to your CSP.
8. Frameworks & SSR
Section titled “8. Frameworks & SSR”- Next.js / SSR:
Sapient.initis a no-op withoutwindow, so it’s safe to import anywhere; put theSapientProviderin a'use client'boundary. Widgets render nothing until mounted on the client. - Plain
<script>sites: use the CDN build and callSapient.init(...).
9. Troubleshooting
Section titled “9. Troubleshooting”Events not arriving? Check, in order:
- The key is valid and not revoked (Settings → API keys).
- Your site’s origin is in the key’s allowed origins list.
- Your CSP allows
connect-src https://api.sapient.works. - You’re not over the client
sampleRate/maxEventsPerSecond, or the per-key rate limit (a leaked or very busy key gets429s with aRetry-After). - A flood of the same error is de-duplicated — that’s expected; you’ll see one grouped issue, not thousands.
10. Related
Section titled “10. Related”- API keys — publishable vs secret, revocation, rate limits.
- Errors and limits — the shared error shape,
429handling, body caps. - Contacts API — the server-side API, for when you need to write data rather than report errors. It uses a secret key, and a publishable key will not work there (nor will a secret key work here).