Part-DB 2.20.2 API 使用详解

Part-DB 2.20.2 REST API 实测:Token 创建与四级权限矩阵、Bearer 鉴权、核心资源 CRUD、JSON-LD 分页过滤与 406 格式坑,2026-10-24 实测。

Part-DB库存管理自托管REST API2026/10/24

Part-DB 2.20.2 API 使用详解

目标:本文讲解 Part-DB 2.20.2 内置 REST API 的鉴权、令牌体系、核心资源操作、格式细节与权限矩阵,全部示例基于 2026-10-24 对 v2.20.2 实例的真实请求与响应实测。组件背景见 《Part-DB 2.20.2 介绍与选型指南》,部署见 《Part-DB 2.20.2 Docker Compose 部署指南》,令牌相关的系统配置见 《Part-DB 2.20.2 配置参数详解》。

一、环境信息

项目内容
API 版本Part-DB v2.20.2 实测(Symfony v7.4.21)
API 框架API Platform(REST,支持 JSON-LD/Hydra)
基础路径/api
状态官方文档标注 beta——接口结构未来版本可能变化,集成方应锁定 Part-DB 版本并做回归
规范描述OpenAPI:/api/docs.json(实测 57 个资源路径,约 692 KB);JSON-LD 版:/api/docs.jsonld;交互文档页:/api/
验证方式curl 直接调用实例(Bearer Token),覆盖创建/读取/更新/删除/分页/权限边界

二、API 总览

Part-DB 的 REST API 覆盖元件全生命周期数据,实测 OpenAPI 描述中的资源路径包括(节选):

  • 元件与库存:/api/parts、/api/parts/{id}、/api/parts/{id}/orderdetails、/api/parts/{id}/part_lots、/api/parts/{id}/project_bom_entries
  • 主数据:/api/categories、/api/footprints、/api/manufacturers、/api/manufacturing_statuses、/api/measurement_units、/api/currencies、/api/suppliers、/api/storelocations(各含 {id}、{id}/children 树形端点)
  • 订单与价格:/api/orderdetails、/api/pricedetails
  • 附件:/api/attachments、/api/attachment_types
  • 标签与工具:/api/label_profiles、/api/labels/generate、/api/tokens/current
  • 项目/BOM:/api/projects、/api/project_bom_entries

能力特性(v2.20.2 实测口径):

  • 标准方法:GET(列表/详情)、POST(创建)、PATCH(部分更新)、DELETE(删除)。
  • 内容协商:JSON-LD(application/ld+json,带 Hydra 上下文与分页)与纯 JSON(application/json)双格式。
  • 分页:?page=N&itemsPerPage=M;过滤:按字段名等值/前缀查询;排序:order[字段]。
  • 错误体统一为 RFC 7807 风格({"title": ..., "detail": ..., "status": ...},JSON-LD 错误附 Hydra 上下文)。
  • ⚠️ 官方 API 文档(api/intro)提到过 search、statistics 等特殊端点,但 v2.20.2 实例实测 /api/statistics、/api/search 均返回 404——以实测为准,计划使用这些端点的集成需先自测。

三、前置条件:开启权限与创建 API Token

3.1 用户权限位

API 访问受 Part-DB 权限系统控制,涉及三个独立开关(本系列实测中 admin 用户默认没有开启 API 权限,首次使用必须手动开启):

  1. Access API(访问 API):允许该用户通过 API 读取数据;
  2. Manage API tokens(管理 API 令牌):允许在用户设置中创建/吊销自己的令牌;
  3. 令牌能力还受令牌自身级别(见 3.2)与 MCP 写开关(MCP_EDITING_ENABLED,仅 MCP 场景)约束。

入口:管理员在「用户管理 → 对应用户 → 权限 → API 组」勾选上述权限位(v2.20 设置页中为 22-1 / 22-3 两行)。

3.2 创建 Token(Web 界面)

路径:登录后右上角用户菜单 → Settings → API Tokens → Create new API token。表单三要素(实测表单字段):

字段说明
Name令牌名(仅用于识别,如 kicad-integration)
Level权限级别:1 Read-Only / 2 Edit / 3 Admin / 4 Full
Valid until过期时间(可留空表示不过期)

提交后系统只显示一次完整令牌明文(形如 tcp_xxx...),请立即保存;之后界面仅可见令牌名与级别。令牌格式实测前缀为 tcp_。

实测创建回显(截取):

Your token:  tcp_315341f9...
Level:       EDIT (2)

3.3 替代方式:OAuth2

若不想手工发令牌,可启用内置 OAuth2 授权服务器(OAUTH_SERVER_ENABLED=1 + OAUTH2_ENCRYPTION_KEY),外部应用走登录授权流自行获取 Bearer token,适合多客户端与 AI Agent 场景;启用方法与安全约束见配置篇 4.11。

四、认证与首次调用

所有 API 请求带 Authorization: Bearer <token> 头。用令牌自检端点验证连通性(实测):

$ TOKEN=tcp_315341f9...
$ curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8133/api/tokens/current
{"name":"docs-api-test","user":{"id":2,"name":"admin"},"level":2,"last_time_used":"2026-10-24T02:34:35+00:00"}

错误行为实测:

  • 无凭据:HTTP 401,{"title":"Unauthorized","detail":"Authentication is required. Please pass a valid API token in the Authorization header."}
  • 令牌错误:HTTP 401(响应体为空)。
  • 令牌有效但越权:HTTP 403,{"title":"An error occurred","detail":"Access Denied.","status":403,"type":"/errors/403"}。

五、核心资源操作(实测)

5.1 创建主数据:类别与制造商

$ curl -s -X POST http://localhost:8133/api/categories \
    -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
    -d '{"name": "Resistors", "comment": "created via REST API test"}'

实测响应(201 Created,截取):

{"name":"Resistors","id":1,"comment":"created via REST API test",
 "addedDate":"2026-10-24T02:34:35+00:00","lastModified":"2026-10-24T02:34:35+00:00",
 "partname_hint":"","partname_regex":"","part_ipn_prefix":"","full_path":"Resistors", ...}
$ curl -s -X POST http://localhost:8133/api/manufacturers \
    -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
    -d '{"name": "Yageo"}'

实测响应(201):{"name":"Yageo","id":1,"full_path":"Yageo", ...}

5.2 创建元件并关联主数据

关联主数据用 IRI 路径(/api/<资源>/<id>)作为值:

$ curl -s -X POST http://localhost:8133/api/parts \
    -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
    -d '{"name": "RC0603FR-0710KL",
         "description": "10kΩ 1% 0603 thick film chip resistor",
         "category": "/api/categories/1",
         "manufacturer": "/api/manufacturers/1"}'

实测响应(201,截取):

{"name":"RC0603FR-0710KL","id":1,"description":"10kΩ 1% 0603 thick film chip resistor",
 "category":{"name":"Resistors","id":1,"full_path":"Resistors"},
 "manufacturer":{"name":"Yageo","id":1,"full_path":"Yageo"},
 "minamount":0.0,"total_instock":0.0,"partLots":[],"orderdetails":[], ...}

5.3 查询:列表、详情与集合

# 纯 JSON 列表(Accept: application/json)
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" \
       http://localhost:8133/api/categories
[{"name":"Resistors","id":1, ...}]

# 详情
$ curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8133/api/parts/1
{"name":"RC0603FR-0710KL","id":1, ...}

JSON-LD 格式(Hydra 集合,带分页元数据):

$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/ld+json" \
       "http://localhost:8133/api/parts.jsonld"

实测响应(截取):

{"@context":"/api/contexts/Part","@id":"/api/parts","@type":"hydra:Collection",
 "hydra:totalItems":1,
 "hydra:member":[{"@id":"/api/parts/1","@type":"Part","name":"RC0603FR-0710KL",
   "category":{"@id":"/api/categories/1","@type":"Category","name":"Resistors"}, ...}]}

5.4 更新:PATCH

部分更新用 PATCH + JSON Merge Patch 媒体类型(实测生效):

$ curl -s -X PATCH http://localhost:8133/api/parts/1 \
    -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/merge-patch+json" -H "Accept: application/json" \
    -d '{"description": "10kΩ 1% 0603 SMD resistor (updated via PATCH)"}'

实测响应(200):"description":"10kΩ 1% 0603 SMD resistor (updated via PATCH)",lastModified 同步更新。

5.5 删除:DELETE

$ curl -s -o /dev/null -w '%{http_code}\n' -X DELETE http://localhost:8133/api/categories/2 \
    -H "Authorization: Bearer $TOKEN"
204
# 删除后再查
$ curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8133/api/categories/2
{"title":"An error occurred","detail":"Not Found","status":404,"type":"/errors/404"}

实测:DELETE 成功返回 204 无响应体,删除后的资源返回 404。

六、格式细节与常见 406 坑

Part-DB API 对「URL 后缀」与「Accept 头」的组合有严格校验,实测三条规则:

  1. 无后缀 + 任意 Accept:按 Accept 协商;不带 Accept 头时默认返回 application/ld+json(实测响应头确认)。
  2. .json 后缀 + Accept: application/json:返回纯 JSON 数组/对象(200)。
  3. .jsonld 后缀 + Accept: application/json:406 拒绝(实测响应):
{"@context":"/api/contexts/Error","@id":"/api/errors/406","@type":"hydra:Error",
 "detail":"Requested format \"application/json\" is not supported. Supported MIME types are \"application/ld+json\".",
 "status":406,"type":"/errors/406"}

OpenAPI 规范文档同理:/api/docs.json 必须带 Accept: application/vnd.openapi+json(实测 application/json 会被 406 拒绝),JSON-LD 版用 /api/docs.jsonld + application/ld+json。

💡 集成建议:脚本里明确设置 Accept 头,不要依赖默认值;工具链要读 OpenAPI 规范时固定用 curl -H "Accept: application/vnd.openapi+json" /api/docs.json。

七、分页、过滤与排序

  • 分页:?page=1&itemsPerPage=20。JSON-LD 响应中 hydra:totalItems 为总数,分页时出现 hydra:view(实测 {"@id":"/api/categories.jsonld?itemsPerPage=1","@type":"hydra:PartialCollectionView"})。
  • 按名称过滤:/api/parts.jsonld?name=RC0603%(% 为 SQL 通配,需 URL 编码为 %25)。同样必须配 Accept: application/ld+json。
  • 按关联过滤:/api/parts?category=1,2++——单个 ID 精确匹配,++ 前缀表示含子类别递归。
  • 排序:/api/parts?order[name]=ASC。
  • 字段裁剪:/api/parts?properties[]=name,description 减少响应体积。
  • 调试辅助:任意请求加 &_comment=1 响应会附解释对象。

八、令牌权限矩阵(实测)

操作Read-Only (1)Edit (2)Admin (3)Full (4)
GET 列表/详情200 ✓(实测)200 ✓200 ✓200 ✓
POST 创建403(实测 Access Denied)201 ✓201 ✓201 ✓
PATCH 更新403200 ✓200 ✓200 ✓
DELETE 删除403204 ✓(实测可删主数据)204 ✓204 ✓

行为要点:

  • Read-Only 令牌写操作一律 403,与用户自身权限无关——令牌级别是上限,实际能力 = min(用户权限, 令牌级别)。
  • Edit 级别即可执行删除(实测 DELETE 类别返回 204),给外部系统发令牌时请优先 Read-Only,写场景再发 Edit,Full 仅用于脚本管理令牌本身。
  • MCP 场景额外受 MCP_ENABLED / MCP_EDITING_ENABLED 两个系统开关约束(配置篇 4.11)。

九、常见问题

  • 401 但确定令牌没输错:检查 Authorization 头格式(Bearer 后有空格);确认令牌未过期、未被吊销;用户 API 权限位是否被撤回。
  • 403 越权:读操作 403 → 用户缺「Access API」权限位;写操作 403 → 令牌级别不足(Read-Only)或用户无对应写权限位。
  • 406 Not Acceptable:URL 后缀与 Accept 头不匹配(最常见:.jsonld 配了 application/json),见第六节对照表。
  • /api/search 404:v2.20.2 实测该端点不存在,用 ?name=<模式> 过滤替代;跨字段搜索暂走 Web 界面或 OpenAPI 中确认最新可用端点。
  • 令牌明文丢了:无法找回,吊销后重新创建即可(Manage API tokens 权限 + 设置页操作)。
  • KiCad 插件连不上:确认实例的 DEFAULT_URI 与实际访问地址一致,令牌级别至少 Edit,且 KiCad 插件走的 /api/parts 路径可用。

十、参考链接