69a0149bbe
Search: - migration 0009: trigram GIN index on brand.name + btree on country_of_origin - SearchProducts: typo-tolerant word_similarity matching (>=0.42) on top of ILIKE substring + barcode; new brand/country filters; rank by similarity * (0.5 + quality_score). Response gains country_of_origin, quality_score and per-result relevance score. - public search UI: brand/country filter inputs; show country in results Docs: - serve embedded OpenAPI 3 spec at GET /api/v1/openapi.json (not rate limited) - ApiDocs page: auth + rate-limit section, updated search params/response - docs/api.md developer guide Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
118 lines
4.0 KiB
Markdown
118 lines
4.0 KiB
Markdown
# OpenGoods 公共 API 开发者文档
|
||
|
||
天工商品档案公共仓(OpenGoods)提供**公开、只读**的商品事实 REST API:按条码/名称查询商品的客观资料(品牌、品类、净含量、产地、配料、营养成分、Nutri-Score、厂商建议零售价快照等)。返回均为 JSON(UTF-8)。**本服务不含任何购买/交易接口。**
|
||
|
||
- 基础地址:`https://goods.tangshasha.com/api/v1`
|
||
- 机器可读规范(OpenAPI 3):`GET /api/v1/openapi.json`
|
||
- 交互式文档:站点「API 调用说明」页
|
||
|
||
## 鉴权
|
||
|
||
API 默认**匿名可用**,无需任何凭证即可调用。匿名请求按来源 IP 计入一个较低的默认每分钟额度。
|
||
|
||
如需更高额度并让用量归属到你,可向运营方申请一枚 **API Key**(形如 `og_live_xxxxxxxx`),请求时二选一携带:
|
||
|
||
```bash
|
||
curl -H "X-API-Key: og_live_xxxxxxxx" \
|
||
"https://goods.tangshasha.com/api/v1/products/search?q=牛奶"
|
||
|
||
# 或
|
||
curl -H "Authorization: Bearer og_live_xxxxxxxx" \
|
||
"https://goods.tangshasha.com/api/v1/products/search?q=牛奶"
|
||
```
|
||
|
||
> 仅在创建时返回一次明文 Key,请妥善保存。服务端只存储其 SHA-256 哈希。
|
||
|
||
## 限流
|
||
|
||
采用**固定窗口**限流(每分钟)。每个响应都会回写以下响应头:
|
||
|
||
| 响应头 | 含义 |
|
||
| --- | --- |
|
||
| `X-RateLimit-Limit` | 当前窗口允许的最大请求数 |
|
||
| `X-RateLimit-Remaining` | 当前窗口剩余可用次数 |
|
||
| `X-RateLimit-Reset` | 窗口重置的 Unix 时间戳(秒) |
|
||
| `Retry-After` | 仅在超额(429)时返回,建议等待的秒数 |
|
||
|
||
- 超过额度:`429 Too Many Requests`,错误码 `rate_limited`。
|
||
- Key 无效或已吊销:`401 Unauthorized`,错误码 `invalid_api_key`。
|
||
|
||
## 错误格式
|
||
|
||
非 2xx 响应体统一为:
|
||
|
||
```json
|
||
{ "error": { "code": "not_found", "message": "…", "request_id": "…" } }
|
||
```
|
||
|
||
## 分页
|
||
|
||
列表类接口支持 `page`(默认 `1`)与 `size`(默认 `20`,最大 `100`),响应含 `page`/`size`/`total`。
|
||
|
||
## 端点
|
||
|
||
### `GET /products/search` — 搜索商品
|
||
|
||
按名称做三元组(trigram)模糊搜索,**可容忍错别字**;支持品类/品牌/产地过滤;结果按相关度(名称相似度 × 数据质量分)排序。
|
||
|
||
| 参数 | 必填 | 说明 |
|
||
| --- | --- | --- |
|
||
| `q` | 否 | 关键词(名称/条码),模糊匹配;留空则按质量分返回全部 |
|
||
| `category` | 否 | 品类编码(含子树),如 `food.beverages` |
|
||
| `brand` | 否 | 品牌名(模糊匹配),如 `Ferrero` |
|
||
| `country` | 否 | 产地前缀(不区分大小写),如 `China` |
|
||
| `page` | 否 | 页码,默认 1 |
|
||
| `size` | 否 | 每页条数,默认 20,最大 100 |
|
||
|
||
```bash
|
||
curl "https://goods.tangshasha.com/api/v1/products/search?q=nutela&country=Italy"
|
||
```
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"id": "…",
|
||
"gtin": "3017624010701",
|
||
"name": "Nutella",
|
||
"brand": "Ferrero",
|
||
"category_path": "food.snacks.chocolate",
|
||
"country_of_origin": "Italy",
|
||
"quality_score": 0.81,
|
||
"score": 0.71
|
||
}
|
||
],
|
||
"page": 1,
|
||
"size": 20,
|
||
"total": 1
|
||
}
|
||
```
|
||
|
||
`score` 为名称相关度(提供 `q` 时返回,0–1),未提供 `q` 时为 `null`。
|
||
|
||
### `GET /products/barcode/{gtin}` — 按条码查询
|
||
|
||
```bash
|
||
curl "https://goods.tangshasha.com/api/v1/products/barcode/5449000000996"
|
||
```
|
||
|
||
### `GET /products/{id}` — 商品详情
|
||
|
||
按商品 UUID 获取完整档案(含配料、营养、添加剂、图片、MSRP 等)。
|
||
|
||
### `GET /products/{id}/nutriments` — 商品营养成分
|
||
|
||
### `GET /products/{id}/msrp` — 厂商建议零售价快照
|
||
|
||
官方建议零售价历史快照,仅供参考,不含任何购买入口。
|
||
|
||
### `GET /brands` — 品牌列表(分页)
|
||
|
||
### `GET /categories` — 品类树
|
||
|
||
### `GET /sources/{id}` — 数据来源
|
||
|
||
## 免责声明
|
||
|
||
数据可能存在误差或滞后,按「现状」提供,不构成医疗/购买建议。商品资料版权归各原始来源所有,请遵循其许可(如 OpenFoodFacts 的 ODbL),引用时请注明天工商品档案公共仓及原始来源。
|