The official, auto-generated TypeScript client for Sentry's public REST API.
npm install @sentry/apiPass baseUrl and an auth header to each call:
import { listYourOrganizations } from "@sentry/api";
const { data, error } = await listYourOrganizations({
baseUrl: "https://sentry.io",
headers: { Authorization: `Bearer ${process.env.SENTRY_AUTH_TOKEN}` },
});
if (error) throw error;
console.log(data);Auth tokens and base URLs (including self-hosted and region URLs) are documented at https://docs.sentry.io/api/auth/.
The root @sentry/api entry has no runtime dependencies. It provides the API client and pure TypeScript types without installing a validation library.
Valibot 1 runtime schemas are available through a separate optional entry point:
npm install @sentry/api valibotimport * as v from "valibot";
import { vGetProjectResponse } from "@sentry/api/valibot";
const project = v.parse(vGetProjectResponse, input);The existing Zod 3 entry remains supported:
npm install @sentry/api zodimport { zGetProjectResponse } from "@sentry/api/zod";
const project = zGetProjectResponse.parse(input);valibot and zod are optional peer dependencies. Install neither when you only need the generated client and TypeScript types, or install the validator used by your application. The @sentry/api/valibot entry requires Valibot 1; its optional peer uses a wildcard because npm applies peer constraints to the whole package, including consumers that never import this entry.
Every operation with documented error responses has a generated narrowError_<operation> wrapper. It returns data or a SentryApiError that preserves the operation's status-to-body type map:
import { narrowError_getProject } from "@sentry/api";
const result = await narrowError_getProject({
baseUrl: "https://sentry.io",
headers: { Authorization: `Bearer ${process.env.SENTRY_AUTH_TOKEN}` },
path: {
organization_id_or_slug: "my-org",
project_id_or_slug: "my-project",
},
});
if (!result.ok) {
if (!result.error.documented) {
// Unexpected HTTP status or a transport failure.
throw result.error;
}
switch (result.error.status) {
case 403:
case 404:
throw result.error;
}
}Checking documented first separates the operation's finite error union from unexpected statuses and transport failures. Within the documented branch, checking status narrows body to that response's schema. Error bodies remain unknown where the source OpenAPI response has no schema.
Sentry uses cursor-based pagination via Link headers. Every operation in the SDK that accepts a cursor query parameter has three auto-generated typed wrappers:
fetchPage_<operation>(options, cursor?)— fetch a single page; returns{ data, nextCursor?, prevCursor? }.paginateAll_<operation>(options, paginateOptions?)— eagerly fetch all pages, returning the concatenated array. Bounded bymaxPages(default 50) for safety. Available only for endpoints whose 200 response isArray<...>.paginateUpTo_<operation>(options, paginateOptions)— fetch up to a hardlimitof items; suppressesnextCursorwhen the last page is trimmed (so callers resuming pagination won't skip records). Available only for endpoints whose 200 response isArray<...>.
The wrappers manage cursor for you — passing one in query is a type error. Every wrapper's query is also widened with an optional per_page?: number field, since Sentry's pagination framework accepts per_page on every cursor-paginated route at runtime even when the spec omits it.
import { fetchPage_listAnOrganization_sIssues } from "@sentry/api";
const { data, nextCursor } = await fetchPage_listAnOrganization_sIssues({
baseUrl: "https://sentry.io",
headers: { Authorization: `Bearer ${process.env.SENTRY_AUTH_TOKEN}` },
path: { organization_id_or_slug: "my-org" },
query: { collapse: ["stats"], limit: 25 },
});import { paginateAll_listAnOrganization_sProjects } from "@sentry/api";
const projects = await paginateAll_listAnOrganization_sProjects({
baseUrl: "https://sentry.io",
headers: { Authorization: `Bearer ${process.env.SENTRY_AUTH_TOKEN}` },
path: { organization_id_or_slug: "my-org" },
});import { paginateUpTo_listAnOrganization_sIssues } from "@sentry/api";
const { data, nextCursor } = await paginateUpTo_listAnOrganization_sIssues(
{
baseUrl: "https://sentry.io",
headers: { Authorization: `Bearer ${process.env.SENTRY_AUTH_TOKEN}` },
path: { organization_id_or_slug: "my-org" },
query: { limit: 100 },
},
{
limit: 250,
onPage: (fetched, target) => console.log(`fetched ${fetched}/${target}`),
},
);By default, paginateUpTo drops nextCursor if the last fetched page had to be trimmed to fit limit — returning a cursor that points past the trimmed items would cause callers resuming pagination to skip records. For endpoints with no server-side per_page control (e.g. /issues/{id}/events/), pass keepCursorOnOvershoot: true to preserve the cursor; the trimmed-tail items remain reachable via the same cursor on the next call.
nextCursor is also dropped if paginateUpTo reaches maxPages (default 50) before fulfilling limit — raise maxPages to continue paginating.
The same low-level helpers used by the generated wrappers are also exported for advanced use cases:
parseSentryLinkHeader(header)—{ nextCursor?, prevCursor? }unwrapResult(sdkResult, context)— throw-on-error data unwrapunwrapPaginatedResult(sdkResult, context)— same but with cursorsfetchPage,paginateAll,paginateUpTo— generic versions taking a fetcher thunk
The OpenAPI schema is synced from getsentry/sentry. Schema fixes belong there; build/tooling changes belong here.
FSL-1.1-Apache-2.0. See LICENSE.md.