PingCode REST API V2 Skill
通过 PingCode REST API V2 操作研发管理平台数据。共 481 个接口、52 个分组。
> V1 与 V2 的差异速览见下方「V1 → V2 迁移对照」。本 skill 以 v2 为主,但同时可以直接调 v1 接口(路径写 /v1/... 即可,不会被改写),
> 便于在尚未升级的私有部署上使用;如需长期跑 v1,设 PINGCODE_API_PREFIX=/v1。
服务地址
| 环境 | REST API 根地址 (PINGCODE_BASE_URL) |
OAuth2 授权页根地址 (PINGCODE_OAUTH2_ROOT) |
V2 支持 |
|---|---|---|---|
| 公有云 | https://open.pingcode.com |
https://open.pingcode.com/oauth2 |
✅ 全量支持 |
| 私有部署 | https://你的域名/open(必须带 /open) |
https://你的域名/oauth2(不带 /open) |
⚠️ 需 v6.13.31 及以上 |
> 私有部署版本要求:V2 接口自私有部署 v6.13.31 版本起提供。
> 低于该版本的私有部署只有 v1 接口,请改用 pingcode skill(v1),
> 或在本 skill 中设 PINGCODE_API_PREFIX=/v1 并调用 /v1/... 路径。
V2 接口统一路径格式:https://{rest_api_root}/v2[/{area}]/{resource}[/{action}]
版本前缀 (PINGCODE_API_PREFIX)
默认 /v2。调用器的路径处理规则:
- 路径已带版本前缀(
/v1/.../v2/...等)→ 原样保留 - 路径不带版本前缀(
pjm/projects)→ 自动补PINGCODE_API_PREFIX PINGCODE_API_PREFIX同时决定令牌接口地址(/v1/auth/token或/v2/auth/token)
因此仍在使用 v1 的私有部署只需加一行:PINGCODE_API_PREFIX=/v1。
实测环境状态(2026-10-20 复核)
| 环境 | v1 | v2 | 说明 |
|---|---|---|---|
公有云 open.pingcode.com |
✅ | ✅ | 同一 token 下双版本并存(/v1/pjm/projects 与 /v2/pjm/projects 均 200) |
| 私有部署(≥ v6.13.31) | ✅ | ✅ | 2026-10-20 实测:v2 全通,v1 保留向后兼容 |
| 私有部署(< v6.13.31) | ✅ | ❌ | 无 v2;/v2/* 会落到文档站 SPA 兜底返回 HTML |
- 版本门槛:私有部署 v6.13.31 起才提供 v2 接口。升级前请用 v1(或设
PINGCODE_API_PREFIX=/v1)。 - 判断某环境是否支持 v2:
GET {base}/v2/auth/token返回 JSON 即有;返回 HTML 即无
(未升级时/v2/*会落到文档站 SPA 兜底)。 - 未达到 v6.13.31 的私有部署:设
PINGCODE_API_PREFIX=/v1并调用/v1/...即可正常使用。 - 私有部署 REST 根必须带
/open;OAuth2 根不带/open(https://域名/oauth2)。
新用户快速开始
1. 配置企业令牌(最简单)
- PingCode 企业后台 → 凭据管理 → 创建应用 → 类型选「企业令牌」(client_credentials)
- 配置应用的数据访问范围(工作项、项目、工时等)
- 填入
.env(模板见.env.example):
PINGCODE_CLIENT_ID=你的Client ID PINGCODE_CLIENT_SECRET=你的Client Secret - 完成,可直接调用所有业务脚本
2. 用户令牌(访问个人数据时需要,如「我的工作项」)
- 另建一个应用,类型选「授权码」(authorization_code),不能复用企业令牌应用
- 回调地址填
http://127.0.0.1:8080(高位端口无需管理员权限,可自动捕获回调) - 填入
.env:
PINGCODE_USER_CLIENT_ID=... PINGCODE_USER_CLIENT_SECRET=... PINGCODE_REDIRECT_URI=http://127.0.0.1:8080 - 运行
python3 scripts/auth_user.py,浏览器自动打开,登录并同意授权 - access_token 与 refresh_token 自动写入
.env,切换为用户令牌模式
> 令牌有效期 30 天,refresh_token 90 天。过期后运行 python3 scripts/refresh_token.py 免交互续期。
3. 个人访问令牌 PAT(个人使用最省事,免 OAuth2 流程)
个人访问令牌(Personal Access Token)是 PingCode 官方支持的第三种鉴权方式:以个人身份调用 REST API,
适合脚本、CI/CD、本地工具等不便走 OAuth2 授权流程的场景。
- PingCode 网页端 → 个人设置 → 个人访问令牌 → 创建
- 填写令牌名称、选择有效期与授权范围(scopes)——服务端会同时校验该用户自身的权限与令牌 scopes,取交集
- 复制令牌(明文仅展示一次,遗失只能重置后重新生成)
- 填入
.env:
PINGCODE_AUTH_MODE=personal_access_token PINGCODE_PERSONAL_ACCESS_TOKEN=你的令牌 - 之后所有脚本/调用器直接可用,无需换 token、无需刷新
# 验证令牌身份(/v2/myself 返回该令牌归属用户)
python3 scripts/api_call.py GET /v2/myself
> 与用户令牌(authorization_code)的区别:PAT 不需要建应用、不需要浏览器授权、不需要 30 天续期,
> 但有效期由创建时选择,过期需重新创建;权限范围也更细(按令牌单独配 scopes)。
> 三种认证方式的取值:PINGCODE_AUTH_MODE=client_credentials | authorization_code | personal_access_token(可简写 pat)。
>
> 已实测(2026-11-04,htz 环境):PAT 直接走 GET /v2/myself、GET /v2/pjm/workitems 及各业务脚本全部正常,
> get_my_tasks.py 会自动以令牌归属用户身份过滤,无需再配 PINGCODE_DEFAULT_USER_ID。
>
> ⚠️ API 根与网页端域名不是一回事:令牌在 htz.pingcode.com 创建,但 REST 调用仍走
> https://open.pingcode.com(https://htz.pingcode.com/open/v2/... 会返回前端 HTML)。
> PINGCODE_BASE_URL 保持 https://open.pingcode.com 即可。
通用 API 调用器(覆盖全部 481 个接口)
这是本 skill 的核心能力,可调用任意 v2 接口。
# 列出所有接口分组(含接口数与命名空间)
python3 scripts/api_call.py --list
# 查看某分组的接口列表
python3 scripts/api_call.py --list-group 工作项
python3 scripts/api_call.py --list-group 迭代
# 按关键字搜索接口(匹配名称 / 路径 / 命名空间)
python3 scripts/api_call.py --search 迭代
python3 scripts/api_call.py --search wiki
# 查看接口详情(参数表 + 响应示例)—— 调接口前必查
python3 scripts/api_call.py --info POST /v2/pjm/workitems
python3 scripts/api_call.py --info GET "/v2/pjm/workitem/workitem_types?project_id=xxx"
# GET 请求(查询参数用 --params key=value,多个参数空格分隔)
python3 scripts/api_call.py GET /v2/pjm/projects --params page_size=50
# POST 请求(--body JSON 字符串 或 --body-file 文件)
python3 scripts/api_call.py POST /v2/pjm/workitems \
--body '{"project_id":"xxx","title":"测试","type_id":"yyy"}'
# PATCH / DELETE(路径参数直接写在 URL 中)
python3 scripts/api_call.py PATCH /v2/pjm/workitems/abc123 --body '{"title":"新标题"}'
python3 scripts/api_call.py DELETE /v2/pjm/workitems/abc123
# 分页遍历全部数据(自动翻页合并 values,推荐用于列表接口)
python3 scripts/api_call.py GET /v2/pjm/projects --fetch-all
# 不带认证头(用于鉴权接口本身)
python3 scripts/api_call.py GET /v2/auth/token --no-auth \
--params grant_type=client_credentials client_id=xxx client_secret=xxx
推荐流程:--search 找接口 → --info 看参数 → 调用。路径可省略 /v2 前缀,脚本会自动补全。
功能脚本
项目 / 工作项
# 项目列表
python3 scripts/get_projects.py
python3 scripts/get_projects.py --keywords "重构" --json
# 指定项目的全部工作项
python3 scripts/get_project_workitems.py --project_name "敏捷示例"
python3 scripts/get_project_workitems.py --project_id 62ded365 --json
# 我的工作项(需用户令牌或 PAT)
python3 scripts/get_my_tasks.py
python3 scripts/get_my_tasks.py --limit 50 --with-image-token # 描述里的图片 token 一并返回(--limit 仅截断显示,获取始终全量)
# 创建工作项(project_id / title / type_id 必填)
python3 scripts/create_workitem.py --project_id <id> --title "修复登录bug" --type_id <type_id> \
--description "Safari 下白屏" --assignee_id <user_id> --start_at 2026-06-18 --end_at 2026-06-25
# 更新工作项
python3 scripts/update_workitem.py --workitem_id <id> --assignee_id <user_id> --state_id <state_id>
# 获取 / 删除单个工作项 —— 支持 ID / 编号 / 短 ID 三种写法,自动识别
python3 scripts/get_workitem.py 5ddf87e6ee2bcb610c950fb3 # 24 位 ID
python3 scripts/get_workitem.py SCRO-78 # 编号(whole_identifier)
python3 scripts/get_workitem.py CLF2026DEVR001-19 # 编号(长格式同样支持)
python3 scripts/get_workitem.py jOruw4Bd # 短 ID(short_id)
python3 scripts/get_workitem.py SCRO-78 --with-image-token # 附带描述图片的 public_image_token
python3 scripts/get_workitem.py SCRO-78 --delete
> 编号解析逻辑:24 位十六进制直接当 ID;否则用 keywords 检索后精确比对 whole_identifier;
> 再不行才翻页扫描 short_id(最多 10 页 / 1000 条)。
> 同编号多命中(实测有重复编号的脏数据)会列出候选并要求用 short_id 消歧,不会瞎猜。
> 取 type_id / state_id / priority_id:
> python3 scripts/api_call.py GET "/v2/pjm/workitem/workitem_types?project_id=<id>"
> python3 scripts/api_call.py GET "/v2/pjm/workitem/workitem_states?project_id=<id>&workitem_type_id=<tid>"
迭代 / 工时 / 评论 / 成员
python3 scripts/sprints.py list --project_id <id> --status in_progress
python3 scripts/sprints.py create --project_id <id> --name "Sprint 3" \
--start_at 2026-07-01 --end_at 2026-07-14 --assignee_id <user_id>
python3 scripts/sprints.py update --sprint_id <sid> --status in_progress
python3 scripts/workloads.py types
python3 scripts/workloads.py create --principal_id <workitem_id> --duration 4 --report_at 2026-06-18
python3 scripts/workloads.py list --start_at 2026-06-01 --end_at 2026-06-30
python3 scripts/comments.py create --type workitem --id <workitem_id> --content "已复现"
python3 scripts/comments.py list --type workitem --id <workitem_id>
python3 scripts/comments.py delete <comment_id> --type workitem --id <workitem_id>
python3 scripts/get_members.py --keyword "张三" # 拿 user_id 用于 assignee_id 等
python3 scripts/get_members.py --json
附件管理
# 上传一个文件(multipart)
python3 scripts/upload_attachment.py upload \
--type workitem --id <workitem_id> --file ./报告.pdf
# 上传到评论下(先 comments.py create 拿 comment_id)
python3 scripts/upload_attachment.py upload \
--type workitem --id <workitem_id> --file ./截图.png --comment-id <comment_id>
# 上传一个代码段(format 有枚举限制,实测需挂评论)
python3 scripts/upload_attachment.py snippet \
--type workitem --id <workitem_id> \
--title "验证脚本" --format python --content 'print(1)' --comment-id <comment_id>
# 列表 / 查询 / 删除
python3 scripts/upload_attachment.py list --type workitem --id <workitem_id>
python3 scripts/upload_attachment.py get <attachment_id> --type workitem --id <workitem_id>
python3 scripts/upload_attachment.py delete <attachment_id> --type workitem --id <workitem_id>
principal_type(v2 命名,注意与 v1 不同——无下划线):
| principal_type | 主体 | 写权限 scope |
|---|---|---|
workitem |
工作项 | pcp:write:pjm:workitem |
workitem_review |
工作项评审 | pcp:write:pjm:project |
testcase |
测试用例 | pcp:write:testhub:testcase |
testcase_review |
用例评审 | pcp:write:testhub:testcase(推断) |
testrun |
测试执行记录 | pcp:write:testhub:testplan |
idea |
需求 | pcp:write:ship:idea |
idea_review |
需求评审 | pcp:write:ship:idea(推断) |
ticket |
工单 | pcp:write:ship:ticket |
page |
Wiki 页面 | pcp:write:wiki:page |
deliverable_target |
工作项交付物 | pcp:write:pjm:workitem(推断) |
> v1 对照:work_item / test_case / test_run / work_item_deliverable(带下划线),且没有 review 系主体。
> 未提供 /v2/attachments 的老私有部署,脚本会自动按 v1 命名回退到 /v1/attachments 并提示。
>
> ⚠️ 代码段接口的 comment_id 文档标「否」,但实测(v1)不带会 400 100039——代码段实际挂在评论下,
> 建议先 comments.py create 建评论再传;删除评论会级联删除其下代码段。
周报
python3 scripts/generate_weekly_report.py
python3 scripts/generate_weekly_report.py --project_name "PingCode 重构" --days 7
python3 scripts/generate_weekly_report.py --output /tmp/weekly_report.md
鉴权
python3 scripts/auth_user.py # 自动模式(推荐)
python3 scripts/auth_user.py --manual # 手动粘贴回调 URL
python3 scripts/auth_user.py --redirect_uri http://127.0.0.1:8080
python3 scripts/refresh_token.py # 用 refresh_token 续期
V1 → V2 迁移对照
命名空间(area)重写
V2 按业务域重新划分命名空间,路径前缀由 /v1/<module> 变为 /v2/<area>:
| V2 命名空间 | 含义 | 典型资源 |
|---|---|---|
/v2/pjm |
项目管理(122 个) | projects、workitems、sprints、boards、releases |
/v2/ship |
产品/需求/工单(113 个) | products、ideas、tickets 及其配置 |
/v2/testhub |
测试(77 个) | testlibs、testcases、testplans、testruns |
/v2/devops |
DevOps(54 个) | 代码仓库/分支/评审/提交/构建/部署/环境 |
/v2/directory |
组织(23 个) | users(企业成员)、departments、teams、jobs、roles |
/v2/wiki |
知识库(19 个) | spaces、pages |
/v2/reviews /v2/workloads /v2/comments /v2/attachments /v2/participants /v2/relations |
横切资源 | 评论/工时/附件/关注人/关联 |
/v2/auth /v2/myself /v2/security /v2/activities |
鉴权与全局 | 令牌、个人信息、日志 |
常见路径对照
| V1 | V2 |
|---|---|
/v1/pjm/work_items |
/v2/pjm/workitems |
/v1/pjm/work_item_types |
/v2/pjm/workitem_types |
/v1/pjm/work_item_states |
/v2/pjm/workitem_states |
/v1/project/projects |
/v2/pjm/projects |
/v1/pjm/sprints |
/v2/pjm/sprints |
/v1/directory/users |
/v2/directory/users |
/v1/auth/token |
/v2/auth/token |
/v1/comments(按 type 分) |
/v2/comments + principal_type / principal_id |
/v1/workloads |
/v2/workloads |
/v1/wiki/spaces |
/v2/wiki/spaces |
字段变化(易踩坑)
| 变化点 | V1 | V2 |
|---|---|---|
| 日期字段 | start_at / end_at(裸时间戳) |
start / due(对象 {"date": 时间戳, "with_time": 0}) |
| 工时登记日期 | report_at(时间戳) |
report_at(对象 {"date": 时间戳}) |
| 评论主体 | 按实体类型拆路径 | 统一 /v2/comments + principal_type |
| 工作项编号 | identifier |
whole_identifier(如 SCR-5)、short_id |
| 路径占位符 | {work_item_id} |
{workitem_id}(去掉下划线) |
用脚本时无需关心转换——_config.to_date_object() 会自动把 2026-06-18 转成 V2 日期对象。
API 参考
references/api_reference.md:全部 481 个接口的完整参考(路径、方法、权限、Scopes、参数表、响应示例)data/api_catalog.json:机器可读的接口目录,供api_call.py使用tools/build_reference.py:从 open.pingcode.com 重新拉取并生成上述文件
接口分组索引(52 个)
| # | 分组 | 接口数 | 命名空间 |
|---|---|---|---|
| 1 | 工作项配置 | 38 | pjm |
| 2 | 工作项 | 30 | pjm |
| 3 | 工单配置 | 30 | ship |
| 4 | 用例配置 | 28 | testhub |
| 5 | 产品 | 27 | ship |
| 6 | 需求配置 | 26 | ship |
| 7 | 计划 | 18 | testhub |
| 8 | 项目配置 | 18 | pjm |
| 9 | 项目 | 17 | pjm |
| 10 | 看板 | 15 | pjm |
| 11 | 工单 | 14 | ship |
| 12 | 用例 | 14 | testhub |
| 13 | 测试库 | 13 | testhub |
| 14 | 需求 | 13 | ship |
| 15 | 类别与分组 | 10 | categories,sections |
| 16 | 页面 | 10 | wiki |
| 17 | 空间 | 9 | wiki |
| 18 | 团队 | 8 | directory |
| 19 | 评审 | 8 | reviews |
| 20 | 发布 | 7 | pjm |
| 21 | 工时 | 7 | workload_types,workloads |
| 22 | 权限 | 7 | permission |
| 23 | 构建记录 | 6 | devops |
| 24 | 环境 | 6 | devops |
| 25 | 部署 | 6 | devops |
| 26 | 代码仓库 | 5 | devops |
| 27 | 代码分支 | 5 | devops |
| 28 | 代码评审 | 5 | devops |
| 29 | 企业成员 | 5 | directory |
| 30 | 托管平台 | 5 | devops |
| 31 | 托管平台用户 | 5 | devops |
| 32 | 拉取请求 | 5 | devops |
| 33 | 迭代 | 5 | pjm |
| 34 | 部门 | 5 | directory |
| 35 | 附件 | 5 | attachments |
| 36 | 产品配置 | 4 | ship |
| 37 | 关注人 | 4 | participants |
| 38 | 关联 | 4 | relations |
| 39 | 实体扩展属性 | 4 | entity_properties |
| 40 | 计划配置 | 4 | testhub |
| 41 | 评论 | 4 | comments |
| 42 | 授权码 | 3 | auth,oauth2 |
| 43 | 提交 | 3 | devops |
| 44 | 提交引用 | 3 | devops |
| 45 | 日志 | 2 | security |
| 46 | 活动记录 | 2 | activities |
| 47 | 职位 | 2 | directory |
| 48 | 表达式 | 2 | expression |
| 49 | 角色 | 2 | directory |
| 50 | 个人 | 1 | myself |
| 51 | 企业 | 1 | directory |
| 52 | 客户端凭据 | 1 | auth |
注意事项
- 凭证安全:凭证存于 skill 根目录
.env,通过_config.py自动加载,环境变量可覆盖。 - 认证模式:
PINGCODE_AUTH_MODE三选一:
-client_credentials(默认,企业令牌,需PINGCODE_CLIENT_ID+PINGCODE_CLIENT_SECRET)
-authorization_code(用户令牌,需先跑auth_user.py)
-personal_access_token(个人访问令牌,可简写pat,需PINGCODE_PERSONAL_ACCESS_TOKEN;
在 PingCode 个人设置中创建,有效期与 scopes 由创建时指定,明文只展示一次) - 用户令牌应用类型:必须创建 authorization_code 类型应用,不能复用企业令牌应用;回调地址需与后台一致。
- 私有部署:
PINGCODE_BASE_URL必须带/open,否则返回前端 HTML 而非 JSON。 - 拿到 HTML 而不是 JSON:说明路径没命中任何 API 路由,被前端/文档站 SPA 兜底。常见原因:
- 私有部署忘了加/open前缀;
- 该环境没有 v2(/v2/auth/token返回 HTML 即可确认),改用/v1/...+PINGCODE_API_PREFIX=/v1;
- 路径里的版本号与部署版本不匹配。 - GET 不带 Content-Type:部分私有部署版本对携带
Content-Type: application/json的 GET 令牌请求
会报100021 'grant_type'类型不支持。调用器已修复(无请求体时不发该头)。 - 授权码流程卡在
/open/oauth2/authorized空白页(私有部署升级 v2 后实测):
点「授权」后浏览器跳到https://域名/open/oauth2/authorized?...&transaction_id=...,
该路径被/open下的文档站 SPA 接管,页面空白、拿不到 code。
绕法:把地址里的/open去掉,直接访问https://域名/oauth2/authorized?...&transaction_id=...
即可正常跳回redirect_uri并带上 code。auth_user.py检测到这种情况会自动给出修正后的地址。
7.1 回调地址登记为远端域名时拿不到 code(用户反馈,v1.0.4 复现):
若应用后台只登记了https://域名/...,授权后浏览器会被直接重定向回工作台,地址栏没有 code,
本地auth_user.py的服务器也收不到回调(只能去浏览器控制台翻)。
正确做法:在应用后台额外新增一条本机回调(如http://127.0.0.1:8080,不要删掉现有远端地址,
否则照旧提示词授权的同事会全部失败),然后python3 scripts/auth_user.py --redirect_uri http://127.0.0.1:8080。
auth_user.py启动时会预检回调地址并打印该提示;传参错误导致的redirect_urimismatch 也多半是这个原因。 code一次性:换过令牌后立即失效(再次使用报100031 'code'已失效),需重新走授权。- 403
100027 'access_token'权限不足:不是凭证问题,是 OAuth 应用后台勾选的数据范围不含该资源。 - 频率限制(V2 更严格):
- 公有云两层限流:企业 RPM(免费版 200;付费版 500 + 用户数×20)+ 单接口突发 RPS 30。
- 响应头X-RateLimit-Team-Remaining/X-RateLimit-Burst-Remaining可用于提前降速。
- 触发 429 时读X-RateLimit-Retry-After延迟重试——_config.request()已内置最多 3 次自动重试。
- 私有部署默认每人每分钟 200,触限返回X-PC-Retry-After。
- 建议优先使用批量接口(如/bulk/create、/bulk/set)并缓存不常变数据。 - 分页三个实测坑(已内置进
--fetch-all与fetch_all_values()):
-page_index从 0 开始;
- 部分接口忽略page_size,每页固定 30 条;
-total可能不准 —— 以「本页条数 < 首页条数」为终止条件,不要用page * page_size >= total。 - 日期字段:V2 的
start/due/report_at是对象,脚本的--start_at/--end_at接受2026-06-18等可读格式并自动转换。 - Token 有效期:access_token 30 天,refresh_token 90 天;删除应用或重置 Secret 会立即失效。
- 工作项状态/优先级:需传 ID,且状态必须同时满足状态方案与状态流转的约束。
- 零依赖:脚本优先使用
requests,缺失时自动回退标准库urllib,无需额外安装。
重新生成接口文档
当 open.pingcode.com 文档更新后:
cd ~/.workbuddy/skills/pingcode-v2
curl -s -L -o tools/api_data.js https://open.pingcode.com/api_data.js
curl -s -L -o tools/api_project.js https://open.pingcode.com/api_project.js
python3 tools/build_reference.py