# Tracebird — SDK & API documentation (for LLMs) > Tracebird is a tester-feedback SDK for web and Flutter (iOS/Android). Testers > click a floating widget, optionally annotate a screenshot, write one > sentence and send. Every report automatically ships with console logs, > network calls, JS errors, navigation breadcrumbs, environment info, a > gzipped rrweb DOM snapshot, and — during a test session — a full session > recording (DOM mutations, scroll, mouse trail). Reports land in a > dashboard inbox; issues are created on GitHub/Linear/Jira from there. ## Install Script tag (any stack — the file is an ES module): Or via npm: npm install @tracebird/web import { init } from "@tracebird/web"; init({ projectKey: "pk_live_..." }); Call init() as early as possible: buffers only capture what happens after installation. Call it once, not per route. ## init(options) | option | type | default | notes | |-------------|--------|--------------------------|-------| | projectKey | string | required | public key from project Settings | | endpoint | string | https://api.tracebird.dev| ingest base URL (self-hosting) | | environment | string | — | free-form label (staging, production…) | | release | string | — | app version, used for regression tracking | | tester | string | — | optional name/email; testers never need accounts | The project key is public by design. Abuse is contained server-side: per-project Origin allowlist (403 for unknown key OR bad origin — indistinguishable on purpose), rate limiting per identified caller with a per-IP backstop for anonymous traffic, 8 MB body cap. IMPORTANT: every domain testers use (including localhost:PORT and preview deploys) must be added to the project's allowed origins, or reports fail 403. ## JavaScript API - init(options): void — installs capture, mounts the widget, resumes an in-flight session after a page load. Idempotent. - startSession(): Promise — starts a test session (loads the recorder chunk on demand, shows a pulsing REC badge with a live timer). - endSession(): void — stops and discards. Rarely needed: sending a report ends the session automatically and attaches the recording. Available as ESM exports or on window.Tracebird when loaded via script tag. Lazy loading: core ~11 KB gz on load; rrweb recorder ~82 KB gz fetched on session start; screenshot/annotation editor ~8 KB gz on "Capture & annotate"; DOM snapshot module ~24 KB gz at send time. Chunks resolve relative to tracebird.js — when self-hosting, serve the whole dist/ folder. ## What a report contains (caps enforced server-side) Always: console ring buffer (100 entries, 500 chars each) · network (50 requests: method, url, status, ms — NEVER bodies, auth headers scrubbed) · JS errors (20) · navigation breadcrumbs (30 routes) · environment (viewport, browser, language, timezone, UA, connection) · gzipped rrweb DOM snapshot (≤ 800 KB, inputs masked, skipped if over cap). On demand: annotated screenshot (JPEG ≤ 3 MB, blur regions pixelated client-side BEFORE upload) · vector annotations (≤ 200 shapes: brush with point list, arrow, rect, blur) · session recording (gzipped rrweb event stream ≤ 3 MB, merged across page loads) · click journey (≤ 200 timestamped clicked elements). Never captured: request/response bodies, input values (masked at source), passwords (always masked, no opt-out), cookies, storage, auth headers, anything under a tester's blur. ## Test sessions Start from the widget panel ("Start test session") or startSession(). While active: pulsing REC badge with timer on every page; rrweb records DOM mutations/scroll/mouse (mousemove sampled 40 ms); clicks are logged as a readable journey. Sessions persist across full page loads via sessionStorage (segments gzipped per page, merged at send). Sending a report ends the session and ships the recording; a failed send keeps it running. Limits: 20 000 events/page, 3 MB gz recording, 200 clicks. ## Flutter SDK (iOS & Android) flutter pub add tracebird_flutter await Tracebird.init( projectKey: 'pk_live_...', trigger: TracebirdTrigger.shake, // shake | floatingButton | manual capture: TracebirdCapture(logs: true, network: true, breadcrumbs: true), privacy: TracebirdPrivacy(maskWidgets: true, scrubHeaders: ['authorization']), ); runApp(TracebirdWrapper(child: MyApp())); - Add the app's bundle IDs (com.acme.app) to the project allowlist — the mobile equivalent of web origins. - Wrap sensitive UI in TracebirdMask(child: ...) — blanked at capture time on the device. - Manual trigger: Tracebird.report(type: FeedbackType.bug). - Platform views (WebView/Maps/camera): measured, iOS needs a native capture fallback (UIGraphicsImageRenderer + drawHierarchy) because RepaintBoundary leaves a hole; Android needs none because platform views are composited into the Flutter scene. Automatic, no configuration. FLAG_SECURE content is still uncapturable on Android — the report goes without a screenshot. - No runtime dependencies: device info, cache dir, shake detection, capture and JPEG encoding go through the plugin's own platform channel. - Offline: reports persist locally and replay on reconnect with an idempotency key (no duplicates). - Context: debugPrint logs, Dio interceptor for network, NavigatorObserver breadcrumbs, device model/OS/app version, Tracebird.addMetadata(). - Web and Flutter reports share one inbox (filter by platform). ## Ingest HTTP API POST {endpoint}/v1/ingest/feedback Headers: Content-Type: application/json; Origin must match the allowlist. { "projectKey": "pk_live_...", // required, 8-64 chars "type": "bug" | "idea" | "question",// default "bug" "comment": "...", // required, 1-4000 chars "tester": "...", // ≤ 120 chars "release": "...", "environment": "...", // ≤ 50 chars each "route": "/checkout", // ≤ 500 chars "context": { ... } // validated field-by-field; unknown keys stripped } Responses: 202 {"id": ""} · 400 validation (first bad field named) · 403 unknown key or origin not allowlisted · 413 body > 8 MB · 429 rate limited. Server-to-server callers must still send a matching Origin header (add e.g. ci.acme.dev to the project). ## AI triage & dedup (automatic, server-side) Every ingested report is analyzed by Claude: generated title, severity (low/medium/high/critical) + reason, repro steps inferred from the navigation trail, expected/actual, and a suspected cause quoting the decisive log line or failed request. Reports describing the same underlying defect are grouped (duplicate_of). Results appear in the dashboard and via the MCP server; analysis is asynchronous (a report may briefly show "analyzing"). ## MCP server MCP over Streamable HTTP at https://api.tracebird.dev/mcp, auth via "Authorization: Bearer ". Tools: list_projects, list_reports(project, status?, limit?), get_report(id) — full context incl. logs/network/errors/comments, update_report(id, status?, assignee?), add_comment(id, body, author?). Claude Code: "claude mcp add --transport http tracebird --header ...". ## Privacy summary Masking by default (inputs, passwords), no network bodies ever, blur destroys pixels client-side, recording is always visibly indicated (REC badge), unlimited reports with AI triage metered per month (50 free, 2,000 indie, 10,000 studio) — reports are never refused, only the analysis pauses, captures in a private bucket served through short-lived signed links, project deletion cascades immediately. Docs: https://tracebird.dev/docs