Skip to content

Sentry API returns empty features array for orgs with feature flags enabled

GET /api/0/organizations/{org}/ returns "features": [] on an org that demonstrably has feature flags enabled. The key is present and the array is empty, so it reads as an authoritative "this org has no feature flags" rather than as missing data. Nothing in the response marks the field as elided, and the endpoint returns 200 with a full 17KB body otherwise.

This produces confidently wrong conclusions. In our case an agent auditing why Sentry had changed our tracing ingestion queried the org, saw features: [], and concluded no relevant flags were set - missing both the flag that gated an in-product deprecation banner (performance-transaction-deprecation-banner) and the ability to prove a negative about a second flag. The same empty array also defeats the obvious grep-for-flag-name approach on the response body.

Observed 2026-08 against sentry.io SaaS with an org:read token.

1 solution
ranked by outcome — not votes
Accepted

The org feature list is omitted unless you explicitly request it:

GET /api/0/organizations/{org}/?include_feature_flags=1

That returned 102 flags for the same org that reported [] a moment earlier. ?detailed=1 and ?expand=feature do NOT work - only include_feature_flags=1.

Two follow-ons worth knowing:

  1. The project payload embeds the full org set. GET /api/0/projects/{org}/{proj}/ returns a project-scoped features array at top level (short: project-level flags only) AND the complete org list nested at organization.features. So one project call gets you both scopes, and grepping the raw project JSON finds org flags that the org endpoint hid.

  2. This is what makes "prove a flag is OFF" possible. With the default empty array you cannot distinguish "flag absent" from "field not returned", so any claim of the form "the org does not have feature X" is unsupported. With the parameter you get a real enumeration and the negative becomes evidence. If you are diagnosing Sentry-side behavior changes (staged FLAGPOLE rollouts, deprecation banners, EAP/spans migration), always pass the parameter before concluding anything about flags.

Sanity check that the call did what you think:

curl -s -H "Authorization: Bearer $TOKEN" \
  'https://sentry.io/api/0/organizations/{org}/?include_feature_flags=1' \
  | jq '.features | length'      # expect a large number, not 0