diff --git a/src/sentry/management/commands/generate_ts_api_routes.py b/src/sentry/management/commands/generate_ts_api_routes.py new file mode 100644 index 00000000000000..6342174e94eed5 --- /dev/null +++ b/src/sentry/management/commands/generate_ts_api_routes.py @@ -0,0 +1,171 @@ +import itertools +import re +from importlib import import_module + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.urls import URLPattern, URLResolver + +# --- UTILS --- + + +def snake_to_camel(s: str) -> str: + parts = s.split("_") + return parts[0] + "".join(p.capitalize() for p in parts[1:]) + + +def final_cleanup(path: str) -> str: + path = path.replace(r"\/", "/") + path = re.sub(r"\([^)]*\)", "", path) # remove leftover groups + path = path.replace(".*", "") + path = re.sub(r"//+", "/", path) + + # Ensure leading and trailing slash + path = "/" + path.strip("/") + + if not path.endswith("/"): + path += "/" + + return path + + +def replace_named_groups(regex: str) -> str: + result = [] + last_end = 0 + + # Match all `(?P...)` groups, even with nested `(...)` inside + pattern = re.compile(r"\(\?P<(\w+)>") + + for match in pattern.finditer(regex): + start = match.start() + name = match.group(1) + + # Find the matching closing parenthesis for this group + depth = 1 + i = match.end() + while i < len(regex): + if regex[i] == "(": + depth += 1 + elif regex[i] == ")": + depth -= 1 + if depth == 0: + break + i += 1 + + # If we couldn't find the end, skip the group entirely (fail-safe) + if depth != 0: + continue + + # Append text before the match and the replacement + result.append(regex[last_end:start]) + result.append(f"${snake_to_camel(name)}") + last_end = i + 1 # skip the closing ')' + + # Append the rest + result.append(regex[last_end:]) + return "".join(result) + + +def convert_django_regex_to_ts_all(regex: str) -> list[str]: + regex = regex.strip("^$") + + regex = replace_named_groups(regex) + + # Handle non-capturing groups (e.g. (?:x|y) → x and y) + pattern = r"\(\?:([^)]+)\)" + matches = list(re.finditer(pattern, regex)) + + # Also detect optional static segments like 'plugins?' + optional_pattern = r"([a-zA-Z0-9_-]+)\?" + matches += list(re.finditer(optional_pattern, regex)) + + if not matches: + return [final_cleanup(regex)] + + # Build route combinations + parts = [] + last_end = 0 + + for match in matches: + start, end = match.span() + parts.append([regex[last_end:start]]) + + if match.re.pattern == pattern: + parts.append(match.group(1).split("|")) + else: + token = match.group(1) + parts.append([token, ""]) # with or without the optional char + + last_end = end + + parts.append([regex[last_end:]]) + + combos = itertools.product(*parts) + return [final_cleanup("".join(c)) for c in combos] + + +def normalize_regex_part(regex: str) -> str: + return regex.strip("^$") + + +def extract_ts_routes(urlpatterns, prefix="") -> list[str]: + routes = [] + + for pattern in urlpatterns: + if isinstance(pattern, URLPattern): + raw_regex = normalize_regex_part(pattern.pattern.regex.pattern) + full_path = prefix + raw_regex + ts_paths = convert_django_regex_to_ts_all(full_path) + for path in ts_paths: + routes.append(f"'{path}'") + + elif isinstance(pattern, URLResolver): + new_prefix = prefix + normalize_regex_part(pattern.pattern.regex.pattern) + routes.extend(extract_ts_routes(pattern.url_patterns, new_prefix)) + + return routes + + +# --- COMMAND --- + + +class Command(BaseCommand): + help = "Generate TypeScript route types from Django urlpatterns" + + def add_arguments(self, parser): + parser.add_argument( + "--output", + type=str, + default="routes.ts", + help="Output file for TypeScript route types", + ) + parser.add_argument( + "--urls", + type=str, + default=settings.ROOT_URLCONF, + help="Python path to root URLconf (default: settings.ROOT_URLCONF)", + ) + + def handle(self, *args, **options): + urls_module_path = options["urls"] + output_file = options["output"] + + self.stdout.write(f"🔍 Loading URLconf: {urls_module_path}") + urlconf = import_module(urls_module_path) + urlpatterns = getattr(urlconf, "urlpatterns", []) + + ts_routes = extract_ts_routes(urlpatterns) + ts_routes = sorted(set(ts_routes)) + + with open(output_file, "w") as f: + f.write("/* prettier-ignore */\n") + f.write("// Auto-generated TypeScript route types\n") + f.write( + "// To update it run `sentry django generate_ts_api_routes --urls sentry.api.urls --output=path/to/thisfile.ts`\n" + ) + f.write("export type KnownApiUrls =\n") + for route in ts_routes: + f.write(f" | {route}\n") + f.write(";\n") + + self.stdout.write(self.style.SUCCESS(f"✅ Wrote {len(ts_routes)} routes to {output_file}")) diff --git a/static/app/api/apiDefinition.ts b/static/app/api/apiDefinition.ts index 61858ac079efa7..b4dae36abf5702 100644 --- a/static/app/api/apiDefinition.ts +++ b/static/app/api/apiDefinition.ts @@ -1,3 +1,29 @@ -type KnownApiUrls = ['/projects/$orgSlug/$projectSlug/releases/$releaseVersion/']; +import type {KnownApiUrls} from './knownUrls'; +import type {paths} from './openapi'; -export type MaybeApiPath = KnownApiUrls[number] | (string & {}); +type SnakeToCamel = S extends `${infer Head}_${infer Tail}` + ? `${Head}${Capitalize>}` + : S; + +// replace {param_name} → $paramName +type ParamToDollarCamel = S extends `{${infer Param}}` + ? `$${SnakeToCamel}` + : S; + +// Recursive: split by '/', transform params, join back +type TransformSegments = S extends `/${infer Rest}` + ? `/${TransformSegments}` + : S extends `${infer Segment}/${infer Tail}` + ? `${ParamToDollarCamel}/${TransformSegments}` + : ParamToDollarCamel; + +// filter GET paths, strip `/api/0`, and transform params +type GetPaths = { + [P in keyof paths]: 'get' extends keyof paths[P] + ? P extends `/api/0${infer Rest}` + ? TransformSegments + : never + : never; +}[keyof paths]; + +export type ApiPath = GetPaths | (string & {}); diff --git a/static/app/api/apiOptions.ts b/static/app/api/apiOptions.ts index 4372957396dd2c..a9e53c6935f136 100644 --- a/static/app/api/apiOptions.ts +++ b/static/app/api/apiOptions.ts @@ -3,8 +3,13 @@ import {queryOptions, skipToken, type SkipToken} from '@tanstack/react-query'; import type {ApiResult} from 'sentry/api'; import {fetchDataQuery, type QueryKeyEndpointOptions} from 'sentry/utils/queryClient'; -import type {MaybeApiPath} from './apiDefinition'; -import {getApiUrl, type ExtractPathParams, type OptionalPathParams} from './getApiUrl'; +import type {ApiPath} from './apiDefinition'; +import { + getApiUrl, + type ExtractPathParams, + type OptionalPathParams, + type PathParamOptions, +} from './getApiUrl'; type Options = QueryKeyEndpointOptions & {staleTime: number}; @@ -28,7 +33,7 @@ export const selectWithHeaders = function _apiOptions< TManualData = never, - TApiPath extends MaybeApiPath = MaybeApiPath, + TApiPath extends ApiPath = ApiPath, // todo: infer the actual data type from the ApiMapping TActualData = TManualData, >( @@ -67,7 +72,7 @@ function _apiOptions< export const apiOptions = { as: () => - ( + ( path: TApiPath, options: Options & PathParamOptions ) => diff --git a/static/app/api/getApiUrl.spec.ts b/static/app/api/getApiUrl.spec.ts index 87a1afdf8022b4..ed5e792e04e6ca 100644 --- a/static/app/api/getApiUrl.spec.ts +++ b/static/app/api/getApiUrl.spec.ts @@ -32,6 +32,21 @@ describe('getApiUrl', () => { expect(url).toBe('/projects/my-org/my-project/releases/v%201.0.0/'); }); + test('advanced path params case', () => { + const url = getApiUrl( + '/organizations/$organizationIdOrSlug/events/$projectIdOrSlug:$eventId/', + { + path: { + organizationIdOrSlug: 'my-org', + projectIdOrSlug: 'my-project', + eventId: '12345', + }, + } + ); + + expect(url).toBe('/organizations/my-org/events/my-project:12345/'); + }); + test('should stringify number path params', () => { const url = getApiUrl('/items/$id/', { path: {id: 123}, diff --git a/static/app/api/getApiUrl.ts b/static/app/api/getApiUrl.ts index b305e2efca997e..e831d59258b7ea 100644 --- a/static/app/api/getApiUrl.ts +++ b/static/app/api/getApiUrl.ts @@ -1,10 +1,16 @@ -import type {MaybeApiPath} from './apiDefinition'; +import type {ApiPath} from './apiDefinition'; + +type StripDollar = T extends `$${infer Name}` ? Name : T; + +type SplitColon = T extends `${infer A}:${infer B}` + ? StripDollar | SplitColon + : StripDollar; export type ExtractPathParams = TApiPath extends `${string}$${infer Param}/${infer Rest}` - ? Param | ExtractPathParams<`/${Rest}`> + ? SplitColon | ExtractPathParams<`/${Rest}`> : TApiPath extends `${string}$${infer Param}` - ? Param + ? SplitColon : never; type PathParamOptions = @@ -21,7 +27,7 @@ const paramRegex = /\$([a-zA-Z0-9_-]+)/g; type ApiUrl = string & {__apiUrl: true}; -export function getApiUrl( +export function getApiUrl( path: TApiPath, ...[options]: OptionalPathParams ): ApiUrl { diff --git a/static/app/api/knownUrls.ts b/static/app/api/knownUrls.ts new file mode 100644 index 00000000000000..a0a8dda1ef5317 --- /dev/null +++ b/static/app/api/knownUrls.ts @@ -0,0 +1,882 @@ +/* prettier-ignore */ +// Auto-generated TypeScript route types +// To update it run `sentry django generate_ts_api_routes --urls sentry.api.urls --output=path/to/thisfile.ts` +export type KnownApiUrls = + | '/' + | '/accept-invite/$memberId/$token/' + | '/accept-invite/$organizationIdOrSlug/$memberId/$token/' + | '/accept-transfer/' + | '/api-applications/$appId/' + | '/api-applications/$appId/rotate-secret/' + | '/api-applications/' + | '/api-authorizations/' + | '/api-tokens/$tokenId/' + | '/api-tokens/' + | '/assistant/' + | '/auth-v2/csrf/' + | '/auth-v2/flag/' + | '/auth-v2/login/' + | '/auth-v2/merge-accounts/' + | '/auth-v2/user-merge-verification-codes/' + | '/auth/' + | '/auth/config/' + | '/auth/login/' + | '/auth/validate/' + | '/authenticators/' + | '/broadcasts/$broadcastId/' + | '/broadcasts/' + | '/builtin-symbol-sources/' + | '/doc-integrations/$docIntegrationIdOrSlug/' + | '/doc-integrations/$docIntegrationIdOrSlug/avatar/' + | '/doc-integrations/' + | '/grouping-configs/' + | '/groups/$issueId/' + | '/groups/$issueId/activities/' + | '/groups/$issueId/asana/autocomplete/' + | '/groups/$issueId/asana/create/' + | '/groups/$issueId/asana/link/' + | '/groups/$issueId/asana/unlink/' + | '/groups/$issueId/attachments/' + | '/groups/$issueId/autofix/' + | '/groups/$issueId/autofix/setup/' + | '/groups/$issueId/autofix/update/' + | '/groups/$issueId/bitbucket/autocomplete/' + | '/groups/$issueId/bitbucket/create/' + | '/groups/$issueId/bitbucket/link/' + | '/groups/$issueId/bitbucket/unlink/' + | '/groups/$issueId/comments/$noteId/' + | '/groups/$issueId/comments/' + | '/groups/$issueId/current-release/' + | '/groups/$issueId/events/$eventId/' + | '/groups/$issueId/events/' + | '/groups/$issueId/external-issues/$externalIssueId/' + | '/groups/$issueId/external-issues/' + | '/groups/$issueId/first-last-release/' + | '/groups/$issueId/github/autocomplete/' + | '/groups/$issueId/github/create/' + | '/groups/$issueId/github/link/' + | '/groups/$issueId/github/unlink/' + | '/groups/$issueId/gitlab/create/' + | '/groups/$issueId/gitlab/link/' + | '/groups/$issueId/gitlab/unlink/' + | '/groups/$issueId/hashes/' + | '/groups/$issueId/integrations/$integrationId/' + | '/groups/$issueId/integrations/' + | '/groups/$issueId/jira/autocomplete/' + | '/groups/$issueId/jira/create/' + | '/groups/$issueId/jira/link/' + | '/groups/$issueId/jira/unlink/' + | '/groups/$issueId/notes/$noteId/' + | '/groups/$issueId/notes/' + | '/groups/$issueId/open-periods/' + | '/groups/$issueId/pivotal/autocomplete/' + | '/groups/$issueId/pivotal/create/' + | '/groups/$issueId/pivotal/link/' + | '/groups/$issueId/pivotal/unlink/' + | '/groups/$issueId/plugins/asana/autocomplete/' + | '/groups/$issueId/plugins/asana/create/' + | '/groups/$issueId/plugins/asana/link/' + | '/groups/$issueId/plugins/asana/unlink/' + | '/groups/$issueId/plugins/bitbucket/autocomplete/' + | '/groups/$issueId/plugins/bitbucket/create/' + | '/groups/$issueId/plugins/bitbucket/link/' + | '/groups/$issueId/plugins/bitbucket/unlink/' + | '/groups/$issueId/plugins/github/autocomplete/' + | '/groups/$issueId/plugins/github/create/' + | '/groups/$issueId/plugins/github/link/' + | '/groups/$issueId/plugins/github/unlink/' + | '/groups/$issueId/plugins/gitlab/create/' + | '/groups/$issueId/plugins/gitlab/link/' + | '/groups/$issueId/plugins/gitlab/unlink/' + | '/groups/$issueId/plugins/jira/autocomplete/' + | '/groups/$issueId/plugins/jira/create/' + | '/groups/$issueId/plugins/jira/link/' + | '/groups/$issueId/plugins/jira/unlink/' + | '/groups/$issueId/plugins/pivotal/autocomplete/' + | '/groups/$issueId/plugins/pivotal/create/' + | '/groups/$issueId/plugins/pivotal/link/' + | '/groups/$issueId/plugins/pivotal/unlink/' + | '/groups/$issueId/plugins/trello/autocomplete/' + | '/groups/$issueId/plugins/trello/create/' + | '/groups/$issueId/plugins/trello/link/' + | '/groups/$issueId/plugins/trello/options/' + | '/groups/$issueId/plugins/trello/unlink/' + | '/groups/$issueId/reprocessing/' + | '/groups/$issueId/similar-issues-embeddings/' + | '/groups/$issueId/similar/' + | '/groups/$issueId/stats/' + | '/groups/$issueId/summarize/' + | '/groups/$issueId/suspect/flags/' + | '/groups/$issueId/suspect/tags/' + | '/groups/$issueId/tags/$key/' + | '/groups/$issueId/tags/$key/values/' + | '/groups/$issueId/tags/' + | '/groups/$issueId/trello/autocomplete/' + | '/groups/$issueId/trello/create/' + | '/groups/$issueId/trello/link/' + | '/groups/$issueId/trello/options/' + | '/groups/$issueId/trello/unlink/' + | '/groups/$issueId/user-feedback/' + | '/groups/$issueId/user-reports/' + | '/integration-features/' + | '/internal/$organizationIdOrSlug/$projectIdOrSlug/files/preprodartifacts/$artifactId/' + | '/internal/$organizationIdOrSlug/$projectIdOrSlug/files/preprodartifacts/$artifactId/assemble-generic/' + | '/internal/$organizationIdOrSlug/$projectIdOrSlug/files/preprodartifacts/$artifactId/update/' + | '/internal/beacon/' + | '/internal/check-am2-compatibility/' + | '/internal/demo/email-capture/' + | '/internal/environment/' + | '/internal/feature-flags/' + | '/internal/feature-flags/ea-feature-flags/' + | '/internal/health/' + | '/internal/integration-proxy/' + | '/internal/mail/' + | '/internal/options/' + | '/internal/packages/' + | '/internal/project-config/' + | '/internal/queue/tasks/' + | '/internal/quotas/' + | '/internal/rpc/$serviceName/$methodName/' + | '/internal/seer-rpc/$methodName/' + | '/internal/stats/' + | '/internal/warnings/' + | '/issues/$issueId/' + | '/issues/$issueId/activities/' + | '/issues/$issueId/asana/autocomplete/' + | '/issues/$issueId/asana/create/' + | '/issues/$issueId/asana/link/' + | '/issues/$issueId/asana/unlink/' + | '/issues/$issueId/attachments/' + | '/issues/$issueId/autofix/' + | '/issues/$issueId/autofix/setup/' + | '/issues/$issueId/autofix/update/' + | '/issues/$issueId/bitbucket/autocomplete/' + | '/issues/$issueId/bitbucket/create/' + | '/issues/$issueId/bitbucket/link/' + | '/issues/$issueId/bitbucket/unlink/' + | '/issues/$issueId/comments/$noteId/' + | '/issues/$issueId/comments/' + | '/issues/$issueId/current-release/' + | '/issues/$issueId/events/$eventId/' + | '/issues/$issueId/events/' + | '/issues/$issueId/external-issues/$externalIssueId/' + | '/issues/$issueId/external-issues/' + | '/issues/$issueId/first-last-release/' + | '/issues/$issueId/github/autocomplete/' + | '/issues/$issueId/github/create/' + | '/issues/$issueId/github/link/' + | '/issues/$issueId/github/unlink/' + | '/issues/$issueId/gitlab/create/' + | '/issues/$issueId/gitlab/link/' + | '/issues/$issueId/gitlab/unlink/' + | '/issues/$issueId/hashes/' + | '/issues/$issueId/integrations/$integrationId/' + | '/issues/$issueId/integrations/' + | '/issues/$issueId/jira/autocomplete/' + | '/issues/$issueId/jira/create/' + | '/issues/$issueId/jira/link/' + | '/issues/$issueId/jira/unlink/' + | '/issues/$issueId/notes/$noteId/' + | '/issues/$issueId/notes/' + | '/issues/$issueId/open-periods/' + | '/issues/$issueId/pivotal/autocomplete/' + | '/issues/$issueId/pivotal/create/' + | '/issues/$issueId/pivotal/link/' + | '/issues/$issueId/pivotal/unlink/' + | '/issues/$issueId/plugins/asana/autocomplete/' + | '/issues/$issueId/plugins/asana/create/' + | '/issues/$issueId/plugins/asana/link/' + | '/issues/$issueId/plugins/asana/unlink/' + | '/issues/$issueId/plugins/bitbucket/autocomplete/' + | '/issues/$issueId/plugins/bitbucket/create/' + | '/issues/$issueId/plugins/bitbucket/link/' + | '/issues/$issueId/plugins/bitbucket/unlink/' + | '/issues/$issueId/plugins/github/autocomplete/' + | '/issues/$issueId/plugins/github/create/' + | '/issues/$issueId/plugins/github/link/' + | '/issues/$issueId/plugins/github/unlink/' + | '/issues/$issueId/plugins/gitlab/create/' + | '/issues/$issueId/plugins/gitlab/link/' + | '/issues/$issueId/plugins/gitlab/unlink/' + | '/issues/$issueId/plugins/jira/autocomplete/' + | '/issues/$issueId/plugins/jira/create/' + | '/issues/$issueId/plugins/jira/link/' + | '/issues/$issueId/plugins/jira/unlink/' + | '/issues/$issueId/plugins/pivotal/autocomplete/' + | '/issues/$issueId/plugins/pivotal/create/' + | '/issues/$issueId/plugins/pivotal/link/' + | '/issues/$issueId/plugins/pivotal/unlink/' + | '/issues/$issueId/plugins/trello/autocomplete/' + | '/issues/$issueId/plugins/trello/create/' + | '/issues/$issueId/plugins/trello/link/' + | '/issues/$issueId/plugins/trello/options/' + | '/issues/$issueId/plugins/trello/unlink/' + | '/issues/$issueId/related-issues/' + | '/issues/$issueId/reprocessing/' + | '/issues/$issueId/similar-issues-embeddings/' + | '/issues/$issueId/similar/' + | '/issues/$issueId/stats/' + | '/issues/$issueId/summarize/' + | '/issues/$issueId/suspect/flags/' + | '/issues/$issueId/suspect/tags/' + | '/issues/$issueId/tags/$key/' + | '/issues/$issueId/tags/$key/values/' + | '/issues/$issueId/tags/' + | '/issues/$issueId/trello/autocomplete/' + | '/issues/$issueId/trello/create/' + | '/issues/$issueId/trello/link/' + | '/issues/$issueId/trello/options/' + | '/issues/$issueId/trello/unlink/' + | '/issues/$issueId/user-feedback/' + | '/issues/$issueId/user-reports/' + | '/notification-defaults/' + | '/organizations/$organizationIdOrSlug/' + | '/organizations/$organizationIdOrSlug/access-requests/$requestId/' + | '/organizations/$organizationIdOrSlug/access-requests/' + | '/organizations/$organizationIdOrSlug/alert-rules/$alertRuleId/' + | '/organizations/$organizationIdOrSlug/alert-rules/' + | '/organizations/$organizationIdOrSlug/alert-rules/available-actions/' + | '/organizations/$organizationIdOrSlug/api-keys/$apiKeyId/' + | '/organizations/$organizationIdOrSlug/api-keys/' + | '/organizations/$organizationIdOrSlug/artifactbundle/assemble/' + | '/organizations/$organizationIdOrSlug/audit-logs/' + | '/organizations/$organizationIdOrSlug/auth-provider/' + | '/organizations/$organizationIdOrSlug/auth-providers/' + | '/organizations/$organizationIdOrSlug/available-actions/' + | '/organizations/$organizationIdOrSlug/avatar/' + | '/organizations/$organizationIdOrSlug/broadcasts/' + | '/organizations/$organizationIdOrSlug/builtin-symbol-sources/' + | '/organizations/$organizationIdOrSlug/chunk-upload/' + | '/organizations/$organizationIdOrSlug/code-mappings/$configId/' + | '/organizations/$organizationIdOrSlug/code-mappings/$configId/codeowners/' + | '/organizations/$organizationIdOrSlug/code-mappings/' + | '/organizations/$organizationIdOrSlug/codeowners-associations/' + | '/organizations/$organizationIdOrSlug/combined-rules/' + | '/organizations/$organizationIdOrSlug/config/integrations/' + | '/organizations/$organizationIdOrSlug/config/repos/' + | '/organizations/$organizationIdOrSlug/dashboards/$dashboardId/' + | '/organizations/$organizationIdOrSlug/dashboards/$dashboardId/favorite/' + | '/organizations/$organizationIdOrSlug/dashboards/$dashboardId/visit/' + | '/organizations/$organizationIdOrSlug/dashboards/' + | '/organizations/$organizationIdOrSlug/dashboards/starred/' + | '/organizations/$organizationIdOrSlug/dashboards/starred/order/' + | '/organizations/$organizationIdOrSlug/dashboards/widgets/' + | '/organizations/$organizationIdOrSlug/data-conditions/' + | '/organizations/$organizationIdOrSlug/data-export/$dataExportId/' + | '/organizations/$organizationIdOrSlug/data-export/' + | '/organizations/$organizationIdOrSlug/data-scrubbing-selector-suggestions/' + | '/organizations/$organizationIdOrSlug/derive-code-mappings/' + | '/organizations/$organizationIdOrSlug/detector-types/' + | '/organizations/$organizationIdOrSlug/detector-workflow/$detectorWorkflowId/' + | '/organizations/$organizationIdOrSlug/detector-workflow/' + | '/organizations/$organizationIdOrSlug/detectors/$detectorId/' + | '/organizations/$organizationIdOrSlug/detectors/' + | '/organizations/$organizationIdOrSlug/discover/homepage/' + | '/organizations/$organizationIdOrSlug/discover/saved/$queryId/' + | '/organizations/$organizationIdOrSlug/discover/saved/$queryId/visit/' + | '/organizations/$organizationIdOrSlug/discover/saved/' + | '/organizations/$organizationIdOrSlug/dynamic-sampling/custom-rules/' + | '/organizations/$organizationIdOrSlug/environments/' + | '/organizations/$organizationIdOrSlug/eventids/$eventId/' + | '/organizations/$organizationIdOrSlug/events-facets-performance-histogram/' + | '/organizations/$organizationIdOrSlug/events-facets-performance/' + | '/organizations/$organizationIdOrSlug/events-facets/' + | '/organizations/$organizationIdOrSlug/events-has-measurements/' + | '/organizations/$organizationIdOrSlug/events-histogram/' + | '/organizations/$organizationIdOrSlug/events-meta/' + | '/organizations/$organizationIdOrSlug/events-root-cause-analysis/' + | '/organizations/$organizationIdOrSlug/events-span-ops/' + | '/organizations/$organizationIdOrSlug/events-spans-histogram/' + | '/organizations/$organizationIdOrSlug/events-spans-performance/' + | '/organizations/$organizationIdOrSlug/events-spans-stats/' + | '/organizations/$organizationIdOrSlug/events-spans/' + | '/organizations/$organizationIdOrSlug/events-stats/' + | '/organizations/$organizationIdOrSlug/events-timeseries/' + | '/organizations/$organizationIdOrSlug/events-trace-light/$traceId/' + | '/organizations/$organizationIdOrSlug/events-trace-meta/$traceId/' + | '/organizations/$organizationIdOrSlug/events-trace/$traceId/' + | '/organizations/$organizationIdOrSlug/events-trends-stats/' + | '/organizations/$organizationIdOrSlug/events-trends-statsv2/' + | '/organizations/$organizationIdOrSlug/events-trends/' + | '/organizations/$organizationIdOrSlug/events-vitals/' + | '/organizations/$organizationIdOrSlug/events/$projectIdOrSlug:$eventId/' + | '/organizations/$organizationIdOrSlug/events/' + | '/organizations/$organizationIdOrSlug/events/anomalies/' + | '/organizations/$organizationIdOrSlug/experimental/projects/' + | '/organizations/$organizationIdOrSlug/explore/saved/$id/' + | '/organizations/$organizationIdOrSlug/explore/saved/$id/starred/' + | '/organizations/$organizationIdOrSlug/explore/saved/$id/visit/' + | '/organizations/$organizationIdOrSlug/explore/saved/' + | '/organizations/$organizationIdOrSlug/explore/saved/starred/order/' + | '/organizations/$organizationIdOrSlug/external-users/$externalUserId/' + | '/organizations/$organizationIdOrSlug/external-users/' + | '/organizations/$organizationIdOrSlug/feedback-summary/' + | '/organizations/$organizationIdOrSlug/flags/hooks/provider/$provider/' + | '/organizations/$organizationIdOrSlug/flags/logs/$flagLogId/' + | '/organizations/$organizationIdOrSlug/flags/logs/' + | '/organizations/$organizationIdOrSlug/flags/signing-secrets/$signingSecretId/' + | '/organizations/$organizationIdOrSlug/flags/signing-secrets/' + | '/organizations/$organizationIdOrSlug/fork/' + | '/organizations/$organizationIdOrSlug/group-search-views/$viewId/' + | '/organizations/$organizationIdOrSlug/group-search-views/$viewId/starred/' + | '/organizations/$organizationIdOrSlug/group-search-views/$viewId/visit/' + | '/organizations/$organizationIdOrSlug/group-search-views/' + | '/organizations/$organizationIdOrSlug/group-search-views/starred/' + | '/organizations/$organizationIdOrSlug/group-search-views/starred/order/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/activities/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/asana/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/asana/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/asana/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/asana/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/attachments/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/autofix/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/autofix/setup/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/autofix/update/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/bitbucket/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/bitbucket/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/bitbucket/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/bitbucket/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/comments/$noteId/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/comments/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/current-release/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/events/$eventId/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/events/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/external-issues/$externalIssueId/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/external-issues/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/first-last-release/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/github/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/github/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/github/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/github/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/gitlab/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/gitlab/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/gitlab/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/hashes/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/integrations/$integrationId/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/integrations/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/jira/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/jira/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/jira/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/jira/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/notes/$noteId/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/notes/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/open-periods/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/pivotal/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/pivotal/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/pivotal/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/pivotal/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/asana/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/asana/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/asana/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/asana/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/bitbucket/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/bitbucket/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/bitbucket/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/bitbucket/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/github/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/github/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/github/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/github/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/gitlab/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/gitlab/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/gitlab/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/jira/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/jira/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/jira/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/jira/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/pivotal/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/pivotal/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/pivotal/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/pivotal/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/trello/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/trello/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/trello/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/trello/options/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/plugins/trello/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/reprocessing/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/similar-issues-embeddings/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/similar/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/stats/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/summarize/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/suspect/flags/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/suspect/tags/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/tags/$key/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/tags/$key/values/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/tags/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/trello/autocomplete/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/trello/create/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/trello/link/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/trello/options/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/trello/unlink/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/user-feedback/' + | '/organizations/$organizationIdOrSlug/groups/$issueId/user-reports/' + | '/organizations/$organizationIdOrSlug/incidents/$incidentIdentifier/' + | '/organizations/$organizationIdOrSlug/incidents/' + | '/organizations/$organizationIdOrSlug/insights/starred-segments/' + | '/organizations/$organizationIdOrSlug/insights/tree/' + | '/organizations/$organizationIdOrSlug/integration-requests/' + | '/organizations/$organizationIdOrSlug/integrations/$integrationId/' + | '/organizations/$organizationIdOrSlug/integrations/$integrationId/issues/' + | '/organizations/$organizationIdOrSlug/integrations/$integrationId/migrate-opsgenie/' + | '/organizations/$organizationIdOrSlug/integrations/$integrationId/repos/' + | '/organizations/$organizationIdOrSlug/integrations/$integrationId/serverless-functions/' + | '/organizations/$organizationIdOrSlug/integrations/' + | '/organizations/$organizationIdOrSlug/invite-requests/$memberId/' + | '/organizations/$organizationIdOrSlug/invite-requests/' + | '/organizations/$organizationIdOrSlug/invited-members/$memberInviteId/' + | '/organizations/$organizationIdOrSlug/invited-members/' + | '/organizations/$organizationIdOrSlug/issues-count/' + | '/organizations/$organizationIdOrSlug/issues-metrics/' + | '/organizations/$organizationIdOrSlug/issues-stats/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/activities/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/asana/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/asana/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/asana/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/asana/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/attachments/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/autofix/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/autofix/setup/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/autofix/update/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/bitbucket/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/bitbucket/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/bitbucket/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/bitbucket/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/comments/$noteId/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/comments/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/current-release/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/events/$eventId/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/events/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/external-issues/$externalIssueId/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/external-issues/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/first-last-release/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/github/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/github/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/github/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/github/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/gitlab/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/gitlab/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/gitlab/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/hashes/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/integrations/$integrationId/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/integrations/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/jira/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/jira/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/jira/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/jira/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/notes/$noteId/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/notes/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/open-periods/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/pivotal/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/pivotal/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/pivotal/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/pivotal/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/asana/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/asana/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/asana/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/asana/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/bitbucket/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/bitbucket/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/bitbucket/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/bitbucket/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/github/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/github/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/github/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/github/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/gitlab/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/gitlab/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/gitlab/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/jira/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/jira/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/jira/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/jira/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/pivotal/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/pivotal/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/pivotal/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/pivotal/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/trello/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/trello/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/trello/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/trello/options/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/plugins/trello/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/reprocessing/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/similar-issues-embeddings/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/similar/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/stats/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/summarize/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/suspect/flags/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/suspect/tags/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/tags/$key/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/tags/$key/values/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/tags/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/trello/autocomplete/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/trello/create/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/trello/link/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/trello/options/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/trello/unlink/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/user-feedback/' + | '/organizations/$organizationIdOrSlug/issues/$issueId/user-reports/' + | '/organizations/$organizationIdOrSlug/issues/' + | '/organizations/$organizationIdOrSlug/join-request/' + | '/organizations/$organizationIdOrSlug/key-transactions-list/' + | '/organizations/$organizationIdOrSlug/key-transactions/' + | '/organizations/$organizationIdOrSlug/measurements-meta/' + | '/organizations/$organizationIdOrSlug/members/$memberId/' + | '/organizations/$organizationIdOrSlug/members/$memberId/teams/$teamIdOrSlug/' + | '/organizations/$organizationIdOrSlug/members/' + | '/organizations/$organizationIdOrSlug/metrics-compatibility-sums/' + | '/organizations/$organizationIdOrSlug/metrics-compatibility/' + | '/organizations/$organizationIdOrSlug/metrics-estimation-stats/' + | '/organizations/$organizationIdOrSlug/metrics/data/' + | '/organizations/$organizationIdOrSlug/missing-members/' + | '/organizations/$organizationIdOrSlug/monitors-count/' + | '/organizations/$organizationIdOrSlug/monitors-schedule-data/' + | '/organizations/$organizationIdOrSlug/monitors-stats/' + | '/organizations/$organizationIdOrSlug/monitors/$monitorIdOrSlug/' + | '/organizations/$organizationIdOrSlug/monitors/$monitorIdOrSlug/checkins/' + | '/organizations/$organizationIdOrSlug/monitors/$monitorIdOrSlug/environments/$environment/' + | '/organizations/$organizationIdOrSlug/monitors/$monitorIdOrSlug/stats/' + | '/organizations/$organizationIdOrSlug/monitors/' + | '/organizations/$organizationIdOrSlug/notifications/actions/$actionId/' + | '/organizations/$organizationIdOrSlug/notifications/actions/' + | '/organizations/$organizationIdOrSlug/notifications/available-actions/' + | '/organizations/$organizationIdOrSlug/onboarding-continuation-email/' + | '/organizations/$organizationIdOrSlug/onboarding-tasks/' + | '/organizations/$organizationIdOrSlug/ondemand-rules-stats/' + | '/organizations/$organizationIdOrSlug/org-auth-tokens/$tokenId/' + | '/organizations/$organizationIdOrSlug/org-auth-tokens/' + | '/organizations/$organizationIdOrSlug/page-web-vitals-summary/' + | '/organizations/$organizationIdOrSlug/pinned-searches/' + | '/organizations/$organizationIdOrSlug/plugins/' + | '/organizations/$organizationIdOrSlug/plugins/configs/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repositories/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repositories/tokens/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repository/$repository/branches/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repository/$repository/test-results-aggregates/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repository/$repository/test-results/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repository/$repository/test-suites/' + | '/organizations/$organizationIdOrSlug/prevent/owner/$owner/repository/$repository/token/regenerate/' + | '/organizations/$organizationIdOrSlug/processing-errors/' + | '/organizations/$organizationIdOrSlug/profiling/chunks/' + | '/organizations/$organizationIdOrSlug/profiling/flamegraph/' + | '/organizations/$organizationIdOrSlug/profiling/function-trends/' + | '/organizations/$organizationIdOrSlug/profiling/has-chunks/' + | '/organizations/$organizationIdOrSlug/project-templates/$templateId/' + | '/organizations/$organizationIdOrSlug/project-templates/' + | '/organizations/$organizationIdOrSlug/project-transaction-threshold-override/' + | '/organizations/$organizationIdOrSlug/projects-count/' + | '/organizations/$organizationIdOrSlug/projects/' + | '/organizations/$organizationIdOrSlug/prompts-activity/' + | '/organizations/$organizationIdOrSlug/recent-searches/' + | '/organizations/$organizationIdOrSlug/region/' + | '/organizations/$organizationIdOrSlug/related-issues/' + | '/organizations/$organizationIdOrSlug/relay_usage/' + | '/organizations/$organizationIdOrSlug/release-threshold-statuses/' + | '/organizations/$organizationIdOrSlug/release-thresholds/' + | '/organizations/$organizationIdOrSlug/releases/$version/' + | '/organizations/$organizationIdOrSlug/releases/$version/assemble/' + | '/organizations/$organizationIdOrSlug/releases/$version/commitfiles/' + | '/organizations/$organizationIdOrSlug/releases/$version/commits/' + | '/organizations/$organizationIdOrSlug/releases/$version/deploys/' + | '/organizations/$organizationIdOrSlug/releases/$version/files/$fileId/' + | '/organizations/$organizationIdOrSlug/releases/$version/files/' + | '/organizations/$organizationIdOrSlug/releases/$version/meta/' + | '/organizations/$organizationIdOrSlug/releases/$version/previous-with-commits/' + | '/organizations/$organizationIdOrSlug/releases/$version/resolved/' + | '/organizations/$organizationIdOrSlug/releases/' + | '/organizations/$organizationIdOrSlug/releases/stats/' + | '/organizations/$organizationIdOrSlug/replay-count/' + | '/organizations/$organizationIdOrSlug/replay-selectors/' + | '/organizations/$organizationIdOrSlug/replays-events-meta/' + | '/organizations/$organizationIdOrSlug/replays/$replayId/' + | '/organizations/$organizationIdOrSlug/replays/' + | '/organizations/$organizationIdOrSlug/repos/$repoId/' + | '/organizations/$organizationIdOrSlug/repos/$repoId/commits/' + | '/organizations/$organizationIdOrSlug/repos/' + | '/organizations/$organizationIdOrSlug/request-project-creation/' + | '/organizations/$organizationIdOrSlug/sampling/admin-metrics/' + | '/organizations/$organizationIdOrSlug/sampling/project-rates/' + | '/organizations/$organizationIdOrSlug/sampling/project-root-counts/' + | '/organizations/$organizationIdOrSlug/scim/v2/Groups/$teamIdOrSlug/' + | '/organizations/$organizationIdOrSlug/scim/v2/Groups/' + | '/organizations/$organizationIdOrSlug/scim/v2/Schemas/' + | '/organizations/$organizationIdOrSlug/scim/v2/Users/$memberId/' + | '/organizations/$organizationIdOrSlug/scim/v2/Users/' + | '/organizations/$organizationIdOrSlug/sdk-deprecations/' + | '/organizations/$organizationIdOrSlug/sdk-updates/' + | '/organizations/$organizationIdOrSlug/sdks/' + | '/organizations/$organizationIdOrSlug/searches/$searchId/' + | '/organizations/$organizationIdOrSlug/searches/' + | '/organizations/$organizationIdOrSlug/seer/explorer-chat/$runId/?/' + | '/organizations/$organizationIdOrSlug/seer/setup-check/' + | '/organizations/$organizationIdOrSlug/sent-first-event/' + | '/organizations/$organizationIdOrSlug/sentry-app-components/' + | '/organizations/$organizationIdOrSlug/sentry-app-installations/' + | '/organizations/$organizationIdOrSlug/sentry-apps/' + | '/organizations/$organizationIdOrSlug/sessions/' + | '/organizations/$organizationIdOrSlug/shared/groups/$shareId/' + | '/organizations/$organizationIdOrSlug/shared/issues/$shareId/' + | '/organizations/$organizationIdOrSlug/shortids/$issueId/' + | '/organizations/$organizationIdOrSlug/spans-samples/' + | '/organizations/$organizationIdOrSlug/spans/fields/$key/values/' + | '/organizations/$organizationIdOrSlug/spans/fields/' + | '/organizations/$organizationIdOrSlug/spans/fields/stats/' + | '/organizations/$organizationIdOrSlug/stats-summary/' + | '/organizations/$organizationIdOrSlug/stats/' + | '/organizations/$organizationIdOrSlug/stats_v2/' + | '/organizations/$organizationIdOrSlug/tags/$key/values/' + | '/organizations/$organizationIdOrSlug/tags/' + | '/organizations/$organizationIdOrSlug/teams/' + | '/organizations/$organizationIdOrSlug/test-fire-actions/' + | '/organizations/$organizationIdOrSlug/trace-explorer-ai/query/' + | '/organizations/$organizationIdOrSlug/trace-explorer-ai/setup/' + | '/organizations/$organizationIdOrSlug/trace-items/attributes/$key/values/' + | '/organizations/$organizationIdOrSlug/trace-items/attributes/' + | '/organizations/$organizationIdOrSlug/trace-items/attributes/ranked/' + | '/organizations/$organizationIdOrSlug/trace-logs/' + | '/organizations/$organizationIdOrSlug/trace-meta/$traceId/' + | '/organizations/$organizationIdOrSlug/trace-summary/' + | '/organizations/$organizationIdOrSlug/trace/$traceId/' + | '/organizations/$organizationIdOrSlug/traces/' + | '/organizations/$organizationIdOrSlug/unsubscribe/issue/$id/' + | '/organizations/$organizationIdOrSlug/unsubscribe/project/$id/' + | '/organizations/$organizationIdOrSlug/uptime-count/' + | '/organizations/$organizationIdOrSlug/uptime-stats/' + | '/organizations/$organizationIdOrSlug/uptime-summary/' + | '/organizations/$organizationIdOrSlug/uptime/' + | '/organizations/$organizationIdOrSlug/user-feedback/' + | '/organizations/$organizationIdOrSlug/user-teams/' + | '/organizations/$organizationIdOrSlug/users/$userId/' + | '/organizations/$organizationIdOrSlug/users/' + | '/organizations/$organizationIdOrSlug/workflows/$workflowId/' + | '/organizations/$organizationIdOrSlug/workflows/$workflowId/group-history/' + | '/organizations/$organizationIdOrSlug/workflows/$workflowId/stats/' + | '/organizations/$organizationIdOrSlug/workflows/' + | '/organizations/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/alert-rule-task/$taskUuid/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/alert-rules/$alertRuleId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/alert-rules/$ruleId/snooze/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/alert-rules/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/artifact-bundles/$bundleId/files/$fileId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/artifact-bundles/$bundleId/files/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/artifact-lookup/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/cluster-transaction-names/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/codeowners/$codeownersId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/codeowners/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/commits/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/create-sample-transaction/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/create-sample/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/environments/$environment/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/environments/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/actionable-items/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/apple-crash-report/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/attachments/$attachmentId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/attachments/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/committers/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/grouping-info/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/json/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/owners/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/reprocessable/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/source-map-debug-blue-thunder-edition/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/$eventId/source-map-debug/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/events/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/artifact-bundles/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/difs/assemble/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/dsyms/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/dsyms/associate/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/dsyms/unknown/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/installablepreprodartifact/$urlPath/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/preprodartifacts/$artifactId/size-analysis/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/preprodartifacts/assemble/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/proguard-artifact-releases/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/files/source-maps/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/filters/$filterId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/filters/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/grouping-configs/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/groups/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/groups/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/hooks/$hookId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/hooks/$hookId/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/hooks/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/issues/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/issues/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/keys/$keyId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/keys/$keyId/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/keys/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/members/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/monitors/$monitorIdOrSlug/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/monitors/$monitorIdOrSlug/checkins/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/monitors/$monitorIdOrSlug/environments/$environment/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/monitors/$monitorIdOrSlug/processing-errors/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/monitors/$monitorIdOrSlug/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/overview/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/ownership/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/performance-issues/configure/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/performance/configure/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/plugins/$pluginId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/plugins/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/preprodartifacts/$artifactId/build-details/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/preprodartifacts/$artifactId/install-details/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/preprodartifacts/check-for-updates/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/processing-errors/$uuid/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/processing-errors/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/profiling/profiles/$profileId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/profiling/raw_chunks/$profilerId/$chunkId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/profiling/raw_profiles/$profileId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/release-thresholds/$releaseThreshold/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/release-thresholds/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/commits/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/files/$fileId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/files/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/repositories/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/resolved/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/completion/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/token/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/clicks/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/recording-segments/$segmentId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/recording-segments/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/summarize/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/videos/$segmentId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/$replayId/viewed-by/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/jobs/delete/$jobId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/replays/jobs/delete/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/repo-path-parsing/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/reprocessing/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rule-actions/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rule-task/$taskUuid/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/$ruleId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/$ruleId/enable/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/$ruleId/group-history/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/$ruleId/snooze/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/$ruleId/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/configuration/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/rules/preview/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/seer/preferences/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/stacktrace-coverage/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/stacktrace-link/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/statistical-detector/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/symbol-sources/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tags/$key/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tags/$key/values/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tags/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/teams/$teamIdOrSlug/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/teams/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tempest-credentials/$tempestCredentialsId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tempest-credentials/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tombstones/$tombstoneId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/tombstones/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/trace-items/$itemId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/transaction-threshold/configure/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/transfer/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/uptime/$uptimeProjectSubscriptionId/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/uptime/$uptimeProjectSubscriptionId/checks/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/uptime/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/user-feedback/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/user-reports/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/user-stats/' + | '/projects/$organizationIdOrSlug/$projectIdOrSlug/users/' + | '/projects/' + | '/prompts-activity/' + | '/publickeys/relocations/' + | '/relays/$relayId/' + | '/relays/' + | '/relays/live/' + | '/relays/projectconfigs/' + | '/relays/projectids/' + | '/relays/publickeys/' + | '/relays/register/challenge/' + | '/relays/register/response/' + | '/relocations/$relocationUuid/' + | '/relocations/$relocationUuid/abort/' + | '/relocations/$relocationUuid/artifacts/$artifactKind/$fileName/' + | '/relocations/$relocationUuid/artifacts/' + | '/relocations/$relocationUuid/cancel/' + | '/relocations/$relocationUuid/pause/' + | '/relocations/$relocationUuid/recover/' + | '/relocations/$relocationUuid/retry/' + | '/relocations/$relocationUuid/unpause/' + | '/relocations/' + | '/reporting-api-experiment/' + | '/secret-scanning/github/' + | '/sentry-app-installations/$uuid/' + | '/sentry-app-installations/$uuid/authorizations/' + | '/sentry-app-installations/$uuid/external-issue-actions/' + | '/sentry-app-installations/$uuid/external-issues/$externalIssueId/' + | '/sentry-app-installations/$uuid/external-issues/' + | '/sentry-app-installations/$uuid/external-requests/' + | '/sentry-app-installations/$uuid/service-hook-projects/' + | '/sentry-apps-stats/' + | '/sentry-apps/$sentryAppIdOrSlug/' + | '/sentry-apps/$sentryAppIdOrSlug/api-tokens/$apiTokenId/' + | '/sentry-apps/$sentryAppIdOrSlug/api-tokens/' + | '/sentry-apps/$sentryAppIdOrSlug/avatar/' + | '/sentry-apps/$sentryAppIdOrSlug/components/' + | '/sentry-apps/$sentryAppIdOrSlug/features/' + | '/sentry-apps/$sentryAppIdOrSlug/interaction/' + | '/sentry-apps/$sentryAppIdOrSlug/publish-request/' + | '/sentry-apps/$sentryAppIdOrSlug/requests/' + | '/sentry-apps/$sentryAppIdOrSlug/rotate-secret/' + | '/sentry-apps/$sentryAppIdOrSlug/stats/' + | '/sentry-apps/$sentryAppIdOrSlug/webhook-requests/' + | '/sentry-apps/' + | '/shared/groups/$shareId/' + | '/shared/issues/$shareId/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/alerts-triggered-index/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/alerts-triggered/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/all-unresolved-issues/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/external-teams/$externalTeamId/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/external-teams/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/issue-breakdown/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/issues/old/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/members/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/projects/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/release-count/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/stats/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/time-to-resolution/' + | '/teams/$organizationIdOrSlug/$teamIdOrSlug/unresolved-issue-age/' + | '/tempest-ips/' + | '/uptime-ips/' + | '/userroles/$roleName/' + | '/userroles/' + | '/users/$userId/' + | '/users/$userId/authenticators/$authId/$interfaceDeviceId/' + | '/users/$userId/authenticators/$authId/' + | '/users/$userId/authenticators/$interfaceId/enroll/' + | '/users/$userId/authenticators/' + | '/users/$userId/avatar/' + | '/users/$userId/emails/' + | '/users/$userId/emails/confirm/' + | '/users/$userId/identities/$identityId/' + | '/users/$userId/identities/' + | '/users/$userId/ips/' + | '/users/$userId/notification-options/$notificationOptionId/' + | '/users/$userId/notification-options/' + | '/users/$userId/notification-providers/' + | '/users/$userId/notifications/' + | '/users/$userId/notifications/email/' + | '/users/$userId/organization-integrations/' + | '/users/$userId/organizations/' + | '/users/$userId/password/' + | '/users/$userId/permissions/$permissionName/' + | '/users/$userId/permissions/' + | '/users/$userId/permissions/config/' + | '/users/$userId/regions/' + | '/users/$userId/roles/$roleName/' + | '/users/$userId/roles/' + | '/users/$userId/subscriptions/' + | '/users/$userId/user-identities/$category/$identityId/' + | '/users/$userId/user-identities/' + | '/users/' + | '/wizard/$wizardHash/' + | '/wizard/' +; diff --git a/static/app/utils/useRelease.tsx b/static/app/utils/useRelease.tsx index 861eaaa9c8d35a..23be4cf3566c63 100644 --- a/static/app/utils/useRelease.tsx +++ b/static/app/utils/useRelease.tsx @@ -16,12 +16,12 @@ export function useRelease({ }) { return useQuery({ ...apiOptions.as()( - '/projects/$orgSlug/$projectSlug/releases/$releaseVersion/', + '/projects/$organizationIdOrSlug/$projectIdOrSlug/releases/$version/', { path: { - orgSlug, - projectSlug, - releaseVersion, + organizationIdOrSlug: orgSlug, + projectIdOrSlug: projectSlug, + version: releaseVersion, }, staleTime: Infinity, }