document-api-endpoint
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocument & Type a Sentry API Endpoint
为Sentry API端点编写文档并定义类型
Add or fix OpenAPI docs for a Sentry endpoint with drf-spectacular. Full reference is at https://develop.sentry.dev/backend/api/public/, the most useful section to you will be https://develop.sentry.dev/backend/api/public/#5-method-decorator. This skill captures the non-obvious lessons on top of it. Most of the work is making the declared schema match what the endpoint actually returns. Before documenting, identify which endpoint class serves the route and what it does; the MCP tool that calls it is usually the fastest way to confirm its behavior. Promoting a PRIVATE/EXPERIMENTAL endpoint to PUBLIC is one application (see below).
使用drf-spectacular为Sentry端点添加或修复OpenAPI文档。完整参考文档见https://develop.sentry.dev/backend/api/public/,对您最有用的章节是https://develop.sentry.dev/backend/api/public/#5-method-decorator。本技能总结了文档之外的非显性经验。大部分工作是让声明的架构与端点实际返回的内容匹配。编写文档前,先确定哪个端点类负责该路由及其功能;调用它的MCP工具通常是确认其行为的最快方式。将PRIVATE/EXPERIMENTAL端点升级为PUBLIC是其中一个应用场景(见下文)。
Workflow
工作流程
- Class-level — use the closest existing
@extend_schema(tags=[...])entry.OPENAPI_TAGS - Method-level .
@extend_schema(operation_id=..., parameters=[...], responses={...}, examples=...) - Reuse and
src/sentry/apidocs/parameters.py; ensureexamples/*.pyis set.owner = ApiOwner.<TEAM> - If a legacy covers the path, remove it (see lesson 4).
api-docs/paths/**/*.json - Validate, then verify against the live endpoint (lesson 1).
- 类级别的—— 使用最接近的现有
@extend_schema(tags=[...])条目。OPENAPI_TAGS - 方法级别的。
@extend_schema(operation_id=..., parameters=[...], responses={...}, examples=...) - 复用和
src/sentry/apidocs/parameters.py;确保设置examples/*.py。owner = ApiOwner.<TEAM> - 如果旧版包含该路径,请删除它(见经验4)。
api-docs/paths/**/*.json - 验证,然后对照在线端点进行确认(经验1)。
Lessons
经验总结
1. Carefully compare what the code does vs declared types
1. 仔细对比代码实际行为与声明的类型
Ideally, hit the live endpoint with a real token and diff the keys and types against your TypedDict. Serializers are sometimes inaccurate. Look out for counts coming back as floats instead of integers, IDs declared emitted as strings, nested types declaring the wrong number of fields. Correct the declared type to match runtime.
intbash
curl -s -H "Authorization: Bearer $TOKEN" "https://us.sentry.io/api/0/<endpoint>" | jq 'keys'理想情况下,使用真实令牌访问在线端点,将返回的键和类型与您的TypedDict进行对比。序列化器有时并不准确。注意返回的计数是浮点数而非整数、声明为的ID以字符串形式返回、嵌套类型声明的字段数量错误等情况。修正声明的类型使其与运行时一致。
intbash
curl -s -H "Authorization: Bearer $TOKEN" "https://us.sentry.io/api/0/<endpoint>" | jq 'keys'2. Reuse the canonical response type
2. 复用标准响应类型
Match the codebase's mixin (main class declares required fields). Nullable-vs-absent: = key always present, value may be null; = key only set under a condition (e.g. an query param). Reuse the existing canonical type instead of re-declaring a second or third copy in a . If there's no clean canonical type to reuse (e.g. a payload proxied from another service like vroom/profiling), type it rather than inventing a new mirror, and confirm the shape from the owning service's repo, not just the serializer.
XxxResponseOptional(TypedDict, total=False)T | NoneNotRequired[T]expand*_types.pydict[str, Any]匹配代码库中的混合类(主类声明必填字段)。可空与缺失的区别:表示键始终存在,值可能为null;表示键仅在特定条件下设置(例如查询参数)。复用现有的标准类型,而非在中重复声明第二或第三个副本。如果没有清晰的标准类型可复用(例如从vroom/profiling等其他服务代理的负载),则将其类型定义为,而非创建新的镜像类型,并从所属服务的仓库确认其结构,而不只是依赖序列化器。
XxxResponseOptional(TypedDict, total=False)T | NoneNotRequired[T]expand*_types.pydict[str, Any]3. Infer the type. Avoid cast
and # type: ignore
cast# type: ignore3. 推导类型,避免使用cast
和# type: ignore
cast# type: ignoreWhen a serializer returns a base type plus extra fields, refactor the producing code so the response type is inferred rather than forced.
当序列化器返回基础类型加额外字段时,重构生成代码,使响应类型可被推导而非强制指定。
4. Legacy doc migration is all-or-nothing per path
4. 旧版文档迁移需针对路径完整处理
Delete the file AND its in . drf-spectacular's does not merge HTTP methods, so once any method on a path uses , all legacy methods on that path vanish — migrate every method on the path in one commit.
api-docs/paths/**/*.json$refapi-docs/openapi.jsonAPPEND_PATHS@extend_schema删除文件及其在中的。drf-spectacular的不会合并HTTP方法,因此一旦路径上的任何方法使用,该路径上的所有旧版方法都会消失——请在一次提交中迁移该路径上的所有方法。
api-docs/paths/**/*.jsonapi-docs/openapi.json$refAPPEND_PATHS@extend_schemaPromoting to PUBLIC
升级为PUBLIC
Do the workflow above, then on the concrete endpoint only (leave siblings PRIVATE):
- Bump →
publish_status[<METHOD>]and setPUBLIC.owner = ApiOwner.<TEAM> - Remove the method from in the same change as the flip.
API_OWNERSHIP_ALLOWLIST_DONT_MODIFY - If the endpoint is redundant or being renamed, delete or deprecate the old version in its own change first, then stack the publish on top.
- Note in the PR if scopes widen (→
event:read) — that's drf-spectacular regenerating fromevent:{admin,read,write}, documentation-only.permission_classes
The change reaches the SDK / MCP only after regenerates downstream.
@sentry/apisentry-api-schema完成上述工作流程后,仅针对具体端点(保留同级端点为PRIVATE):
- 将升级为
publish_status[<METHOD>]并设置PUBLIC。owner = ApiOwner.<TEAM> - 在同一变更中,将该方法从中移除。
API_OWNERSHIP_ALLOWLIST_DONT_MODIFY - 如果端点冗余或正在重命名,请先在单独的变更中删除或弃用旧版本,再叠加发布操作。
- 如果权限范围扩大(例如→
event:read),请在PR中注明——这是drf-spectacular从event:{admin,read,write}重新生成的,仅影响文档。permission_classes
变更需等在下游重新生成后,才会同步到 SDK / MCP。
sentry-api-schema@sentry/apiValidate
验证
bash
make build-api-docs
pnpm run validate-api-examples
.venv/bin/pytest -q --reuse-db tests/apidocs/endpoints/<area>/test_<name>.py
.venv/bin/prek run -q --files <changed paths>bash
make build-api-docs
pnpm run validate-api-examples
.venv/bin/pytest -q --reuse-db tests/apidocs/endpoints/<area>/test_<name>.py
.venv/bin/prek run -q --files <changed paths>