DÉVELOPPEURS / OPENAPI v1

Donnez à votre application
le sens de l’identité.

Guide de l’API de reconnaissance Maopu

De la première photo inscrite à la recherche d’identité : utilisez HTTP pour créer des registres, gérer les tâches et retrouver des candidats.

Documentation publique · Sans connexion

Avant la première requête

  1. Connectez-vous à la console, créez un projet et copiez son UUID complet.
  2. Créez une clé API de projet, configurez ses autorisations et conservez le secret affiché une seule fois.
  3. Créez une identité, conservez l’id retourné et envoyez les photos d’inscription.
  4. Vérifiez la liste des tâches. Après l’inscription, envoyez une image de recherche pour obtenir les correspondances classées.
Dans ces exemples, {{base_url}}est l’adresse HTTPS de votre service API et {{api_key}} est votre clé de projet. Obtenez l’adresse auprès de votre déploiement ou fournisseur. Ce site héberge la documentation, pas les requêtes métier /v1.

Les exemples cURL utilisent les continuations Bash. Sous Windows, importez-les dans Postman via Import → Raw text, définissez base_url et api_key et resélectionnez les fichiers. Exécutez Python sur le serveur avec requests et les variables d’environnement configurés.

AUTHENTIFICATION

Identifiants limités au projet

Les endpoints métier acceptent Authorization: Bearer mk_live_… ou le jeton de connexion du propriétaire. Chaque clé est liée à un projet et à ses autorisations.

Autorisation Opérations autorisées
cats:readLire les identités, listes d’images et images
cats:writeGérer les identités, inscrire des images, choisir les photos principales et les candidats
recognition:writeRechercher des identités félines
tasks:readLire les tâches, résultats, résumés et aperçus

L’authentification vérifie l’état, la révocation, l’expiration et les adresses IP. L’accès complet comprend les quatre autorisations ; un tableau scopes vide à la création les accorde toutes. La relance accepte cats:write ou recognition:write.

Projets, paramètres, clés, portefeuilles, facturation et consommation exigent un jeton de connexion, pas une clé API. Stockez les secrets dans les variables d’environnement du serveur.

PROCESSUS

Inscription asynchrone et recherche de résultats

L’inscription renvoie HTTP 202 et task_id ; vectors_added: 0 est normal à ce stade. Les images deviennent recherchables après extraction. La reconnaissance est prioritaire et attend l’inférence avant de répondre.

queued → running → completed
                 → waiting_user → selection → queued
                 → failed → retry → queued

Interrogez GET /tasks?limit=10&offset=0 toutes les quelques secondes et retrouvez task_id par id. Il n’existe pas d’endpoint de détail GET /tasks/ {task_id} . Les tâches sont triées de la plus récente à la plus ancienne. Paginez avec offset et dédupliquez par identifiant.

Une inscription avec plusieurs chats peut passer à waiting_user. Consultez les images candidates, envoyez candidate_index via selection ou abandonnez via cancel. Seules les tâches échouées peuvent être relancées.

Un délai dépassé ne signifie pas un échec. Consultez les tâches avant de renvoyer l’image pour éviter doublons et frais. Il n’existe pas de déduplication générale par Idempotency-Key.

LIMITES ET ERREURS

Limites, facturation et erreurs

Par défaut, chaque clé autorise par seconde 2 reconnaissances, 10 inscriptions/écritures et 20 lectures. Ces limites sont configurables. Sur 429, respectez Retry-After. Les réponses JSON normales exposent X-RateLimit-Limit et X-RateLimit-Remaining.

La limite d’image par défaut est de 15 MiB, configurable. JPEG, PNG et WebP sont acceptés. L’extraction des représentations vectorielles est facturée ; tarifs et crédits sont dans la console. detail peut être une chaîne, un objet ou un tableau de validation. Conservez le statut HTTP et X-Request-Id.

HTTP Code d’erreur / détail Description
401invalid_api_keyFormat ou secret invalide, ou clé inconnue
401expired_api_keyLa clé a expiré
403api_key_disabled / api_key_revokedLa clé est désactivée ou révoquée
403project_mismatchLa clé appartient à un autre projet
403scope_deniedAutorisation requise manquante
403ip_not_allowedAdresse IP source non autorisée
404Not foundProjet, identité, image ou tâche introuvable
409ConflictL’état de la tâche interdit cette opération
413Image is too largeL’image dépasse la taille autorisée
415Unsupported media typeSeuls JPEG, PNG et WebP sont acceptés
422Validation errorVérifiez les champs requis, types et plages
429rate_limit_exceededRéduisez la concurrence et respectez Retry-After
503Recognition task failedÉchec de l’inférence ; vérifiez la tâche avant de relancer

RÉFÉRENCE API / v1

Créer une identité

POST/v1/projects/{project_id}/cats

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

name contient de 1 à 100 caractères et est obligatoire à la création ; metadata est un objet JSON ; active vaut true par défaut. Envoyez seulement les champs modifiés.

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}'
Voir l’exemple Python
import os
import json
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Lister les identités

GET/v1/projects/{project_id}/cats

Autorisation requise : cats:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/cats' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Modifier une identité

PATCH/v1/projects/{project_id}/cats/{cat_id}

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

name contient de 1 à 100 caractères et est obligatoire à la création ; metadata est un objet JSON ; active vaut true par défaut. Envoyez seulement les champs modifiés.

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}'
Voir l’exemple Python
import os
import json
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Supprimer une identité

DELETE/v1/projects/{project_id}/cats/{cat_id}

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

Supprimer une identité supprime ses images et vecteurs ; supprimer une image supprime ses vecteurs. La suppression d’identité renvoie 204 sans corps.

cURL / Postman

curl --request DELETE '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Inscrire une image

POST/v1/projects/{project_id}/cats/{cat_id}/images

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

Utilisez multipart/form-data avec le champ fichier obligatoire image . Un fichier JPEG, PNG ou WebP par requête. Laissez le client générer Content-Type et boundary.

Renvoie 202 queued avec task_id. Suivez l’inscription dans la liste des tâches.

cURL / Postman

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'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Lister les images

GET/v1/projects/{project_id}/cats/{cat_id}/images

Autorisation requise : cats:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Obtenir une image

GET/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/content

Autorisation requise : cats:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

La réponse réussie contient une image binaire, pas du JSON.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/content' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Définir la photo principale

PATCH/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/primary

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

cURL / Postman

curl --request PATCH '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}/primary' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Supprimer une image

DELETE/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

Supprimer une identité supprime ses images et vecteurs ; supprimer une image supprime ses vecteurs. La suppression d’identité renvoie 204 sans corps.

cURL / Postman

curl --request DELETE '{{base_url}}/v1/projects/{project_id}/cats/{cat_id}/images/{image_id}' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Lister les tâches

GET/v1/projects/{project_id}/tasks

Autorisation requise : tasks:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

limit va de 1 à 200, par défaut 100 ; offset est supérieur ou égal à 0, par défaut 0. Le tableau retourné contient les états et result.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks?limit=10&offset=0' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Résumé de la tâche

GET/v1/projects/{project_id}/tasks/summary

Autorisation requise : tasks:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks/summary' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Image de recherche

GET/v1/projects/{project_id}/tasks/{task_id}/query

Autorisation requise : tasks:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

La réponse réussie contient une image binaire, pas du JSON.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/query' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Image candidate

GET/v1/projects/{project_id}/tasks/{task_id}/candidates/{candidate_index}

Autorisation requise : tasks:read. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

La réponse réussie contient une image binaire, pas du JSON.

cURL / Postman

curl --request GET '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/candidates/{candidate_index}' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Choisir le candidat à inscrire

POST/v1/projects/{project_id}/tasks/{task_id}/selection

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

Réservé aux inscriptions en waiting_user. Les autres états renvoient 409. candidate_index est un entier non négatif.

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}'
Voir l’exemple Python
import os
import json
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Abandonner la sélection

POST/v1/projects/{project_id}/tasks/{task_id}/cancel

Autorisation requise : cats:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

Réservé aux inscriptions en waiting_user. Les autres états renvoient 409. candidate_index est un entier non négatif.

cURL / Postman

curl --request POST '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/cancel' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

RÉFÉRENCE API / v1

Relancer une tâche échouée

POST/v1/projects/{project_id}/tasks/{task_id}/retry

Autorisation requise : cats:write / recognition:write. Le jeton du propriétaire est aussi accepté. Remplacez tous les paramètres de chemin par les vrais identifiants.

Seules les tâches échouées dont la source est conservée peuvent être relancées. Succès : 202.

cURL / Postman

curl --request POST '{{base_url}}/v1/projects/{project_id}/tasks/{task_id}/retry' \
  --header 'Authorization: Bearer {{api_key}}'
Voir l’exemple Python
import os
import requests

api_key = os.environ["MEOWID_API_KEY"]
base_url = os.environ["MEOWID_API_BASE"].rstrip("/")
# Remplacez {project_id}, {cat_id}, etc. par les vrais identifiants.
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)

Chemins, corps et autorisations sont synchronisés avec la documentation existante. Les exemples ne contiennent que des paramètres fictifs, jamais de secrets réels.