DEVELOPERS / OPENAPI v1
让你的应用,
认出每一只猫。
猫谱猫脸识别 API 接入指南
从第一张注册图片,到一次猫咪个体检索。通过标准 HTTP 接口建立猫谱、管理任务和获取身份候选结果。
公开文档 · 阅读无需登录 首次调用前
- 在开放平台控制台登录并创建项目,复制完整的项目 UUID。
- 为项目创建 API Key,配置所需权限,并保存只显示一次的密钥。
- 创建猫咪个体,保存返回的 id,再上传注册图片。
- 查询任务列表,确认注册完成后上传查询图片,获得相似度排序结果。
示例中的 {{base_url}}是你的 HTTPS API 服务地址, {{api_key}} 是项目密钥。请从平台部署配置或服务提供方获取 API 地址;官网地址用于阅读文档,不承接 /v1 业务请求。
cURL 示例使用 Bash 续行语法。Windows 用户可在 Postman 中通过 Import → Raw text 导入,设置 base_url 和 api_key,并重新选择上传图片。Python 示例在服务端运行,需安装 requests 并设置环境变量。
AUTHENTICATION
一个项目,一组访问凭证
业务接口接受 Authorization: Bearer mk_live_… ,也接受拥有该项目的用户登录 Token。每个 Key 绑定一个项目,能够访问其权限范围内的项目数据。
| Scope | 允许操作 |
|---|
cats:read | 读取个体、注册图片列表和图片内容 |
cats:write | 管理个体、注册图片、设置主图和选择注册候选猫 |
recognition:write | 执行猫咪身份识别查询 |
tasks:read | 读取任务状态、结果、统计和预览图片 |
Key 的启停、吊销、有效期和 IP 白名单都会参与鉴权。完整访问包含以上四项权限;创建 Key 时空 scopes 数组会授予全部四项。重试任务接口目前接受 cats:write 或 recognition:write 任一权限。
项目创建与设置、API Key 管理、钱包、账单和用量查询需要用户登录 Token,不能用 API Key 调用。请将密钥保存在服务端环境变量中。
WORKFLOW
注册是异步的,识别等待结果
上传注册图片返回 HTTP 202 和 task_id。此时 vectors_added 为 0 属于正常情况,后台完成特征提取后,图片才参与检索。识别请求优先排队,并等待推理完成后返回结果。
queued → running → completed
→ waiting_user → selection → queued
→ failed → retry → queued每隔几秒调用 GET /tasks?limit=10&offset=0 ,在列表中按 id 查找 task_id。当前没有 GET /tasks/ {task_id} 单独详情接口。任务按创建时间倒序排列;翻页使用 offset,并按任务 ID 去重。
注册图片检测到多只猫时,任务可能进入 waiting_user。查看候选图片后,通过 selection 提交 candidate_index;也可以 cancel 放弃本次待选择注册。只有 failed 状态的任务可以 retry。
请求超时不等于任务失败。先查任务列表,避免重复上传产生额外调用和费用。当前接口没有通用 Idempotency-Key 去重保证。
LIMITS & ERRORS
限流、计费与错误处理
默认每 Key 每秒允许识别 2 次、注册及写操作 10 次、读取 20 次,部署配置可以调整。遇到 429 请按 Retry-After 等待重试。常规成功 JSON 响应可查看 X-RateLimit-Limit 和 X-RateLimit-Remaining。
图片默认上限 15 MiB,可配置;支持 JPEG、PNG、WebP。注册与识别按猫咪向量提取计费,价格和赠送额度以控制台为准。错误响应 detail 可能是字符串、结构化对象或校验数组,请保留 HTTP 状态码和 X-Request-Id。
| HTTP | 错误码 / detail | 说明 |
|---|
| 401 | invalid_api_key | Key 格式错误、密钥不匹配或不存在 |
| 401 | expired_api_key | Key 已过期 |
| 403 | api_key_disabled / api_key_revoked | Key 已禁用或吊销 |
| 403 | project_mismatch | Key 不属于此项目 |
| 403 | scope_denied | 缺少接口所需权限 |
| 403 | ip_not_allowed | 来源 IP 不在白名单 |
| 404 | Not found | 项目、个体、图片或任务不存在 |
| 409 | Conflict | 任务当前状态不允许此操作 |
| 413 | Image is too large | 图片超过上传大小限制 |
| 415 | Unsupported media type | 仅支持 JPEG、PNG、WebP |
| 422 | Validation error | 检查字段类型、必填项和范围 |
| 429 | rate_limit_exceeded | 降低并发,按 Retry-After 等待后重试 |
| 503 | Recognition task failed | 推理不可用,检查任务状态后决定是否重试 |
API REFERENCE / v1
识别猫咪
POST/v1/projects/{project_id}/search
所需权限: recognition:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
请求体使用 multipart/form-data,必填字段 image 为图片文件。每次上传一张 JPEG、PNG 或 WebP;让客户端自动设置 Content-Type 和 boundary。
查询参数与结果
top_k 为 1–100 的整数,默认 5(可配置); threshold 为 −1 到 1 的可选相似度阈值,省略时采用模型默认值。
matches 是相似度排序列表; unknown=true 表示没有找到达到阈值的可信个体。 candidates 中的 score 是检测分数,不是个体匹配相似度。检测到猫脸不代表已经识别出身份。
{
"cat_count": 1,
"route": "face",
"face_detected": true,
"unknown": true,
"matches": [],
"candidates": [
{
"index": 0,
"score": 0.95,
"route": "face",
"face_detected": true,
"unknown": true,
"matches": []
}
],
"task_id": "<task_id>"
}以上为响应结构示例,非实时结果。
curl --request POST '{{base_url}}/v1/projects/{project_id}/search?top_k=5' \
--header 'Authorization: Bearer {{api_key}}' \
--form 'image=@cat.jpg;type=image/jpeg'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
with open("cat.jpg", "rb") as image:
response = requests.post(
base_url + "/v1/projects/{project_id}/search?top_k=5",
headers={"Authorization": f"Bearer {api_key}"},
files={"image": ("cat.jpg", image, "image/jpeg")},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
创建个体
POST/v1/projects/{project_id}/cats
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
name 为 1–100 字符,创建时必填; metadata 为 JSON 对象; active 默认为 true。修改时只提交需要更新的字段。
curl --request POST '{{base_url}}/v1/projects/{project_id}/cats' \
--header 'Authorization: Bearer {{api_key}}' \
--header 'Content-Type: application/json' \
--data '{"name":"Mimi","metadata":{},"active":true}'
查看 Python 示例
import os
import json
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.post(
base_url + "/v1/projects/{project_id}/cats",
headers={"Authorization": f"Bearer {api_key}"},
json=json.loads("{\"name\":\"Mimi\",\"metadata\":{},\"active\":true}"),
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
个体列表
GET/v1/projects/{project_id}/cats
所需权限: cats:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
curl --request GET '{{base_url}}/v1/projects/{project_id}/cats' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/cats",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
修改个体
PATCH/v1/projects/{project_id}/cats/{cat_id}
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
name 为 1–100 字符,创建时必填; metadata 为 JSON 对象; active 默认为 true。修改时只提交需要更新的字段。
curl --request PATCH '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}' \
--header 'Authorization: Bearer {{api_key}}' \
--header 'Content-Type: application/json' \
--data '{"name":"Mimi","active":true}'
查看 Python 示例
import os
import json
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.patch(
base_url + "/v1/projects/{project_id}/cats/{cat_id}",
headers={"Authorization": f"Bearer {api_key}"},
json=json.loads("{\"name\":\"Mimi\",\"active\":true}"),
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
删除个体
DELETE/v1/projects/{project_id}/cats/{cat_id}
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
删除个体同时清理其图片和向量;删除图片会移除对应向量。删除个体成功返回 204,无响应体。
curl --request DELETE '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.delete(
base_url + "/v1/projects/{project_id}/cats/{cat_id}",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
上传注册图片
POST/v1/projects/{project_id}/cats/{cat_id}/images
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
请求体使用 multipart/form-data,必填字段 image 为图片文件。每次上传一张 JPEG、PNG 或 WebP;让客户端自动设置 Content-Type 和 boundary。
成功返回 202 queued 和 task_id,通过任务列表跟踪注册进度。
curl --request POST '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images' \
--header 'Authorization: Bearer {{api_key}}' \
--form 'image=@cat.jpg;type=image/jpeg'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
with open("cat.jpg", "rb") as image:
response = requests.post(
base_url + "/v1/projects/{project_id}/cats/{cat_id}/images",
headers={"Authorization": f"Bearer {api_key}"},
files={"image": ("cat.jpg", image, "image/jpeg")},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
注册图片列表
GET/v1/projects/{project_id}/cats/{cat_id}/images
所需权限: cats:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
curl --request GET '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/cats/{cat_id}/images",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
获取图片文件
GET/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/content
所需权限: cats:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
成功响应为图片二进制内容,不是 JSON。
curl --request GET '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/content' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/content",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
设置主图
PATCH/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/primary
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
curl --request PATCH '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/primary' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.patch(
base_url + "/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/primary",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
删除图片
DELETE/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
删除个体同时清理其图片和向量;删除图片会移除对应向量。删除个体成功返回 204,无响应体。
curl --request DELETE '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.delete(
base_url + "/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
任务列表与结果
GET/v1/projects/{project_id}/tasks
所需权限: tasks:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
limit 范围 1–200,默认 100; offset ≥ 0,默认 0。返回数组包含任务状态和 result。
curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks?limit=10&offset=0' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/tasks?limit=10&offset=0",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
任务统计
GET/v1/projects/{project_id}/tasks/summary
所需权限: tasks:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks/summary' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/tasks/summary",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
查询原图
GET/v1/projects/{project_id}/tasks/{task_id}/query
所需权限: tasks:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
成功响应为图片二进制内容,不是 JSON。
curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/query' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/tasks/{task_id}/query",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
候选猫图片
GET/v1/projects/{project_id}/tasks/{task_id}/candidates/{candidate_index}
所需权限: tasks:read。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
成功响应为图片二进制内容,不是 JSON。
curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/candidates/{candidate_index}' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.get(
base_url + "/v1/projects/{project_id}/tasks/{task_id}/candidates/{candidate_index}",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
选择注册候选猫
POST/v1/projects/{project_id}/tasks/{task_id}/selection
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
仅适用于 waiting_user 状态的注册任务,其他状态返回 409。candidate_index 为非负整数。
curl --request POST '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/selection' \
--header 'Authorization: Bearer {{api_key}}' \
--header 'Content-Type: application/json' \
--data '{"candidate_index":0}'
查看 Python 示例
import os
import json
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.post(
base_url + "/v1/projects/{project_id}/tasks/{task_id}/selection",
headers={"Authorization": f"Bearer {api_key}"},
json=json.loads("{\"candidate_index\":0}"),
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
放弃待选择注册
POST/v1/projects/{project_id}/tasks/{task_id}/cancel
所需权限: cats:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
仅适用于 waiting_user 状态的注册任务,其他状态返回 409。candidate_index 为非负整数。
curl --request POST '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/cancel' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.post(
base_url + "/v1/projects/{project_id}/tasks/{task_id}/cancel",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
API REFERENCE / v1
重试失败任务
POST/v1/projects/{project_id}/tasks/{task_id}/retry
所需权限: cats:write / recognition:write。同时支持拥有该项目的用户登录 Token。将路径中的占位符替换为实际 ID。
只有 failed 状态且保留了源数据的任务可重试,成功返回 202。
curl --request POST '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/retry' \
--header 'Authorization: Bearer {{api_key}}'
查看 Python 示例
import os
import requests
api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# 将 {project_id}、{cat_id} 等占位符替换为实际 ID。
response = requests.post(
base_url + "/v1/projects/{project_id}/tasks/{task_id}/retry",
headers={"Authorization": f"Bearer {api_key}"},
timeout=120,
)
response.raise_for_status()
print(response.content)
接口路径、请求体与权限信息同步自平台现有开发者文档。示例仅含占位符,不包含可用密钥。