貓臉辨識 API 接入指南
從第一張註冊照片,到一次貓咪身分檢索。
介面均為標準 HTTP 請求:在專案內建立貓咪檔案、上傳註冊圖片、檢索身分、查詢任務狀態。
公開文件 · 閱讀無需登入 圖文 API 串接教學 ↗跟著 12 張標註截圖,建立貓咪檔案並完成首次辨識請求。首次呼叫前
- 在開放平台控制台登入並建立專案,複製完整的專案 UUID。
- 為專案建立 API Key,設定所需權限,並保存只顯示一次的金鑰。
- 建立貓咪個體,保存回傳的 id,再上傳註冊圖片。
- 查詢任務列表,確認註冊完成後上傳查詢圖片,獲得相似度排序結果。
前往開放平台控制台 ↗ 示例中的 {{base_url}}是你的 HTTPS API 服務地址, {{api_key}} 是專案 API Key。API 地址由平台部署時提供。官網只用於閱讀文件,不接收介面請求。
cURL 示例使用 Bash 續行語法。Windows 用戶可在 Postman 中透過 Import → Raw text 導入,設定 base_url 和 api_key,並重新選擇上傳圖片。Python 示例在伺服器端運行,需安裝 requests 並設定環境變量。
一個專案,一組訪問憑證
業務介面接受 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 呼叫。請將金鑰保存在伺服器端環境變量中。
註冊是非同步的,辨識等待結果
上傳註冊圖片回傳 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 去重保證。
限流、計費與錯誤處理
預設每 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 | 推理不可用,檢查任務狀態後決定是否重試 |
辨識貓咪
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 '[email protected];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)
建立個體
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)
個體列表
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)
修改個體
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)
刪除個體
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)
上傳註冊圖片
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 '[email protected];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)
註冊圖片列表
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)
獲取圖片文件
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)
設定主圖
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)
刪除圖片
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)
任務列表與結果
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)
任務統計
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)
查詢原圖
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)
候選貓圖片
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)
選擇註冊候選貓
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)
放棄待選擇註冊
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)
重試失敗任務
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)
範例中的網址與金鑰均為佔位符,請替換成你自己的設定。