Skip to main content
The read API returns the same data the console shows: release health and comparisons, issues, sessions, vitals and cohort comparisons. Agents and scripts use it too, and the MCP server is built on it. It is a preview (v0): fields may change before 1.0.

Base URL and description

The API reference in these docs is generated from that document: every endpoint, with its parameters and response fields.

Authentication

Send a project token as a bearer token:
A project token reads exactly one project and expires after at most 7 days. A token used on another project’s path gets 403, and a revoked token gets 401. The console calls the same endpoints with your session cookie instead: it reads every project of the organizations you belong to, and any other project gets 403. Issuing project tokens from the console is not available yet. An OAuth access token from Apsio’s sign-in (WorkOS AuthKit) issued for the API (https://api.apsio.io) reads what its user can read, like the console session: memberships are checked on every request, so a person removed from an organization loses its projects at once. A token that names an organization (org_id) reads only that organization. Tokens issued for the MCP server work only through the MCP server, which passes them on with its own credential; sent to the API directly they get 401, like a token for any other audience. Every request with a project token or an access token, directly or through the MCP server, is written to the organization’s audit log before anything is read, with the user or the project token’s id (never the token), the route and, from the MCP server, the tool. If the entry cannot be written the request fails with 503 and reads nothing. Requests from the console, with your session, are not agent calls and are not written. The entries are in GET /v1/orgs/{orgId}/audit with the action agent.call. GET /v1/projects lists the projects your credentials can read, with their apps: a project token’s one project, or every project of your organizations.
When you run the Apsio service locally from its repository, mint a project token with pnpm --filter @apsio/api token <project id> [ttl seconds], which signs it with the API_TOKEN_SECRET of your environment. This is an operator tool for local and self-hosted stacks, not how customers get tokens.
Every response to a project path carries an X-Request-Id header; quote it when you report a problem.

The public sandbox

To try the API without an account, ask for a token for the public sandbox: a read-only example project (Acme Shop on iOS and Android) filled with synthetic data.
The Apsio-Sandbox: 1 header is required. The answer has a token, its expires_at and the sandbox’s project_id. The token reads that project through every endpoint below for a few hours, and nothing else; every route that would change something answers 403 with the code sandbox_read_only. Tokens and reads are rate-limited per client. The same example project opens in the console at app.apsio.io/sandbox.

Endpoints

All paths start with /v1/projects/{projectId}. Users are counted by install id. When an app turns the install id off, user numbers are null and only the session numbers are given. An issue’s id is its fingerprint: the exception type and the top in-app frames of the stack once symbolicated. When an occurrence arrives before its symbols, symbolicated is false and missing_debug_ids lists every image of its stack without symbols, system frameworks included. The in-app images to upload come from GET /v1/projects/{projectId}/releases/{release}/missing-symbols. After an upload, the occurrence is symbolicated again and may move to another issue. grouping tells which rule made the fingerprint: see Grouping. In an issue’s latest occurrence, frames is the crashing thread symbolicated (function, file, line, image, whether it is in your app), and raw_frames is the stack as the device sent it. /issues takes kind (crash, error, anr, hang or abnormal_exit; every kind by default) and sort (last_seen, occurrences or users, descending). Vitals percentiles are exact and weighted by each span’s sample weight. TTFD is listed only for screens where the app called reportFullyDrawn(): Apsio never substitutes TTID for it. A hang rate counts sessions with at least one hang occurrence (iOS), an ANR rate sessions with an ANR (Android). A cohort is defined by the same filters as /sessions (at least one besides app_id, which narrows both sides). For each value of a dimension, difference is its share in the cohort minus its share in the other sessions, and lift their ratio; values are ranked by difference, and only over-represented ones are listed. Shares from a few sessions are noisy: min_sessions (default 2) leaves out rarer values, and a small cohort deserves a higher one. When the cohort or the rest is empty, comparable is false, no values are listed and note says why. Feature flags come from the evaluation records (feature_flag.key and feature_flag.result.variant) and from the feature_flag.<name> attributes a session carries after a rotation; network types from network.connection.type. A cohort covers at most 30 days, and so do vitals.

Performance and network

Requests are grouped by the endpoint template: url.template when the app or its HTTP library sends it (without any query or fragment), otherwise the path of url.full with every segment that looks like an identifier or personal data (ids, UUIDs, long hexadecimal, phone numbers, tokens, email addresses, free text) replaced by {id}. So GET /orders/1001 and GET /orders/1002 are one endpoint, GET /orders/{id}. A request failed when it got a 5xx or no response at all (error.type set, no status); 4xx responses are counted on their own, since many are expected. Request counts and percentiles are reweighted by session sampling, as vitals are; network percentiles are estimates (t-digest), app start and screen percentiles are exact. A method other than the standard ones is _OTHER. /sessions and /cohorts/compare take an endpoint (endpoint_method, endpoint_host and endpoint_template, with endpoint_failed=true for failed requests only) or a screen (screen, with min_ttid_ms for slow loads only), so the sessions behind a failing endpoint or a slow screen are one request away. Each sample request and trace carries apm_url, the same trace in your APM, built from the project’s APM link (Settings, or PATCH /v1/orgs/{orgId}/projects/{projectId}): an https URL with a {trace_id} placeholder, for example https://app.datadoghq.com/apm/trace/{trace_id}. Apps send traceparent only to the hosts you list, so the trace id is the one your backend saw. MetricKit histograms come from every user’s day, not from sampled sessions; points with other bucket bounds than a release’s most common ones are counted in excluded_points and not added. Performance views cover at most 30 days.

Examples

Release health since October 1:
Crashes, most frequent first:
Crashed sessions with a given issue:
What the crashing sessions of an issue have in common, by device model:
The slowest endpoints of the iOS app, with their error rates:
The numbers and ids are examples.

Time ranges and pages

  • from and to are RFC 3339 times. The default range is the last 7 days (90 days for one issue, 30 days for a release comparison, 14 days for the daily series); a request may cover at most 90 days, and 30 days for session search, vitals and cohorts.
  • The daily series has one entry per UTC day. Without from it starts at midnight UTC 13 days before to, so it holds 14 days; the last day is partial (up to to), and so is the first when from is not at midnight.
  • A request that hits a query limit (time, memory or result size) gets query_limit with 503 or 422: narrow the time range or pick an app.
  • Lists return next_cursor. Pass it back as cursor for the next page; it is null on the last page. limit sets the page size.

Errors

Errors are JSON with a code and a message:
The code is invalid_request (400), unauthorized (401), forbidden (403) or not_found (404).

The console API

The API reference also lists the console’s own endpoints: sign-in, organizations, members, projects, apps and app keys. They use the console’s sign-in session, not project tokens, and are documented for completeness.

Text written by apps

Exception messages, log bodies, breadcrumbs and attributes are written by your app and its users. Treat them as data, not instructions, when you pass them to an agent.