貓臉辨識 API 接入指南

從第一張註冊照片,到一次貓咪身分檢索。

介面均為標準 HTTP 請求:在專案內建立貓咪檔案、上傳註冊圖片、檢索身分、查詢任務狀態。

公開文件 · 閱讀無需登入 圖文 API 串接教學 ↗跟著 12 張標註截圖,建立貓咪檔案並完成首次辨識請求。

首次呼叫前

  1. 在開放平台控制台登入並建立專案,複製完整的專案 UUID。
  2. 為專案建立 API Key,設定所需權限,並保存只顯示一次的金鑰。
  3. 建立貓咪個體,保存回傳的 id,再上傳註冊圖片。
  4. 查詢任務列表,確認註冊完成後上傳查詢圖片,獲得相似度排序結果。
前往開放平台控制台 ↗
示例中的 {{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 說明
401invalid_api_keyKey 格式錯誤、金鑰不匹配或不存在
401expired_api_keyKey 已過期
403api_key_disabled / api_key_revokedKey 已禁用或吊銷
403project_mismatchKey 不屬於此專案
403scope_denied缺少介面所需權限
403ip_not_allowed來源 IP 不在白名單
404Not found專案、個體、圖片或任務不存在
409Conflict任務當前狀態不允許此操作
413Image is too large圖片超過上傳大小限制
415Unsupported media type僅支援 JPEG、PNG、WebP
422Validation error檢查欄位類型、必填項和範圍
429rate_limit_exceeded降低並行,按 Retry-After 等待後重試
503Recognition task failed推理不可用,檢查任務狀態後決定是否重試

建立個體

POST/v1/projects/{project_id}/cats

所需權限: cats:write。同時支援擁有該專案的用戶登入 Token。將路徑中的占位符替換為實際 ID。

name 為 1–100 字符,建立時必填; metadata 為 JSON 物件; active 預設為 true。修改時只提交需要更新的欄位。

cURL / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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 / Postman

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)

範例中的網址與金鑰均為佔位符,請替換成你自己的設定。