3. Jira Issue REST API实战

Jira Issue REST API 是 Atlassian 生态集成中最核心的一组接口。无论是同步外部系统的工单、自动创建缺陷、批量迁移历史数据,还是构建自定义看板,最终都要落到对 Issue 资源的增删改查上。本节以 Jira Cloud 的 REST API v3 为基准,围绕创建、查询、更新、删除、批量操作和字段元数据获取六类调用展开,并给出可复用的错误处理策略。

一、认证与基础约定

Jira Cloud 推荐使用 API Token 配合 Basic Auth,或使用 OAuth 2.0 的 3LO。以 API Token 为例,请求头为 Authorization: Basic base64(email:api_token),同时必须带 Accept: application/json 与 Content-Type: application/json。所有 Issue 相关接口的基础路径为 https://{your-domain}.atlassian.net/rest/api/3/。注意 v3 的富文本字段(如 description)使用 ADF(Atlassian Document Format)而非纯字符串,这是与 v2 最易踩坑的差异。

二、创建问题:POST /issue

创建问题的核心是构造 fields 对象,其中 project.key、issuetype.name、summary 为必填。description 在 v3 中需写成 ADF 文档结构。下面是一个可直接参考的示例请求体:

POST /rest/api/3/issue
{
  "fields": {
    "project": { "key": "OPS" },
    "issuetype": { "name": "Bug" },
    "summary": "登录接口偶发 502",
    "description": {
      "type": "doc", "version": 1,
      "content": [{
        "type": "paragraph",
        "content": [{ "type": "text", "text": "复现步骤:并发 50 时出现。" }]
      }]
    },
    "priority": { "name": "High" },
    "labels": ["api", "regression"],
    "customfield_10016": 8
  }
}

成功返回 201 Created,响应体包含 id、key 和 self。若字段值非法,会返回 400 并在 errors 中逐字段说明原因,例如 {"errors":{"customfield_10016":"Field does not support value"}}。因此创建前应先调用字段元数据接口确认字段类型与可选值。

三、查询问题:GET /search 与单条获取

获取单条问题使用 GET /issue/{issueIdOrKey},可通过 fields 与 expand 参数裁剪返回内容,减少传输量。批量查询使用 GET /search(新版为 POST /search/jql),关键参数包括 jql、startAt、maxResults、fields。例如:

GET /rest/api/3/search?jql=project=OPS AND status="In Progress"
    &fields=summary,status,assignee&maxResults=50&startAt=0

响应中的 total 表示匹配总数,issues 为当前页数据。分页时以 startAt + maxResults 递增,直到取满 total。JQL 中的字段名、状态名必须与实例配置一致,否则返回 400 并提示 "Field 'xxx' does not exist"。

四、更新与删除

更新使用 PUT /issue/{issueIdOrKey},请求体同样为 fields 结构,只传需要修改的字段即可,未传字段保持不变。若需追加而非覆盖,可使用 update 语法配合 add/set/remove 操作。成功返回 204 No Content。删除使用 DELETE /issue/{issueIdOrKey},默认移入回收站,加 ?deleteSubtasks=true 可级联删除子任务,成功同样返回 204。删除是不可逆操作,生产环境务必先做权限校验与备份。

五、批量操作

批量创建使用 POST /issue/bulk,请求体为 issueUpdates 数组,单次上限 50 条。批量更新字段使用 POST /issue/bulk 的更新变体或 PUT /issue/{key} 循环调用;批量删除则通过 DELETE /issue 配合 JQL 或 ID 列表实现。批量接口的响应会区分成功与失败条目,必须逐条检查 errors,不能只看 HTTP 状态码。

六、字段元数据获取

字段元数据是保证创建/更新成功的前提。常用接口有:GET /field 列出所有字段及 ID;GET /issue/createmeta/{projectIdOrKey}/issuetypes/{issueTypeId} 返回该问题类型下可用字段、是否必填、允许值;GET /issue/{issueIdOrKey}/editmeta 返回当前问题可编辑字段。自定义字段以 customfield_xxxxx 形式出现,必须通过元数据接口映射到业务含义,硬编码字段 ID 是常见故障源。

Jira Issue REST API 调用链与错误处理 集成客户端 API Token / OAuth 字段元数据 /field · createmeta Issue 核心操作 POST /issue 创建 GET /search 查询 PUT /issue 更新 批量操作 /issue/bulk ≤ 50 HTTP 响应 201 / 200 / 204 错误处理策略 400 字段非法 → 读 errors 逐字段修正,先查元数据 401/403 认证或权限 → 检查 Token 与项目角色 429 限流 → 读 Retry-After,指数退避重试 重试 / 修正 幂等键防重复 关键约束: v3 富文本用 ADF;自定义字段需元数据映射;批量接口逐条校验 errors;删除默认入回收站,deleteSubtasks 级联。 分页:startAt + maxResults 递增至 total;限流:429 + Retry-After 退避。

七、错误处理与重试

Jira API 的错误码语义清晰:400 表示请求体或 JQL 非法,需读取 errors 与 errorMessages;401 为认证失败;403 为权限不足;404 为 Issue 或项目不存在;429 为触发限流,响应头 Retry-After 给出等待秒数。工程上应统一封装一个请求函数,对 429 与 5xx 采用指数退避重试,对 4xx 中的参数类错误直接抛出并记录字段级原因,避免无意义重试。

建议在集成层维护一张“字段 ID → 业务含义”的映射表,并在启动时调用 GET /field 校验映射是否失效。这样当管理员调整自定义字段时,集成能快速定位问题,而不是在创建时报出难以理解的 customfield 错误。
批量创建时,即使 HTTP 返回 201,也要遍历 errors 数组确认每条是否真正成功。部分失败不会改变整体状态码,忽略这一点会导致数据静默丢失。

综合来看,Jira Issue REST API 的实战要点可以归纳为:先查元数据再写数据,创建与更新严格对齐字段类型,查询用 JQL 与分页控制数据量,批量操作逐条校验,删除前确认权限与级联范围,错误处理区分可重试与不可重试。把这六类调用封装成稳定的客户端,后续的 Webhook、自动化与跨系统同步才有可靠基础。