Repository navigation
Description
@sentry/api should be a stable, supported foundation for the Sentry frontend, CLI, MCP server, and external developers building on the Sentry API. Each consumer should configure its deployment and authentication once and reuse shared request mechanics without rebuilding Sentry-specific plumbing.
Status updated 2026-11-05: the package is already on 1.x; the Zod 4 migration in #127 introduced the major-version break. This issue retains the adoption and compatibility acceptance criteria originally named v1.0.0. Publishing 1.x does not mark the remaining gates complete. The package version is independent of the backend API's /api/0 version.
The current routing plan is #81. Build on current main, including the shared client and per-request URL resolver. The closed #78/#79 stack and the uncommitted October gateway prototype are historical inputs, not the delivery architecture.
What already exists
Build on these merged contracts; do not reimplement them inside routing:
-
Configured clients and responses: object methods #98, response/error contract #104, cancellation foundation #105, and shared raw request preparation #117. Standalone operations remain supported.
-
Pagination: original primitives/wrappers feat: bundle pagination utilities into the SDK entry point #61/feat: auto-generate typed pagination wrappers per operation #69/feat(pagination): export SdkResult type for consumer use #74, bound helpers and bounded-collection contracts #100/#101, partial-page continuation and pure consumption #116, with short-page coverage #118. These address the missing continuation mechanism; consumer bookmark/adoption gates remain separate.
-
Discovery and generated metadata: named enum query types #108, operation catalog #110, idempotence #111, build-time source analysis #115, and validator descriptions #128. Backend routing metadata is merged in sentry#127778; consuming it in request routing remains open.
-
Shared request layer: #122 supplies
@sentry/api/clienttransport/core, retries, credential refresh, errors, response-cache policy and pagination with host-owned storage/credentials. Toolkit #1942 adopted it for CLI/MCP and deleted the Toolkit copy; #1961 removed further duplicated helpers. #129 adds request scope to credential selection and #130 adds per-requestresolveBaseUrlto generated preparation. Neither path scope alone nor a URL hook supplies authoritative silo classification. -
Behavior and package/tooling: event query defaults #112/#113, tree shaking/lazy default client #120, bounded-int64 normalization #123, Hey API 0.98/security update #124, pnpm/Node/esbuild/Vitest and browser portability checks #126, optional Zod 4 #127, and Craft release checks #121. Browser cookie/CSRF support feat: add @sentry/api/browser entry point for cookie+CSRF auth #73, optional Valibot feat: add Valibot validation schemas #90 and serialized releases fix: serialize release workflows #89 remain available.
-
Build pipeline: #131 merged on 2026-11-05. It runs generators in one process with shared
emit({ sourceSpec, normalizedSpec })inputs and patch helpers; it does not change routing semantics. The current metadata-routing implementation uses that pipeline and its helpers, preserving identical generated runtime/types while avoiding duplicate schema reads or patch helpers. Package 1.29.0 includes the feat(client): Pick each request's base URL from its path with resolveBaseUrl #130 hook; use it as the current published baseline in addition to the version declared by each consumer.
The historical shared-client design records background, not the current API surface. Merged primitives and CLI/MCP library adoption are progress, not proof that every workflow gate below is complete.
Implementation order
- Backend/OpenAPI metadata — complete: declared silo availability and the actual organization path parameter are exported by HTTP operation, including explicit unknowns. No runtime routing or publication changes.
- Current SDK routing slice: consume that metadata through the existing per-request URL-resolution path from feat(client): Pick each request's base URL from its path with resolveBaseUrl #130. Reuse feat(client): Move the shared API client from toolkit into @sentry/api #122's shared client/transport and caller-owned locality state. Preserve explicit destinations,
bothsemantics, unknown/private fallback, trust, authentication context, cancellation andprepareRequest. Do not add another cache, retry loop or redirect engine. - Current consumer validation and simplification: exercise CLI, MCP and frontend using their current implementations and a current SDK baseline. Reuse CLI memory/SQLite, MCP verified/request-local metadata and frontend
ConfigStore. Require equal or fewer client requests, preserved cache behavior/results/errors/cursors/headers, identity isolation, and no newly serialized independent work. Show actual routing plumbing removed in an adoption diff. Reassess Toolkit #1502 and #1508 against what has already merged; neither historical PR is a prerequisite. - Separate follow-ups: opt-in built-in discovery with bounded memory for consumers without locality infrastructure, frontend runtime adoption under Integrate the SDK runtime with frontend apiOptions and RequestError #103, and gateway locality learning in its own PR. The current routing slice excludes gateway response-header learning and requires no companion gateway rollout.
#81 owns the detailed routing contract and acceptance matrix. #78/#79 are closed; there is no old auth → routing → progressive-accuracy stack to preserve. Existing supported gateway dispatch remains available without mandatory discovery; the deferred gateway optimization is a different feature.
#92 remains a contract/acceptance review over the retry/cache mechanics now shipped in #122. Reconcile its older minimal GET/HEAD sketch with the explicit shared transport policy; do not silently narrow that policy or install a second retry owner in this routing change. Per-call no-replay/no-store propagation and integrated acceptance remain to be verified. #99 now includes the delivered continuation mechanism from #116 while consumer pilots remain open.
Toolkit #1669 is an open docs-only CLI-first MCP proposal, not a shipped architecture. Keep request-scoped, stateless hosted usage possible without requiring SQLite, a filesystem, KV or another database. Command selection/execution and MCP permission exposure stay outside this SDK.
Cancellation delivery plan and consumer evidence
The #95 plan records the original consumer investigation. The SDK foundation #105 and shared transport #122 are merged. Treat the old gap descriptions as investigation history; verify current integrations rather than assuming the same adapter bugs remain.
A reusable client receives a separate signal per operation. Cancellation must not leak to sibling calls or be stored in a query key/global controller. Routing, raw preparation, resource dispatch, response body reads, pagination and retry waits must compose with that signal; an arbitrary custom hook/transport still owns cooperative cancellation.
- CLI / Toolkit: preserve credential/cache/deadline policy and shared OAuth refresh. Verify the supported CLI invocation paths stop their work; do not infer universal command cancellation solely from the streaming API's signal.
- MCP / Toolkit: verify protocol
extra.signalreaches invocation context, API methods and SDK/raw transports, including polling/retry waits. Suppressing a late protocol response does not prove work stopped. Preserve concurrent identity isolation in Workers. - Frontend Integrate the SDK runtime with frontend apiOptions and RequestError #103: forward TanStack's real
context.signalcentrally throughapiFetch/apiFetchInfinite, preservingapiOptions, the actualRequestErrorand cache metadata. Verify cancelQueries, observer unmount, infinite refetch and waiting for sudo, without per-component plumbing or cancellation-triggered retry/toast. Consuming the signal changes unmount/cache-completion behavior and needs explicit validation. Generate API operation mappings for frontend apiOptions inference #102 remains independent type-only adoption.
Preserve #104 error semantics and native reason behavior; do not require signal-object identity or convert aborts into HTTP errors. Keep one retry owner and verify cancellation stops both requests and waits. Generated SSE reconnect behavior remains a separate explicit coverage decision.
Historical October probes, including local workerd redirects, establish specific fixture behavior only. They do not validate current consumer commits, production OAuth, deployed Workers, browser login/sudo or live tenants. Record exact SDK/consumer revisions with new evidence.
Frontend adoption: preserve apiOptions and RequestError
The acceptance target is no additional infrastructure code in a migrated query or component. Keep apiOptions as the frontend entry point and retain the actual RequestError; retiring that class is not required.
Phase A — generated contracts, existing execution
#102 exports a type-only operation map by endpoint + HTTP method and connects it once to existing apiOptions / infinite options. Resolve frontend/OpenAPI route and parameter naming centrally. Infer covered inputs/responses; retain .as<T>() and private/unsupported endpoint fallback.
apiOptions + SDK-generated contracts
↓
existing apiFetch → frontend Client → existing RequestError
This preserves current query keys, cache, auth/sudo/routing, retries, and form handling without error conversion. It can proceed alongside #94/#95/#92; those are runtime-contract dependencies, not prerequisites for type-only adoption. The generic TanStack plugin is not required.
Phase B — runtime integration in shared infrastructure
#103 introduces SDK runtime mechanics behind the existing frontend abstraction. The SDK team supplies and tests reusable response/error adaptation; feature teams must not write WeakMaps, clone responses, repeat an endpoint and SDK operation, or add converters to each query.
Preserve {json, headers, status?}, selectors, invalidation, pagination, and the frontend's real RequestError. Keep login/SSO, sudo, allowAuthError, app routing context, telemetry, and presentation policies in shared frontend infrastructure. A small optional compatibility module may accept the actual error constructor, but do not freeze the earlier illustrative helper names or copy the entire frontend client into the SDK.
Phase B consumes the relevant #94, #95, #92, and auth/browser/routing contracts and validates #99's table/infinite-query behavior. The frontend keeps one retry owner, normally TanStack.
Acceptance boundary: Phase A is useful adoption of generated contracts, not evidence of SDK runtime adoption. Phase B must still satisfy the frontend workflow gate below. The local mocked 403/RequestError/TanStack probe establishes feasibility only; it is not browser/auth/sudo/cancellation validation.
Remaining adoption and compatibility gates
1. A coherent public client and package contract
- Settle and document configuration, authentication, routing, transport composition and per-call overrides on the current root client plus optional
@sentry/api/clientlayer. Reuse feat(client): Move the shared API client from toolkit into @sentry/api #122/feat(client): Pass the request's org scope to CredentialProvider.current #129/feat(client): Pick each request's base URL from its path with resolveBaseUrl #130; keep authentication and routing independently composable. Closed feat: SDK auth/client config factories (bearerToken, browserSession, createSentryClient) #78 is not a dependency. - Complete #92 acceptance using the shipped shared transport, including per-call no-replay/cache controls and override propagation. Root generated requests remain single-attempt unless composed with a retrying transport. Preserve host credentials/storage and one retry owner; distinguish fresh/reload reads, which can update cache, from no-store reads, which must bypass both lookup and storage.
- Support isolated deployment/authentication contexts without requiring a global singleton. Concurrent clients must not share credentials, routing state, or mutable defaults.
- Preserve explicitly configured SaaS, regional, dedicated, custom-domain, and self-hosted origins. Do not infer a different deployment from a hostname suffix. Document supported URL shapes, local-development HTTP behavior, and server-version assumptions.
- Keep the root entry usable without React or validator dependencies. Optional browser/validator/query integrations must have explicit dependency and runtime boundaries.
2. Shared routing based on authoritative operation metadata
- Export routing metadata from the backend into OpenAPI, including reliable legacy mappings and explicit unknowns: sentry#127778. Metadata identifies the HTTP operation, declared silo availability and actual organization parameter without changing publication/runtime behavior.
- Preserve and expose those facts in the current generated SDK and operation catalog. They require no runtime metadata request. Availability alone does not imply equivalent
bothsemantics, effective method behavior inside a handler or universal gateway support. - Classify generated requests from that metadata through the current per-request URL-resolution path. A concrete-path lookup must match a known operation; feat(client): Pass the request's org scope to CredentialProvider.current #129/feat(client): Pick each request's base URL from its path with resolveBaseUrl #130 path scope alone cannot infer a silo. Organization-scoped operations can belong to control. Retain explicit fallback for raw/private/unmatched paths.
- Distinguish control requests, regional data requests, and operations valid in both contexts. For example, listing organizations has different control and cell implementations;
bothdoes not mean the hosts are interchangeable. Preserve explicit caller context and define precedence. - Reuse current generated request preparation and URL resolution with a typed operation-context contract. Execute routing once for bound/standalone operations and
prepareRequest, preserve signal/interceptor ordering, and avoid per-call metadata annotations or a competing resolver API. - Support a known locality URL without discovery or additional requests. Use backend-provided public URLs, not private cell addresses or constructed region hostnames.
- Keep existing supported gateway dispatch available without mandatory discovery/fanout. Preserve configured context for missing metadata and legacy resource-ID paths; a control-origin fallback is not universally sufficient. Gateway locality learning and its backend headers/rollout remain a separate optional PR, excluded from the current routing slice.
3. Explicit ownership of discovery, cache, and destination trust
- Provide opt-in built-in discovery in a separate slice for consumers that do not already know locality and have no resolver. Current adoption can reuse existing consumer resolvers; the default request path must not acquire mandatory lookup latency.
- Scope SDK-managed discovery state to deployment, authentication context, and organization. Use bounded instance-owned memory with finite TTL and explicit invalidation/reconfiguration. Deduplicate concurrent lookups and evict failed lookups. Reusing a client in a long-lived process retains its cache across calls; a new instance/process is independent. Provide sensible defaults. Do not cache missing metadata forever. No process-global or persistent cache by default.
- Let consumers supply existing metadata or a resolver. Reuse frontend bootstrap/page-memory
ConfigStore, CLI memory/SQLite, and already-verified MCP request metadata. Do not add a second locality cache or require durable storage in Workers. Distinguish metadata-only lookup from HTTP discovery, and locality storage from the shared HTTP response-cache policy. A known locality applies to its organization/auth/deployment context, not every organization accessible to the credential. - Select and validate the destination before credential selection, response-cache identity and dispatch. Additional origins follow an explicit trust policy supporting dedicated/self-hosted deployments; no loose suffix trust. Cover discovery, explicit overrides and URL transforms. Reuse the shared redirect mechanism with its existing opt-in semantics; final-response locality validation cannot protect an earlier redirect hop.
4. A reusable browser transport with a proven frontend integration
- Verify the browser helper and current shared transport compose with injected fetch, instrumentation and request interceptors. feat(client): Move the shared API client from toolkit into @sentry/api #122 documents
createApiTransport({ fetch: createBrowserFetch(), ... })and build: Move the build and tests from Bun to pnpm and Node.js #126 adds portability checks; neither alone establishes Sentry frontend runtime adoption or browser login/sudo behavior. - Select the destination, apply URL transformations, validate the final origin, and then attach applicable CSRF/authentication data before dispatch. Preserve method, body, headers, and cancellation signal throughout.
- Preserve explicit-host precedence, multi-region-disabled behavior, admin proxy behavior, and development proxy rewrites in the Sentry integration. The frontend supplies application context; the package must not import Sentry stores, React routes, or dev-server globals.
- Share routing mechanics for schema-covered operations while retaining a documented adapter for private or unsupported operations. The public OpenAPI schema cannot replace the frontend's entire internal route catalog.
5. Usable schemas, errors, pagination, and query integration
- Audit the real requests and responses used by the adoption workflows: path/query/body parameters, datasets, response metadata, nullability, pagination, and common errors. Fix supported API gaps upstream rather than relying on casts or editing generated output.
- Complete Align responseStyle types and stabilize SDK error contracts #94's response/error foundation in #104: reusable default HTTP errors and explicit opt-in narrowing, accurate absent-response types, original text/parsed body and response metadata, and preservation of intentional consumer errors. Do not treat cancellation, decoding, or arbitrary custom-fetch exceptions as interchangeable network failures.
- Preserve access to the HTTP response and relevant headers. Frontend integration must retain its
{json, headers, status?}cache contract, includingLink, hit counts, andX-Sentry-Direct-Hit, or provide a deliberate migration for all affected readers/writers. - Reuse the existing Link-header parser and pagination primitives. Verify query keys, cache isolation, infinite pagination, invalidation, optimistic updates, and AbortSignal propagation in an actual frontend workflow.
- Keep login, SSO, sudo, credential storage/refresh, UI messages, CLI exit codes, and MCP tool presentation with consumers. Adapters must preserve these behaviors. In particular, changing the error class must not silently change frontend retry decisions.
- Keep a documented generic request path for operations outside the generated surface, with consumer-owned validation. Decide API publication with endpoint owners; do not publish private identity/internal endpoints merely to remove an adapter.
- Use canonical
permalink,webUrl, andorganizationUrlvalues for navigation. Do not derive product links from the regional API origin or duplicate the frontend's route catalog in the SDK.
6. Stable releases and verified package compatibility
- Maintain a documented public surface, supported runtime/module-resolution matrix, optional peers and experimental-operation policy for the published 1.x package. Provide migration guidance, including the optional Zod 4 break, without treating version numbering as closure of these gates.
- Detect schema/codegen changes that remove or rename exports, narrow accepted inputs, change response/error contracts, or break validators. Review their versioning impact before publishing. Currently
Generatedcommits are classified as minor releases; that alone cannot enforce v1 compatibility. - Continue packed-artifact validation in clean supported consumers: Node ESM/NodeNext, browser bundling/runtime and any claimed Bun compatibility. build: Move the build and tests from Bun to pnpm and Node.js #126 now builds/tests with pnpm/Node/esbuild/Vitest and includes browser portability checks; older Bun/build diagnostics are historical, not automatically current failures. Verify published declaration resolution and portable fetch signatures without requiring runtime-specific helpers or unrelated DOM/validator dependencies.
- Compile documented examples against packed public entry points. Verify root/browser consumers without validator peers, optional Valibot independently, and Zod 4.6.6+ independently. Retain feat(build): Make validator schemas and the default client tree-shakeable #120 tree shaking/lazy initialization and feat(validators): Attach OpenAPI descriptions to Valibot and Zod schemas #128 schema descriptions/top-level Valibot compatibility; new routing must not introduce eager transport/catalog dependencies.
- Verify release-candidate publication, upgrade behavior, changelog/deprecation guidance, and release ownership. Review generator upgrades against the public contract rather than treating them as ordinary dev-dependency bumps.
Adoption evidence still required
Track concrete consumer PRs and validation results here. Toolkit #1942/#1961 establish shared-library adoption for CLI/MCP. The remaining routing and workflow gates need current evidence; the October prototype does not validate later integrations. Each first-party consumer must complete a meaningful integrated workflow, and external usability must be demonstrated outside the Sentry monorepos. Complete migration of every consumer is not required, but isolated SDK tests are insufficient.
| Consumer | Required evidence |
|---|---|
| Sentry frontend | Phase B: regional read, control request, paginated query, and a related mutation/cache update using the SDK runtime through shared infrastructure. Preserve apiOptions, the actual RequestError, existing cache/keys/selectors, and no extra per-component plumbing. Verify browser auth, auth-error/sudo handling, retry behavior, cancellation, and admin/dev proxy compatibility. Phase A type inference alone does not meet this gate. |
| CLI | A real command uses configured client instances and generated operations without repeating host/auth or casting around schema gaps. Verify deployment selection, pagination, error mapping, and composition with existing credential/transport policy. Include the #92 preflight/mutation flow: explicit no-store reads bypass cache lookup and storage, reload/fresh reads retain their documented cache-write policy, and a no-replay mutation is not repeated after failure or 401. Verify a single retry owner after adoption and cancellation through the supported adapter paths, without claiming universal command cancellation from the streaming-only public signal. |
| MCP | A real tool flow uses an isolated client per deployment/auth context. Verify concurrent organizations and credentials, trusted regional destinations, dedicated/self-hosted hosts, and correct web links. Connect protocol cancellation to per-invocation API work and verify cancellation stops transport, pagination and waits while preserving concurrent calls. Remove only adapters whose guarantees the SDK actually replaces. |
| External developer | A standalone example/application installs the packed release candidate and performs a typed read, pagination, and a supported mutation. Demonstrate custom configuration and optional validation without first-party stores, wrappers, or private imports. |
- Link Phase A generated-contract adoption and compile-time validation.
- Link Phase B frontend runtime adoption and integrated validation; this is the required runtime gate.
- Link shared-client CLI/MCP adoption and deletion of the duplicated Toolkit layer: #1942, follow-ups #1961. This does not close the routing or end-to-end gates.
- Link current CLI routing/workflow validation, including actual deleted call-site plumbing, request counts, cache-hit behavior and concurrency.
- Link current MCP routing/workflow validation, including request-scoped identities and Workers execution without mandatory persistence.
- Link standalone external-consumer validation and the supported runtime/deployment matrix. Distinguish mocked contract checks from real deployment/browser verification.
Existing backlog and scope decisions
| Work | Current treatment |
|---|---|
| #81, #130 | Extend the merged per-request URL hook with authoritative operation context and shared-client composition; preserve existing consumer locality/cache ownership. |
| #78, #79 | Closed without merge; historical designs, not prerequisites. |
| #71 | Reconcile with current backend/schema and fix remaining adoption blockers. meta.units is already present; older dataset names in the issue must be revalidated. |
| #91 | Triage each remaining gap as a supported public API, replacement/migration, or intentional consumer adapter. Some listed gaps have already landed; closure of every listed internal route is not a v1 condition. |
| #76 | Ensure stable exported names and accurate docs for supported operations. Full legacy-docs migration is separate and must not silently change publication policy. |
| #77 | Its 0.97.3 proposal is superseded by the merged 0.98.0 upgrade in #124. Maintain generator-contract checks on current tooling; do not block routing on this old PR. |
| #88, #121 | Ownership and release tooling are merged; maintain accountability and compatibility checks for future releases. |
| #80 | Decide separately whether to ship shared progressive accuracy. Its historical stack description is obsolete; it remains independent of routing and transport retries. |
| #102 | Generate SDK contracts for existing frontend apiOptions; retain current runtime and errors initially. |
| #103 | Required frontend runtime pilot and shared compatibility integration; preserve current DX and policies. |
| #92 | Shared retry/cache mechanics now exist in #122. Reconcile the older policy sketch and verify no-replay/no-store/reload controls, budgets, cancellation and composed consumer acceptance; do not build another transport. |
An optional generic TanStack Query entry remains a candidate for external applications after the reusable contract is established. It is distinct from integrating SDK contracts into Sentry's existing apiOptions and is not a prerequisite for Phase A. The stock generator drops response headers and uses different query keys; enabling it alone does not satisfy frontend readiness. A standalone bindings package, full internal-route coverage, and full consumer rewrites are not prerequisites if the required integration contracts above are delivered and exercised.
If progressive accuracy ships, its sampling parameters and partial-scan metadata must be typed and its escalation behavior explicit. The remaining #92 acceptance covers eligible failures/methods, budgets, cancellation, per-call precedence and consumer composition over the shared transport. Do not silently change its shipped policy in routing or add a second retry loop; explicit no-replay must retain its intended guarantees.
Close the remaining checklists only with linked current evidence, and explicitly record optional features as included, experimental or deferred. Published 1.x versions do not retroactively establish frontend/external adoption, universal routing parity or gateway readiness.
Activity
feat: add configured clients with bound API methods (#98)
feat: bind pagination helpers to configured clients (#100)
feat: report pagination limits and resize safe requests (#101)
fix: stabilize SDK response and error contracts (#104)
fix: preserve cancellation before SDK fetch dispatch (#105)
feat(api): export OpenAPI routing metadata (getsentry#127778)
feat: export a generated operation catalog (#110)
feat(pagination): resume partially consumed pages (#116)
feat(client): expose shared request preparation (#117)