Référence de l’API REST#
Plateforme Ultralytics fournit une API REST pour accéder de manière programmatique aux jeux de données, aux images, aux projets, aux modèles, à l’entraînement, aux exportations et aux déploiements.

# List the datasets owned by a workspace
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://platform.ultralytics.com/api/datasets/YOUR_USERNAMEChaque point de terminaison ci-dessous indique l’appel client.<resource>.<method>(...) correspondant dans le SDK ultralytics-platform, généré à partir du même contrat que cette référence.
Cette page propose une visite guidée de l’API. La référence générée et toujours à jour se trouve à l’adresse platform.ultralytics.com/api/docs, et le document OpenAPI 3.2 lisible par machine qui l’alimente est publié à l’adresse platform.ultralytics.com/openapi.json. Les deux sont générés directement à partir du contrat côté serveur et font donc autorité en cas de divergence entre cette page et le schéma.
Présentation de l’API#
L’API est organisée autour des ressources principales de la plateforme :
graph LR
A[API Key]:::start --> B[Datasets]:::proc
A --> C[Projects]:::proc
B -->|images| G[Images]:::proc
C -->|contains| D[Models]:::proc
B -->|train on| D
D -->|deploy| E[Deployments]:::proc
D -->|export| F[Exports]:::proc
classDef start fill:#4CAF50,color:#fff
classDef proc fill:#2196F3,color:#fff| Ressource | Description | Opérations clés |
|---|---|---|
| Jeux de données | Collections d’images annotées | CRUD, ingestion, versions, classes, partitions, clonage, copie |
| Images | Images et annotations individuelles | Lire, annoter, déplacer vers une partition, supprimer, annoter automatiquement, flouter les visages |
| Projets | Espaces de travail des modèles | CRUD, clonage |
| Modèles | Points de contrôle entraînés | CRUD, prédiction, téléchargement, clonage, état de l’entraînement |
| Entraînement | Tâches d’entraînement sur GPU dans le cloud | Disponibilité du GPU, démarrage, progression, annulation |
| Exportations | Tâches de conversion de format | Créer, lister, consulter l’état, annuler |
| Déploiements | Points de terminaison d’inférence dédiés | Créer, mettre à jour, démarrer/arrêter, prédire, consulter les métriques et les journaux |
| Agents | Flux de travail visuels enregistrés | Lister, enregistrer, supprimer |
| Corbeille | Ressources supprimées de façon réversible | Lister, restaurer, supprimer définitivement |
| Stockage | Intégrations de stockage cloud | Connecter, découvrir, parcourir, déconnecter |
| Compte | Offre, crédits, stockage, profil | Récapitulatif du compte, clés API, utilisation du stockage, recherche d’utilisateurs |
| Facturation | Utilisation de l’offre et registre des opérations | Récapitulatif de l’utilisation, transactions |
| Explorer | Recherche de contenu public | Rechercher des projets, des jeux de données et des images |
Authentification#
La plupart des points de terminaison nécessitent une clé API. Ceux qui exposent du contenu public — lecture d’un jeu de données, d’un projet ou d’un modèle public, liste des images d’un jeu de données public, exécution d’inférences sur un modèle public ou recherche dans Explorer — acceptent également les requêtes anonymes et renvoient simplement davantage de résultats lorsqu’une clé est fournie.
Obtenir une clé API#
- Va dans
Settings>API Keys - Clique sur
Add Key, conserveUltralyticscomme fournisseur, saisis un nom, puis clique surCreate Key - Copie la clé générée
Consulte Clés API pour obtenir des instructions détaillées.
En-tête d’autorisation#
Ajoute ta clé API comme jeton Bearer :
Authorization: Bearer YOUR_API_KEYLes clés API sont constituées du préfixe littéral ul_, suivi de 40 caractères hexadécimaux, soit 43 caractères au total (par exemple ul_a1b2c3d4e5f6789012345678901234567890abcd). Les requêtes sans en-tête, avec une clé mal formée ou avec une clé révoquée renvoient 401. Garde ta clé secrète : ne l’enregistre jamais dans un système de contrôle de version et ne la partage pas publiquement.
Exemple#
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://platform.ultralytics.com/api/account/summaryURL de base#
Tous les points de terminaison de l’API utilisent :
https://platform.ultralytics.com/apiChemins des ressources#
La plupart des ressources sont désignées par les mêmes noms lisibles que ceux qui apparaissent dans les URL de la plateforme, et non par des identifiants de base de données :
| Ressource | Chemin | Exemple |
|---|---|---|
| Jeu de données | /api/datasets/{owner}/{dataset} | /api/datasets/acme-vision/warehouse |
| Projet | /api/projects/{owner}/{project} | /api/projects/acme-vision/inspection |
| Modèle | /api/models/{owner}/{project}/{model} | /api/models/acme-vision/inspection/v3 |
| Déploiement | /api/deployments/{owner}/{deployment} | /api/deployments/acme-vision/edge-1 |
| Image | /api/images/{imageId} | /api/images/65f1c0a2b3d4e5f601234567 |
| Agent | /api/workflows?id={agentId} | /api/workflows?id=65f1c0a2b3d4e5f601234567 |
{owner}est un nom d’utilisateur personnel ou un identifiant d’espace de travail d’équipe : de 4 à 32 caractères, en minuscules alphanumériques, avec des traits d’union simples entre les segments.{dataset},{project},{model}et{deployment}suivent le même format en minuscules séparées par des traits d’union, sur un maximum de 128 caractères.{imageId},{exportId}et{agentId}sont des identifiants hexadécimaux de 24 caractères renvoyés par l’API.- Renommer une ressource via
PATCHmodifie simultanément sonnamed’affichage et son nom dans l’URL. La réponse renvoie le nom actuel dans l’URL pour que tu puisses continuer à l’utiliser.
À l’exception de l’API Agents, il n’existe pas de paramètre de requête owner. Les chemins associés à un espace de travail indiquent le propriétaire dans le chemin, et les points de terminaison associés au compte (/api/account/summary, /api/api-keys, /api/storage, /api/billing/*, /api/trash, /api/integrations/buckets) opèrent sur l’espace de travail qui a émis la clé API. Pour agir sur un espace de travail d’équipe, utilise une clé API créée dans cet espace de travail ou transmets owner à l’API Agents.
Limites de débit#
L’API applique des limites par clé API sur une fenêtre glissante. Chaque route appartient à une catégorie, et chaque catégorie dispose d’un compteur indépendant : ainsi, 20 requêtes de prédiction ne réduisent pas ton quota par défaut.
| Catégorie | Limite | S’applique à |
|---|---|---|
| Par défaut | 100 requêtes/min | Toutes les routes non répertoriées ci-dessous |
| Entraînement | 10 requêtes/min | POST /api/training/start |
| Téléverser | 10 requêtes/min | URL de téléversement signées, finalisation du téléversement et ingestion de jeux de données |
| Prédiction | 20 requêtes/min | Inférence sur les modèles et les déploiements via les routes de l’API de la plateforme |
| Exporter | 20 requêtes/min | Liste et création d’exportations de modèles, et création ou mise à jour de versions de jeux de données ; la lecture d’une exportation de jeu de données (GET) et d’une exportation de modèle unique sont soumises à la limite par défaut |
| Télécharger | 30 requêtes/min | Téléchargements de fichiers de modèles |
| Modification | 10 requêtes/min | Liste des clés API, liste ou connexion des intégrations de stockage cloud, découverte des emplacements de stockage et mises à jour des déploiements (PATCH) |
| Hydratation | 20 requêtes/min | POST /api/datasets/{owner}/{dataset}/images (récupération d’un ensemble sélectionné d’images) et GET /api/images/{imageId}/similar |
| Regroupement | 10 requêtes/min | GET /api/datasets/{owner}/{dataset}/images/clustering et GET /api/models/{owner}/{project}/{model}/similar-images |
Les routes de la plateforme réservées au navigateur, comme le paiement de factures et la gestion des équipes, ont leurs propres limites, qui ne s'appliquent pas au trafic utilisant des clés API.
En cas de limitation, l'API renvoie 429 avec des en-têtes et un corps JSON :
Retry-After: 12
X-RateLimit-Reset: 2026-02-21T12:34:56.000Z{
"error": "Rate limit exceeded, wait 12s",
"retryAfter": 12,
"resetAt": "2026-02-21T12:34:56.000Z"
}Points de terminaison dédiés (illimités)#
Les points de terminaison dédiés ne sont pas soumis aux limites de débit des clés API de la plateforme lorsque tu appelles directement le serviceUrl propre au déploiement (par exemple, https://predict-abc123.run.app/predict). Le débit dépend alors de la configuration du service déployé.
Lorsque tu reçois un 429, attends Retry-After secondes (ou jusqu'à X-RateLimit-Reset) avant de réessayer. Consulte la FAQ sur les limites de débit pour voir une implémentation du délai exponentiel.
Format de réponse#
Réponses de réussite#
Les réponses sont des objets JSON contenant des champs propres à chaque ressource. Il n'existe pas d'enveloppe générique : les points de terminaison de liste renvoient une collection nommée, généralement accompagnée de nombres, et les opérations de modification renvoient les identifiants modifiés.
{
"datasets": [{ "id": "65f1c0a2b3d4e5f601234567", "owner": "acme-vision", "dataset": "warehouse" }],
"total": 1,
"region": "us"
}Les listes de ressources, les réponses de création et de clonage, ainsi que quelques lectures comme celles des déploiements, du stockage et de la corbeille incluent également region (us, eu ou ap), la région de stockage de cet espace de travail.
Réponses d'erreur#
Chaque réponse d'erreur est un objet JSON contenant un message error :
{
"error": "Dataset not found"
}| Code d'état HTTP | Signification |
|---|---|
200 | Réussite |
201 | Date de création |
202 | Acceptée, le traitement se poursuit de manière asynchrone |
400 | Chemin, requête ou corps de requête invalide |
401 | Authentification manquante ou invalide |
402 | Crédits insuffisants (entraînement) |
403 | Autorisations, formule ou quota insuffisants |
404 | Ressource introuvable |
409 | Conflit avec l'état actuel (nom en double, tâche en cours) |
413 | Entrée de prédiction trop volumineuse |
422 | Les classes du modèle ne correspondent pas au jeu de données, ou une clé de fournisseur est manquante ou refusée (annotation automatique) |
429 | Limite de débit dépassée |
500 | Erreur du serveur |
502 | Échec de l'appel au fournisseur ou au service en amont |
503 | Service dépendant temporairement indisponible |
Pagination#
Le style de pagination dépend de la collection :
| Style | Points de terminaison | Paramètres |
|---|---|---|
| Limite uniquement | Listes de jeux de données, projets, modèles, exports et déploiements | limit |
| Décalage et limite | Images de jeux de données, regroupement d'images, recherche Explore | offset, limit, plus hasMore dans la réponse |
| Curseur | Images de jeux de données (grands jeux de données) | cursor, includeTotal, plus nextCursor |
| Numéro de page | Corbeille | page, limit, plus totalPages |
| Jeton de page opaque | Journaux de déploiement | pageToken, plus nextPageToken |
API des jeux de données#
Crée, parcours et gère des jeux de données d'images étiquetées pour entraîner des modèles YOLO. Consulte la documentation sur les jeux de données.
Lister les jeux de données#
GET /api/datasets/{owner}SDK Python : client.datasets.list(owner)
Renvoie les jeux de données publics du propriétaire, ainsi que ses jeux de données privés si ta clé permet d'accéder à cet espace de travail.
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
limit | int | Nombre maximal de jeux de données à renvoyer (par défaut : 1000, maximum : 1000) |
includeSamples | booléen | Inclure des aperçus d'images d'exemple (par défaut : true) |
includeImageUrls | booléen | Inclure des URL de secours vers des images d'exemple en pleine résolution (par défaut : false) |
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://platform.ultralytics.com/api/datasets/acme-vision?limit=10&includeSamples=false"Réponse :
{
"datasets": [
{
"id": "65f1c0a2b3d4e5f601234567",
"owner": "acme-vision",
"dataset": "warehouse",
"name": "Warehouse",
"task": "detect",
"visibility": "private",
"imageCount": 1000,
"classCount": 2,
"classNames": ["person", "forklift"],
"splits": { "train": 800, "val": 200, "test": 0, "labeled": 1000 },
"annotationCount": 5400,
"starCount": 3,
"isStarred": false,
"status": "ready",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-16T08:30:00Z"
}
],
"total": 1,
"region": "us"
}Obtenir un jeu de données#
GET /api/datasets/{owner}/{dataset}SDK Python : client.datasets.retrieve(owner, dataset)
Renvoie l'objet complet du jeu de données sous une clé dataset, y compris classNames, splits, versions, source et l'objet metadata défini par l'utilisateur. Lorsqu'un import de 10 000 images ou plus est en cours, les éditeurs reçoivent également processingProgress avec stage, percent et, si ces informations sont connues, processed, total et objects (objets cloud analysés).
Créer un jeu de données#
POST /api/datasetsSDK Python : client.datasets.create(dataset=..., name=...)
Corps :
{
"dataset": "warehouse",
"name": "Warehouse",
"task": "detect",
"description": "Forklift and pedestrian safety dataset",
"classNames": ["person", "forklift"],
"visibility": "private",
"metadata": { "location": "factory-1", "reviewed": true },
"owner": "acme-vision"
}| Champ | Type | Obligatoire | Description |
|---|---|---|---|
dataset | chaîne | Oui | Nom du jeu de données utilisé dans les URL de la plateforme (minuscules, mots séparés par des tirets, 128 caractères maximum) |
name | chaîne | Oui | Nom d'affichage (100 caractères maximum) |
description | chaîne | Non | Description (1000 caractères maximum) |
task | chaîne | Non | Type de tâche (par défaut : detect) |
classNames | tableau | Non | Noms des classes par ordre d’index (25 000 maximum) ; aucun doublon, casse ignorée pour les noms de plus de 2 caractères |
format | chaîne | Non | Format d'annotation : yolo (par défaut), coco, raw, ndjson |
visibility | chaîne | Non | public ou private |
blurFaces | booléen | Non | Flouter les visages dans les images importées dans le jeu de données (voir Flouter les visages) |
tags | tableau | Non | Jusqu'à 50 étiquettes de 50 caractères chacune |
license | chaîne | Non | Identifiant de licence du jeu de données |
metadata | objet | Non | Métadonnées JSON personnalisées |
owner | chaîne | Non | Identifiant de l'espace de travail d'équipe ; par défaut, ton espace de travail personnel |
Un slug dataset qui existe déjà dans l'espace de travail, y compris dans la corbeille, renvoie 409.
Valeurs task valides lors de la création ou de la mise à jour d'un jeu de données : detect, segment, semantic, depth, classify, pose et obb. Les jeux de données de profondeur n'ont pas de classes.
Réponse (201) :
{
"id": "65f1c0a2b3d4e5f601234567",
"owner": "acme-vision",
"dataset": "warehouse",
"region": "us"
}Mettre à jour un jeu de données#
PATCH /api/datasets/{owner}/{dataset}SDK Python : client.datasets.update(owner, dataset)
Corps (mise à jour partielle) :
{
"name": "Warehouse Safety",
"description": "New description",
"visibility": "public",
"metadata": { "location": "factory-2", "reviewed": true }
}Champs acceptés : name, description, visibility, metadata, tags, classNames, classColors, format, task, license, iconColor, iconLetter, starred, blurFaces, kptSkeletonId (attribuer un modèle de squelette de pose à un jeu de données de pose) et initializeClassNames (la mise à jour renvoie 409, sauf si le jeu de données ne contient pas encore de classes ou d'annotations). Envoie un objet metadata vide ({}) pour effacer les métadonnées personnalisées. Les clés de métadonnées sont limitées à 128 caractères et l'objet sérialisé à 500 000 caractères.
Réponse :
{
"success": true,
"dataset": "warehouse-safety"
}Le renommage modifie le nom dans l'URL ; utilise donc la valeur dataset renvoyée pour les requêtes suivantes.
Supprimer le jeu de données#
DELETE /api/datasets/{owner}/{dataset}SDK Python : client.datasets.delete(owner, dataset)
Déplace le jeu de données dans la corbeille, où il peut être récupéré pendant 30 jours.
Cloner le jeu de données#
POST /api/datasets/{owner}/{dataset}/cloneSDK Python : client.datasets.clone(owner, dataset)
Copie un jeu de données accessible, avec ses images et ses étiquettes, dans ton espace de travail personnel ou dans un espace de travail d'équipe.
Corps facultatif (tous les champs sont facultatifs) :
{
"dataset": "warehouse-copy",
"name": "Warehouse Copy",
"description": "Cloned for experimentation",
"visibility": "private",
"license": "CC-BY-4.0",
"owner": "acme-vision"
}Réponse (201) : id, owner, dataset, name, imageCount, classCount et region. Les jeux de données associés à une source de stockage connectée renvoient 409, car leurs fichiers ne sont pas copiés.
Télécharger un export de jeu de données#
GET /api/datasets/{owner}/{dataset}/exportSDK Python : client.datasets.export(owner, dataset)
Renvoie une URL de téléchargement NDJSON signée. Omet v pour exporter l'état actuel du jeu de données ; l'export mis en cache est réutilisé si rien n'a changé depuis sa génération.
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
v | entier | Numéro de version enregistrée (indexée à partir de 1). À omettre pour le jeu de données actuel. |
Réponse :
{
"downloadUrl": "https://storage.googleapis.com/...&signature=...",
"cached": true
}Demander une version spécifique renvoie downloadUrl et version au lieu de cached.
Créer une version du jeu de données#
POST /api/datasets/{owner}/{dataset}/exportSDK Python : client.datasets.create_export(owner, dataset)
Crée une version numérotée immuable du jeu de données. L'accès éditeur est requis. Définis download sur false pour enregistrer la version sans préparer de téléchargement NDJSON ; downloadUrl est alors omis. Le SDK accepte download depuis ultralytics-platform>=0.1.73.
Corps (facultatif) :
{
"description": "Added 500 training images",
"download": true
}Réponse :
{
"version": 3,
"downloadUrl": "https://storage.googleapis.com/...&signature=...",
"reused": false
}reused vaut true lorsque le jeu de données correspond à une version existante, par exemple juste après sa restauration. Cette version est alors renvoyée, avec sa description mise à jour si tu en as fourni une.
Mettre à jour la description d'une version#
PATCH /api/datasets/{owner}/{dataset}/exportSDK Python : client.datasets.update_export(owner, dataset, version=..., description=...)
Corps :
{
"version": 2,
"description": "Fixed mislabeled classes"
}Réponse : {"ok": true}
Restaurer une version du jeu de données#
POST /api/datasets/{owner}/{dataset}/restoreSDK Python : client.datasets.restore(owner, dataset, version=...)
Reconstruit les images, les annotations et les classes à partir d'une version enregistrée, sans copier les octets des images.
Corps :
{
"version": 2
}Réponse : {"version": 2, "imageCount": 1000}
Comparer les versions d'un jeu de données#
GET /api/datasets/{owner}/{dataset}/versions/compare?base={from}&head={to}SDK Python : client.datasets.compare(owner, dataset, base=1, head=2) (ultralytics-platform>=0.1.73)
| Paramètre | Type | Description |
|---|---|---|
base | int | Version de départ de la comparaison |
head | int | Version d'arrivée de la comparaison |
cursor | chaîne | nextCursor de la page précédente |
hash | chaîne | Le hash d'un élément : renvoie cette image telle qu'elle est stockée dans chaque version, et non les modifications. |
Réponse (abrégée) :
{
"summary": { "added": 0, "removed": 1, "modified": 1, "moved": 1, "labelsAdded": 1, "labelsRemoved": 2 },
"items": [
{
"hash": "b5c605c133f84c3024af7e652b135501",
"name": "000000000042",
"change": "moved",
"base": { "split": "val", "labelCount": 1 },
"head": { "split": "test", "labelCount": 1 }
}
]
}summary apparaît uniquement sur la première page et contient les totaux exacts ainsi qu'un header qui répertorie les classes ajoutées, supprimées ou renommées et les autres champs du jeu de données qui diffèrent. Le change de chaque élément est added, removed, modified (avec le fields modifié) ou moved (fractionnement modifié), et labelsRemoved contient les étiquettes des images supprimées. Si nextCursor est présent, transmets-le comme cursor pour obtenir la page suivante. Avec hash, la réponse est versions : l'image telle qu'elle est stockée dans chaque version, avec ses étiquettes et un imageUrl signé. Les deux ordres fonctionnent ; inverser base et head signale une image supprimée comme ajoutée. Les comparaisons utilisent la limite de débit par défaut, et les requêtes sans hash sont également limitées à 10 par minute et par utilisateur et jeu de données, quelle que soit la clé API utilisée.
Obtenir les statistiques du jeu de données#
GET /api/datasets/{owner}/{dataset}/class-statsSDK Python : client.datasets.class_stats(owner, dataset)
Renvoie le nombre d’annotations par classe, des histogrammes d’images et d’annotations, ainsi que des cartes thermiques. Les grands jeux de données sont échantillonnés ; dans ce cas, sampleSize indique le nombre d’images prises en compte.
Réponse (abrégée) :
{
"classes": [{ "classId": 0, "count": 1500, "imageCount": 450 }],
"imageStats": {
"widthHistogram": [{ "bin": 640, "count": 120, "size": 1 }],
"heightHistogram": [{ "bin": 480, "count": 95, "size": 1 }],
"pointsHistogram": [{ "bin": 4, "count": 200, "size": 1 }],
"formatDistribution": { "jpg": 900, "png": 100 },
"fileSizeHistogram": [{ "bin": 250000, "count": 300, "size": 50000 }],
"objectsPerImageHistogram": [{ "bin": 5, "count": 210, "size": 1 }],
"bboxWidthHistogram": [{ "bin": 120, "count": 340, "size": 20 }],
"bboxHeightHistogram": [{ "bin": 90, "count": 300, "size": 20 }]
},
"locationHeatmap": {
"bins": [
[5, 10],
[8, 3]
],
"maxCount": 50
},
"dimensionHeatmap": {
"bins": [
[2, 5],
[3, 1]
],
"maxCount": 12,
"minWidth": 10,
"maxWidth": 1920,
"minHeight": 10,
"maxHeight": 1080
},
"classNames": ["person", "forklift"],
"cached": true,
"sampleSize": null
}Gérer les classes#
Fusionne des classes (réaffecte les annotations à une classe cible, puis supprime les classes sources) :
POST /api/datasets/{owner}/{dataset}/classes/mergeSDK Python : client.datasets.merge_classes(owner, dataset, source_class_ids=..., target_class_id=...)
{
"sourceClassIds": [2, 4],
"targetClassId": 1
}Supprime des classes (leurs annotations sont supprimées et les ID des classes restantes sont décalés vers le bas) :
POST /api/datasets/{owner}/{dataset}/classes/deleteSDK Python : client.datasets.delete_classes(owner, dataset, class_ids=...)
{
"classIds": [2, 4]
}Les deux opérations renvoient success, les valeurs mises à jour classNames et classColors, ainsi qu’un résumé des modifications (mergedClassIds et targetClassId, ou deletedClassIds et deletedAnnotations).
Comme les ID restants sont décalés après une fusion ou une suppression, ces opérations ne sont pas idempotentes. Récupère à nouveau le jeu de données pour obtenir les indices de classe actuels avant de lancer une autre opération sur les classes.
Redistribuer les partitions#
POST /api/datasets/{owner}/{dataset}/splits/redistributeSDK Python : client.datasets.redistribute_splits(owner, dataset, train=..., val=..., test=...)
Réaffecte aléatoirement les images entre les partitions. Le total des trois pourcentages doit être égal à 100.
{
"train": 80,
"val": 20,
"test": 0
}Réponse : success, les nombres obtenus splits et modified (nombre d’images déplacées).
Plongements du jeu de données#
GET /api/datasets/{owner}/{dataset}/embeddings
POST /api/datasets/{owner}/{dataset}/embeddings
DELETE /api/datasets/{owner}/{dataset}/embeddingsSDK Python : client.datasets.embeddings(owner, dataset), client.datasets.create_embeddings(owner, dataset), client.datasets.delete_embeddings(owner, dataset)
GET renvoie le résumé de l’analyse (analyzedAt, embeddingsCount, latestImageAt, activeJob). POST met en file d’attente une analyse des plongements et renvoie 202 avec un jobId. DELETE annule la tâche active et renvoie l’ID de la tâche annulée ou null.
Regroupement des images#
GET /api/datasets/{owner}/{dataset}/images/clusteringSDK Python : client.datasets.clustering(owner, dataset)
Renvoie la disposition 2D UMAP issue d’une analyse terminée, avec pagination à l’aide de offset et limit (valeur par défaut et maximum : 50 000). Chaque entrée comporte id, umapX, umapY, cluster, split, classIds, width, height, bytes, labelCount, labeled et missing. cluster correspond à l’îlot visuel du point, classé par taille (0 = le plus grand, -1 = dispersé), ou null pour les dispositions analysées avant l’ajout du regroupement.
Lister les modèles entraînés sur un jeu de données#
GET /api/datasets/{owner}/{dataset}/modelsSDK Python : client.datasets.models(owner, dataset)
Réponse :
{
"models": [
{
"id": "65f1c0a2b3d4e5f601234599",
"owner": "acme-vision",
"project": "inspection",
"model": "v3",
"name": "v3",
"status": "completed",
"task": "detect",
"epochs": 100,
"bestEpoch": 87,
"metrics": { "mAP50": 0.85, "mAP50-95": 0.72, "precision": 0.88, "recall": 0.81 },
"startedAt": "2026-01-14T22:00:00Z",
"completedAt": "2026-01-15T10:00:00Z",
"createdAt": "2026-01-14T21:55:00Z"
}
],
"count": 1
}Lister les images du jeu de données#
GET /api/datasets/{owner}/{dataset}/imagesSDK Python : client.datasets.images(owner, dataset)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
limit | int | Nombre maximal d’images à renvoyer (par défaut : 50, maximum : 5 000) |
offset | int | Nombre d’images à ignorer (par défaut : 0) |
cursor | chaîne | ID de la dernière image de la page précédente, pour la pagination par curseur |
includeTotal | booléen | Inclure le nombre total de résultats correspondants (par défaut : true) |
split | chaîne | Filtrer par partition : train, val, test |
hasLabel | booléen | Filtrer par état d’annotation |
hasError | booléen | Filtrer par état d’erreur de traitement |
classIds | chaîne | ID de classe séparés par des virgules ; renvoie les images qui en contiennent au moins un |
search | chaîne | Correspondance de sous-chaîne dans le nom de fichier, le nom de classe et les métadonnées personnalisées (200 caractères maximum) |
q | chaîne | Classe par pertinence plutôt que par sort : correspondances textuelles, puis jusqu’à 1 000 éléments similaires ; un ID, un hachage ou un nom de fichier sert de search (200 caractères maximum) |
sort | chaîne | newest (par défaut), oldest, name-asc, name-desc, height-asc, height-desc, width-asc, width-desc, size-asc, size-desc, labels-asc, labels-desc |
includeThumbnails | booléen | Inclure les URL signées des miniatures (par défaut : true) |
includeImageUrls | booléen | Inclure les URL signées des images en pleine résolution (par défaut : false) |
includeLabels | booléen | Inclure les annotations d’aperçu plafonnées (par défaut : false) |
Réponse :
{
"images": [
{
"id": "65f1c0a2b3d4e5f601234567",
"hash": "9f2c1d4b6a8e0f3c5d7b9a1e2f4c6d8b",
"ext": "jpg",
"name": "aisle-04",
"thumbnailUrl": "https://storage.googleapis.com/...&signature=...",
"width": 1920,
"height": 1080,
"split": "train",
"labelCount": 6,
"bytes": 284213,
"error": null
}
],
"total": 1000,
"hasMore": true,
"classes": ["person", "forklift"],
"errorCount": 0,
"nextCursor": "65f1c0a2b3d4e5f601234567"
}Obtenir les images sélectionnées#
POST /api/datasets/{owner}/{dataset}/imagesSDK Python : client.datasets.selected_images(owner, dataset, image_ids=...)
Renvoie la même structure d’image pour un maximum de 1 000 ID d’image fournis et accepte les mêmes paramètres de filtre et d’URL que l’opération de liste.
{
"imageIds": ["65f1c0a2b3d4e5f601234567", "65f1c0a2b3d4e5f601234568"]
}Copier ou déplacer des images#
POST /api/datasets/{owner}/{dataset}/images/adoptSDK Python : client.datasets.adopt_images(owner, dataset, image_ids=..., release=...) (ultralytics-platform>=0.1.50)
Copie jusqu’à 1 000 images depuis d’autres jeux de données vers celui-ci, comme le fait l’application avec sa fonction copier-coller, et renvoie le nombre adopted.
{
"imageIds": ["65f1c0a2b3d4e5f601234567"],
"release": false,
"classMapping": { "person": 0, "vase": null }
}La définition de release ou classMapping conserve les étiquettes et les partitions des jeux de données que tu peux modifier : release: false copie les images et release: true les déplace hors de leur jeu de données source. Si tu omets les deux champs, les images train sans étiquette sont importées, comme lors d’une copie depuis une source en lecture seule ; déplacer des images depuis une source en lecture seule renvoie 403. Les images existantes sont ignorées ; si les étiquettes et les partitions sont conservées, les doublons sont recherchés dans la partition de destination. Les classes sont associées par nom, sans tenir compte de la casse pour les noms de plus de deux caractères ; 422 renvoie les classes source sans correspondance dans unmatchedClasses, et classMapping associe chacune d’elles à un index de classe, à un nouveau nom de classe ou à null pour ignorer ses étiquettes. 409 signifie que le jeu de données de destination est connecté, ou qu’une source ou une destination est occupée. Si les étiquettes et les partitions sont conservées, les tâches, les canaux d’image, les paramètres de pose ou les échelles de profondeur incompatibles renvoient également 409, même pour les images sans étiquette.
Importer des données dans un jeu de données#
POST /api/datasets/{owner}/{dataset}/ingestSDK Python : client.datasets.ingest(owner, dataset, body=...)
Traite un téléversement terminé, une archive distante ou une source de stockage connectée pour les intégrer à un jeu de données existant. Indique exactement une source :
| Champ | Type | Description |
|---|---|---|
sessionId | chaîne | Session de téléversement provenant de POST /api/upload/signed-url ; l’importation vérifie et termine le téléversement si POST /api/upload/complete n’a pas été appelé |
sourceUrl | chaîne | URL HTTP ou HTTPS publique d’un fichier ZIP, TAR, TAR.GZ, TGZ ou NDJSON (4 096 caractères maximum) |
reference | objet | Une source connectée : stockage cloud (provider: "cloud", integrationId, target, prefix) ou sur site (provider: "local", keyId, root, prefix) |
targetSplit | chaîne | train, val ou test ; remplace la structure de partitions de l’archive |
conflictPolicy | chaîne | skip, keep_both ou replace en cas de conflit de nom de fichier ou de contenu |
classMapping | objet | Associe les noms de classe entrants à un index de classe, à un nom de classe existant ou nouveau, ou à null pour les ignorer |
imageMetadata | objet | Métadonnées personnalisées indexées par le chemin relatif de chaque image dans l’archive ou par la valeur NDJSON file |
Les sessions de téléversement sont associées à un jeu de données par le paramètre assetId transmis à POST /api/upload/signed-url, et l’importation rejette toute session liée à un autre jeu de données.
Corps (archive téléversée) :
{
"sessionId": "session_abc123",
"targetSplit": "train"
}Corps (archive distante ou NDJSON) :
{
"sourceUrl": "https://example.com/my-dataset.zip"
}Corps (importation des étiquettes lors d’une importation ultérieure) :
{
"sessionId": "session_abc123",
"classMapping": { "person": 0, "automobile": "forklift", "background": null }
}Corps (ajout de métadonnées par image) :
{
"sessionId": "session_abc123",
"imageMetadata": {
"airbus-wing.jpg": { "aircraft": { "family": "A350" }, "inspectionStatus": "reviewed" },
"images/tail.jpg": { "aircraft": { "family": "A320" }, "inspectionSeverity": 2 }
}
}Les clés des métadonnées doivent correspondre au chemin normalisé dans l’archive, dossiers compris. Pour les importations NDJSON, chaque enregistrement peut contenir son propre objet metadata, qui a priorité sur une entrée imageMetadata correspondante. Les chemins d’archive sont limités à 1 024 caractères, les clés de métadonnées de premier niveau à 128 caractères, et chaque objet de métadonnées — ainsi que l’ensemble de la mappe imageMetadata — à 500 000 caractères sérialisés.
La première ingestion crée automatiquement les classes à partir de l’archive. Lors des ingestions suivantes, les classes de l’archive absentes de classMapping sont associées par nom aux classes existantes du jeu de données, sans tenir compte de la casse pour les noms de plus de deux caractères ; les classes sans correspondance sont ajoutées comme nouvelles classes. Les étiquettes sont ignorées uniquement pour les classes explicitement associées à null.
Réponse (201) :
{
"jobId": "65f1c0a2b3d4e5f6012345aa",
"status": "queued"
}graph LR
A[POST /api/datasets]:::start --> B[POST /api/upload/signed-url]:::proc
B --> C[PUT archive to signed URL]:::proc
C --> D["POST /api/upload/complete (optional)"]:::proc
D --> E["POST /api/datasets/{owner}/{dataset}/ingest"]:::proc
E --> F[Process archive]:::proc
F --> G[Dataset ready]:::out
classDef start fill:#4CAF50,color:#fff
classDef proc fill:#2196F3,color:#fff
classDef out fill:#9C27B0,color:#fffTéléverser une image avec ses métadonnées à l’aide de Python
Le même code traite un groupe d’images : ajoute des fichiers à l’archive ZIP et les entrées correspondantes à imageMetadata.
import io
import zipfile
from pathlib import Path
import requests
api = "https://platform.ultralytics.com/api"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
owner, dataset = "acme-vision", "warehouse"
dataset_id = "65f1c0a2b3d4e5f601234567" # id returned by POST /api/datasets
image_path = Path("airbus-wing.jpg")
archive = io.BytesIO()
with zipfile.ZipFile(archive, "w", zipfile.ZIP_DEFLATED) as zf:
zf.write(image_path, image_path.name)
data = archive.getvalue()
signed = requests.post(
f"{api}/upload/signed-url",
headers=headers,
json={
"assetType": "datasets",
"assetId": dataset_id,
"filename": "images.zip",
"contentType": "application/zip",
"totalBytes": len(data),
},
)
signed.raise_for_status()
upload = signed.json()
headers_put = {"Content-Type": "application/zip", **upload.get("headers", {})}
requests.put(upload["uploadUrl"], headers=headers_put, data=data).raise_for_status()
requests.post(
f"{api}/upload/complete",
headers=headers,
json={"sessionId": upload["sessionId"]},
).raise_for_status()
ingest = requests.post(
f"{api}/datasets/{owner}/{dataset}/ingest",
headers=headers,
json={
"sessionId": upload["sessionId"],
"imageMetadata": {
"airbus-wing.jpg": {
"aircraft": {"family": "A350", "section": "wing"},
"inspectionStatus": "reviewed",
}
},
},
)
ingest.raise_for_status()
print(ingest.json())API Images#
Inspecte, annote, déplace et supprime les images du jeu de données à l’aide de leur ID d’image de 24 caractères. Consulte la documentation sur les annotations.
Obtenir une image#
GET /api/images/{imageId}SDK Python : client.images.retrieve(image_id)
Renvoie metadata (personnalisé, défini par l’utilisateur), properties (nom de fichier, hachage, dimensions, partition, nombres, horodatages), labels et classNames du jeu de données.
Mettre à jour une image#
PATCH /api/images/{imageId}SDK Python : client.images.update(image_id, body=...)
Remplace soit les annotations, soit les métadonnées personnalisées — envoie l’une des deux structures, pas les deux.
Corps (annotations) :
{
"labels": [
{ "classId": 0, "bbox": [0.5, 0.5, 0.2, 0.3] },
{ "classId": 1, "segments": [0.1, 0.2, 0.3, 0.2, 0.2, 0.4] }
]
}Corps (métadonnées) :
{
"metadata": { "location": "strasbourg", "reviewed": true }
}Les coordonnées des étiquettes utilisent les valeurs normalisées YOLO comprises entre 0 et 1. Les boîtes englobantes utilisent [x_center, y_center, width, height]. Les étiquettes de segmentation utilisent segments, une liste aplatie de sommets de polygone [x1, y1, x2, y2, ...]. Les étiquettes de pose utilisent keypoints selon une structure aplatie cohérente : des paires [x1, y1, x2, y2, ...] ou des triplets [x1, y1, v1, x2, y2, v2, ...], où la visibilité est généralement codée par 0, 1 ou 2. Les boîtes orientées utilisent les coins obb. Les coordonnées enregistrées sont arrondies à 5 décimales, et une image peut contenir au maximum 10 000 annotations.
Supprimer une image#
DELETE /api/images/{imageId}SDK Python : client.images.delete(image_id)
Supprime définitivement une image et ses annotations.
Annoter automatiquement une image#
POST /api/images/{imageId}/predictSDK Python : client.images.predict(image_id, model_id=...)
Exécute le modèle sur l’image et renvoie les annotations prédites. Elles ne sont pas enregistrées — renvoie les résultats avec PATCH /api/images/{imageId} lorsque tu en es satisfait.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
modelId | chaîne | Oui | URI complète du modèle, ul://{owner}/{project}/{model} ou ID d’un modèle avec invite de classe pour un jeu de données de détection comportant 1 à 200 classes : un modèle hébergé (qwen, moondream, florence2, owlv2, yoloe26x, sam3, sam3.1, groundingdino) ou l’ID d’un modèle d’un fournisseur payant issu de l’énumération modelId dans openapi.json |
confidence | float | Non | Seuil de confiance, de 0,01 à 1,0 (par défaut : 0,25) ; ignoré par les modèles avec invite de classe, qui utilisent des seuils propres au modèle |
iou | float | Non | Seuil IoU pour la suppression des non-maxima, de 0,0 à 0,95 (par défaut : 0,7) ; ignoré par les modèles avec invite de classe |
classMapping | tableau | Non | Pour un modèle YOLO, l’index de classe du jeu de données correspondant à chaque classe du modèle, dans l’ordre, ou null pour ignorer cette classe ; une longueur incorrecte ou un index hors des classes du jeu de données renvoie 400. Ignoré par les modèles avec invite de classe |
Réponse : success, predictions (objets d’annotation), confidences (scores alignés sur les index, vide pour les modèles avec invite de classe), modelUsed, inferenceTime, pour les modèles avec invite de classe partial (true lorsque la sortie tronquée d’un modèle génératif ne contient que les boîtes complètes) et, pour les modèles de fournisseurs payants, éventuellement cost (coût estimé du fournisseur en USD facturé sur ta clé fournisseur, omis si aucune estimation n’est disponible). Un modèle YOLO dont les classes ne correspondent pas au jeu de données renvoie 422, tout comme un modèle avec invite de classe utilisé sur un jeu de données qui n’est pas destiné à la détection ou qui comporte un nombre de classes hors de la plage de 1 à 200, ainsi qu’un modèle de fournisseur payant sans clé fournisseur enregistrée dans les Settings > API Keys de l’espace de travail du jeu de données (code : missing_provider_api_key). Une erreur du fournisseur inclut son message : 422 lorsque le fournisseur répond 400, 401, 403 ou 404 (clé, modèle ou requête refusés), 429 en cas de limite de débit, et 503 pour toute autre erreur du fournisseur. Les jeux de données de profondeur renvoient 400, tout comme les jeux de données sur un stockage connecté ou comportant plus de 3 canaux d’image renvoient 409.
Trouver des images similaires#
GET /api/images/{imageId}/similarSDK Python : client.images.find_similar_images(image_id)
Renvoie jusqu’à 24 images visuellement similaires provenant de jeux de données publics, des jeux de données personnels et d’équipe, chacun avec score (0-1), une URL signée thumbnailUrl et la source dataset (owner, dataset, license). Les images déjà présentes dans le jeu de données source et les copies de l’image de requête sont exclues. Nécessite une clé API disposant d’un accès en lecture à l’image ; une image qui n’a pas encore été intégrée est d’abord intégrée, et 503 indique que cette préparation a échoué : réessaie.
Annoter automatiquement un jeu de données#
POST /api/datasets/{owner}/{dataset}/predict/batchSDK Python : client.datasets.create_batch(owner, dataset, body={...}) (ultralytics-platform>=0.1.57)
Enregistre une version du jeu de données, puis met en file d’attente une exécution qui annote les images sans étiquette du jeu de données à l’aide du modèle et renvoie 202. Le corps accepte les mêmes champs modelId, confidence, iou et classMapping que le point de terminaison pour une seule image, ainsi que includeAnnotated (par défaut : false) pour annoter également les images déjà étiquetées. Un modèle avec invite de classe détecte les classes du jeu de données sans scores de confiance, et un modèle de fournisseur payant nécessite une clé fournisseur enregistrée dans l’espace de travail du jeu de données Settings > API Keys (422, code : missing_provider_api_key, avant l’admission de l’exécution). Les étiquettes existantes ne sont jamais modifiées, et l’exécution est facturée en fonction des images qu’elle traite réellement. 402 signifie que le solde ne couvre pas le montant estimé, 409 que le jeu de données n’est pas prêt, qu’il ne reste aucune image à annoter ou qu’une exécution est déjà en cours, et 422 que le jeu de données ne comporte aucune classe ou qu’un modèle avec invite de classe est utilisé sur un jeu de données qui n’est pas destiné à la détection ou qui comporte un nombre de classes hors de la plage de 1 à 200 : crée les classes avec le point de terminaison des classes avant d’appeler ce point de terminaison ; c’est ce que fait l’étape de mappage des classes de l’application avant de lancer une exécution.
GET sur le même chemin (client.datasets.batch(owner, dataset)) renvoie l’exécution en cours et sa progression, ou la dernière exécution terminée jusqu’à ce qu’elle soit ignorée ; son results inclut partialImages lorsque l’exécution d’un modèle génératif n’a conservé que les boîtes complètes de la sortie tronquée ; DELETE (client.datasets.delete_batch(owner, dataset)) annule une exécution en cours ou règle la facturation et ignore le résumé de l’exécution terminée.
Le même point de terminaison floute les visages avec "operation": "blur", confidence (par défaut 0.25) et boxScale (0.5–1.5, par défaut 1) ; imageId limite l’exécution à une image. Il ne crée aucune version et ne modifie jamais les étiquettes. Envoie "preview": true pour traiter jusqu’à six images sans les modifier, puis envoie le jobId renvoyé en tant que previewJobId avec les mêmes paramètres pour appliquer les modifications ; un aperçu déjà appliqué ne peut pas être réutilisé et renvoie 409. Lorsqu’un aperçu est en attente, transmets son ID à DELETE en tant que previewJobId pour le supprimer.
{ "operation": "blur", "confidence": 0.25, "boxScale": 1, "preview": true }Déplacer des images en masse#
PATCH /api/images/bulkSDK Python : client.images.update_bulk(image_ids=..., split=...)
Déplace jusqu’à 1 000 images d’un jeu de données vers une autre partition.
{
"imageIds": ["65f1c0a2b3d4e5f601234567"],
"split": "val",
"conflictPolicy": "skip"
}Les conflits de nom de fichier ou de contenu renvoient 409 jusqu’à ce que tu choisisses une valeur conflictPolicy unique pour l’ensemble du lot parmi skip, keep_both ou replace. La réponse indique modifiedCount, skippedCount et targetSplit.
Supprimer des images en masse#
DELETE /api/images/bulkSDK Python : client.images.delete_bulk(image_ids=...)
{
"imageIds": ["65f1c0a2b3d4e5f601234567", "65f1c0a2b3d4e5f601234568"]
}Supprime jusqu’à 1 000 images d’un seul jeu de données et renvoie deletedCount et deletedImageIds.
Obtenir des URL d’image signées#
POST /api/images/urlsSDK Python : client.images.urls(image_ids=...)
Renvoie des URL signées temporaires pour un maximum de 100 ID d’image provenant d’un seul jeu de données.
{
"imageIds": ["65f1c0a2b3d4e5f601234567"]
}Réponse : urls, thumbnails et depths (aperçus des cibles de profondeur pour les images de profondeur appariées), tous indexés par ID d’image.
API Projets#
Organise tes modèles en projets. Chaque modèle appartient à un projet. Consulte la documentation sur les projets.
Lister les projets#
GET /api/projects/{owner}SDK Python : client.projects.list(owner)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
limit | int | Nombre maximal de projets à renvoyer (par défaut : 20, maximum : 500) |
Obtenir un projet#
GET /api/projects/{owner}/{project}SDK Python : client.projects.retrieve(owner, project)
Renvoie l’objet project, un tableau models contenant un résumé par modèle (état, métriques, époques, poids, arguments d’entraînement), et isOwner. Transmets search (200 caractères maximum) pour filtrer models par nom de modèle ou métadonnées.
Créer un projet#
POST /api/projectsSDK Python : client.projects.create(project=..., name=...)
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
project | chaîne | Oui | Nom du projet utilisé dans les URL de la plateforme |
name | chaîne | Oui | Nom d'affichage (100 caractères maximum) |
description | chaîne | Non | Description (1000 caractères maximum) |
visibility | chaîne | Non | public ou private |
tags | tableau | Non | Jusqu’à 50 étiquettes |
license | chaîne | Non | Identifiant de licence du projet |
metadata | objet | Non | Métadonnées JSON personnalisées |
owner | chaîne | Non | Identifiant de l'espace de travail d'équipe ; par défaut, ton espace de travail personnel |
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"project": "inspection",
"name": "Inspection",
"description": "Detection experiments",
"metadata": {"department": "manufacturing", "cost_center": "cv-01"}
}' \
https://platform.ultralytics.com/api/projectsRéponse (201) : id, owner, project, region.
Un slug project qui existe déjà dans l'espace de travail, y compris dans la corbeille, renvoie 409.
Mettre à jour un projet#
PATCH /api/projects/{owner}/{project}SDK Python : client.projects.update(owner, project)
Champs acceptés : name, description, visibility, metadata, tags, license, archived, iconColor, iconLetter, viewPreferences et starred.
{
"metadata": { "department": "research", "program": "inspection" }
}Envoie un objet metadata vide ({}) pour l'effacer. Les métadonnées du projet sont soumises aux mêmes limites que les métadonnées du jeu de données : une clé de 128 caractères et un objet sérialisé de 500 000 caractères.
Supprimer le projet#
DELETE /api/projects/{owner}/{project}SDK Python : client.projects.delete(owner, project)
Déplace le projet et ses modèles vers la corbeille et renvoie cascadedModels, puis supprime définitivement leurs déploiements. La restauration du projet ne restaure pas les déploiements. 502 signifie que le nettoyage des déploiements n'est pas terminé ; les modèles restent dans la corbeille jusqu'à ce qu'il réussisse.
Cloner un projet#
POST /api/projects/{owner}/{project}/cloneSDK Python : client.projects.clone(owner, project)
Clone un projet accessible et ses modèles entraînés. Le corps facultatif accepte project, name, description, visibility, license et une destination owner.
API des modèles#
Gère les modèles YOLO entraînés : consulte les métriques, télécharge les poids, lance l'inférence et surveille l'entraînement. Consulte la documentation sur les modèles.
Lister les modèles d'un projet#
GET /api/models/{owner}/{project}SDK Python : client.models.list(owner, project)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
limit | int | Nombre maximal de modèles à renvoyer (par défaut : 20, maximum : 100) |
Obtenir un modèle#
GET /api/models/{owner}/{project}/{model}SDK Python : client.models.retrieve(owner, project, model)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
analysis | int | Définis sur 1 pour renvoyer l'analyse de validation par image plutôt que le modèle |
La réponse par défaut contient l'objet model — état, tâche, métriques, trainArgs, trainResults, classNames, computeCost, metadata et plus encore — ainsi que isOwner.
Créer un modèle#
POST /api/modelsSDK Python : client.models.create(body=...)
Crée un enregistrement de modèle non entraîné auquel tu peux associer des poids ou que tu peux entraîner.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
project | chaîne | Oui | Nom du projet de destination |
owner | chaîne | Non | Identifiant de l'espace de travail ; par défaut, ton espace de travail personnel |
model | chaîne | Non | Nom du modèle utilisé dans les URL de la plateforme ; généré s'il n'est pas fourni |
name | chaîne | Non | Nom affiché (accepté uniquement avec model) |
description | chaîne | Non | Description (1000 caractères maximum) |
task | chaîne | Non | detect, segment, semantic, depth, classify, pose ou obb |
metadata | objet | Non | Métadonnées JSON personnalisées |
trainArgs | objet | Non | Arguments d'entraînement à enregistrer |
metrics | objet | Non | Métriques telles que mAP50, mAP50-95, precision, recall |
epochs | nombre | Non | Nombre d'époques pour un modèle déjà entraîné |
version | chaîne | Non | Libellé de version (50 caractères maximum) |
Réponse (201) : id, owner, project, model, region.
Pour associer des poids .pt, demande une URL de téléversement signée avec assetType: "models" et le id de ce modèle comme assetId, PUT le fichier vers l'URL renvoyée, puis appelle POST /api/upload/complete avec le sessionId renvoyé.
Mettre à jour le modèle#
PATCH /api/models/{owner}/{project}/{model}SDK Python : client.models.update(owner, project, model)
Les champs acceptés incluent name, description, color, metadata, status, license, datasetSlug, trainArgs, trainResults, epochs, bestEpoch, bestFitness, version, trainingError et starred. Fournir uniquement projectId déplace le modèle vers un autre projet appartenant au même propriétaire ; la réponse renvoie le slug du modèle dans le projet de destination, renamed: true si ce slug y est déjà pris, et 409 tant que le modèle est en cours d'entraînement.
{
"metadata": { "release": "candidate-3", "reviewed": true }
}Les champs personnalisés metadata sont distincts des champs gérés par l'entraînement tels que trainArgs, environment et trainResults, et sont soumis aux mêmes limites de taille que les métadonnées du jeu de données.
Supprimer le modèle#
DELETE /api/models/{owner}/{project}/{model}SDK Python : client.models.delete(owner, project, model)
Déplace le modèle vers la corbeille pendant 30 jours et supprime définitivement chaque déploiement qui l'utilise, y compris les remplacements en attente. La restauration du modèle ne restaure pas les déploiements.
Télécharger les fichiers du modèle#
GET /api/models/{owner}/{project}/{model}/filesSDK Python : client.models.files(owner, project, model)
Renvoie des URL signées de courte durée pour les poids du modèle.
{
"files": [
{
"name": "best.pt",
"size": 6534127,
"downloadUrl": "https://storage.googleapis.com/...&signature=..."
}
]
}Trouver des images similaires aux pires images de validation#
GET /api/models/{owner}/{project}/{model}/similar-imagesSDK Python : client.models.find_similar_training_images(owner, project, model)
Renvoie jusqu'à 100 images, au même format que Trouver des images similaires, qui ressemblent aux images de validation pour lesquelles ce cycle d'entraînement a obtenu les pires scores, à l'exclusion des images déjà présentes dans son jeu de données d'entraînement. Fournis hashes (séparés par des virgules, jusqu'à 100) pour lancer la recherche à partir d'un sous-ensemble de ces pires images. Nécessite une clé API ayant accès à l'espace de travail du modèle. La liste est vide si le cycle n'a enregistré aucun résultat par image, et 404 signifie également que les pires images ne sont pas encore intégrées : lance d'abord l'intégration des données du jeu de données sur le jeu de données d'entraînement.
Cloner le modèle#
POST /api/models/{owner}/{project}/{model}/cloneSDK Python : client.models.clone(owner, project, model, project_body=...)
Copie un modèle accessible dans un projet existant.
{
"owner": "acme-vision",
"project": "inspection",
"model": "v3-copy",
"name": "V3 Copy",
"description": "Cloned from a public model"
}| Champ | Type | Obligatoire | Description |
|---|---|---|---|
project | chaîne | Oui | Nom du projet de destination |
owner | chaîne | Non | Espace de travail de destination ; par défaut, ton espace personnel |
model | chaîne | Non | Nom du modèle de destination |
name | chaîne | Non | Nom affiché de destination |
description | chaîne | Non | Description du clone |
Exécuter l’inférence#
POST /api/models/{owner}/{project}/{model}/predictSDK Python : client.models.predict(owner, project, model, body=...)
Les modèles publics peuvent être utilisés pour des prédictions sans authentification. Les modèles privés et partagés nécessitent une clé API ayant accès au projet parent.
Formulaire multipart :
| Paramètre | Type | Valeur par défaut | Plage | Description |
|---|---|---|---|---|
file | fichier | - | - | Fichier image ou vidéo (obligatoire sauf si source est défini) |
conf | float | 0.25 | 0.01 – 1.0 | Seuil de confiance minimal |
iou | float | 0.7 | 0.0 – 0.95 | Seuil IoU de la NMS |
imgsz | int | - | 32 – 1280 | Taille de l’image d’entrée en pixels ; par défaut, la taille utilisée pour l’entraînement du modèle (640 si elle n’est pas disponible) |
normalize | bool | false | - | Renvoyer les coordonnées des boîtes englobantes entre 0 et 1 |
decimals | int | 5 | 0 – 10 | Précision décimale des valeurs de coordonnées |
vid_stride | int | 1 | ≥ 1 | Prédire une image vidéo sur N ; les images fixes ne sont pas concernées |
bits | int | 8 | 8, 12, 16 | Quantification de la carte de profondeur, modèles de profondeur uniquement |
source | chaîne | - | - | URL d’image ou chaîne encodée en base64 (alternative à file) ; 4 096 caractères max. via l’API de la plateforme |
Fournis file ou source. Les modèles de profondeur acceptent également bits (8, 12 ou 16) pour définir la quantification PNG de la carte de profondeur. Les requêtes qui dépassent les limites d'entrée du service renvoient 413.
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@image.jpg" \
-F "conf=0.5" \
https://platform.ultralytics.com/api/models/acme-vision/inspection/v3/predictRéponse :
Chaque entrée de images contient shape, speed, results et, pour les tâches de prédiction dense, une charge utile PNG semantic_mask ou depth (les valeurs de profondeur sont pixel × max / divisor, avec un diviseur de 255 pour la carte 8 bits par défaut et de 65535 lorsque bits vaut 12 ou 16). L'objet metadata indique le nombre d'images, les noms des classes du modèle, les durées d'exécution des fonctions, la tâche et les versions du service. Les chemins internes des modèles ne sont jamais renvoyés.
{
"images": [
{
"shape": [1080, 1920],
"speed": { "preprocess": 2.1, "inference": 12.4, "postprocess": 1.3 },
"results": [
{
"class": 0,
"name": "person",
"confidence": 0.92,
"box": { "x1": 100, "y1": 50, "x2": 300, "y2": 400 }
}
]
}
],
"metadata": {
"imageCount": 1,
"classNames": ["person", "forklift"],
"functionTimeAlive": 184.2,
"functionTimeCall": 0.31,
"task": "detect",
"version": { "ultralytics": "8.4.120" }
}
}Vérifier la progression de l'entraînement#
GET /api/models/{owner}/{project}/{model}/trainingSDK Python : client.models.training(owner, project, model)
Renvoie job, qui contient l'état, la progression des époques, les durées, les détails du calcul, les arguments d'entraînement, les métriques par époque et des détails d'erreur sécurisés, ou null si le modèle n'a jamais été entraîné. Les modèles des projets publics peuvent être consultés sans authentification.
Annuler l’entraînement#
DELETE /api/models/{owner}/{project}/{model}/trainingSDK Python : client.models.delete_training(owner, project, model)
Arrête l'instance de calcul en cours et marque le travail comme annulé. Renvoie 409 lorsque l'entraînement n'est plus actif.
API d'entraînement#
Lance l'entraînement YOLO sur des GPU cloud et suis la progression en temps réel. Consulte la documentation sur l'entraînement cloud.
graph LR
A[POST /api/training/start]:::start --> B[Job Created]:::proc
B --> C{Training}:::decide
C -->|progress| D[GET .../training]:::proc
C -->|cancel| E[DELETE .../training]:::error
C -->|complete| F[Model Ready]:::out
F --> G[Deploy or Export]:::proc
classDef start fill:#4CAF50,color:#fff
classDef proc fill:#2196F3,color:#fff
classDef decide fill:#FF9800,color:#fff
classDef out fill:#9C27B0,color:#fff
classDef error fill:#F44336,color:#fffObtenir la disponibilité des GPU#
GET /api/training/gpu-availabilitySDK Python : client.training.gpu_availability()
Renvoie l'état actuel des stocks, indexé par ID de GPU. Accessible au public et sans authentification ; fournis managed=true pour inclure la capacité d'entraînement gérée, qui nécessite une clé API.
Démarrer l'entraînement#
POST /api/training/startSDK Python : client.training.start(model_id=..., train_args=...)
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
modelId | chaîne | Oui | ID du modèle à entraîner |
trainArgs | objet | Oui | Arguments d'entraînement YOLO ; model, data et epochs sont obligatoires |
gpuType | chaîne | Non | GPU cloud à utiliser (par défaut : rtx-4090) |
captureDatasetVersion | booléen | Non | Enregistrer une version immuable du jeu de données pour ce cycle (par défaut : false) |
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"modelId": "65f1c0a2b3d4e5f601234599",
"gpuType": "rtx-4090",
"trainArgs": {
"model": "yolo26n.pt",
"data": "ul://acme-vision/datasets/warehouse",
"epochs": 100,
"imgsz": 640,
"batch": 16
}
}' \
https://platform.ultralytics.com/api/training/startRéponse :
{
"modelId": "65f1c0a2b3d4e5f601234599",
"status": "starting",
"gpuType": "rtx-4090",
"estimatedCost": { "pricePerHour": 0.69, "gpuMemoryGb": 24 },
"billing": {
"estimatedCostCents": 138,
"estimatedCostDisplay": "$1.38",
"balanceCents": 2500
}
}L'entraînement renvoie 402 lorsque ton solde de crédits est trop bas et 503 lorsqu'aucune capacité n'est disponible pour le GPU demandé.
26 types de GPU sont disponibles, de rtx-2000-ada à b300, notamment rtx-4090, l40s, a100-80gb-pcie, a100-80gb-sxm, rtx-pro-6000, h100-sxm, h200-sxm et b200. Consulte l'entraînement cloud pour obtenir la liste complète et les tarifs.
API des exports#
Convertis les modèles en formats optimisés tels que ONNX, TensorRT, CoreML et LiteRT pour le déploiement en périphérie. Consulte la documentation sur le déploiement.
Lister les exports#
GET /api/models/{owner}/{project}/{model}/exportsSDK Python : client.exports.list(owner, project, model)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
status | chaîne | Filtrer par queued, starting, running, completed, failed ou cancelled |
limit | int | Nombre maximal d'exports à renvoyer (par défaut : 20, maximum : 100) |
Créer un export#
POST /api/models/{owner}/{project}/{model}/exportsSDK Python : client.exports.create(owner, project, model, format=...)
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
format | chaîne | Oui | Format d'export cible (voir le tableau ci-dessous) |
gpuType | chaîne | Conditionnel | Obligatoire lorsque format est engine ; utilise une cible GPU ou Jetson prise en charge |
args | objet | Non | Options d’exportation : imgsz, quantize, dynamic, simplify, opset, conf, iou, batch, workspace, nms, optimize et name (cible de l’appareil pour RKNN, QNN, Hailo, Ascend et Xilinx) |
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"format": "onnx", "args": {"imgsz": 640, "quantize": 16}}' \
https://platform.ultralytics.com/api/models/acme-vision/inspection/v3/exportsChaque format ne prend en compte que les options de sa colonne Arguments dans le tableau d'export ci-dessous : une valeur autre que celle par défaut pour batch, dynamic, opset, simplify, workspace ou optimize pour un format qui ne la prend pas en charge renvoie 400. Les exports imx sont uniquement en INT8 et disponibles pour les modèles de détection, de segmentation, de classification et d'estimation de pose ; les modèles YOLO26 et les tailles YOLOv8 ou YOLO11 autres que nano renvoient 400.
Réponse (201) : id, format, status (queued ou running), region et gpuType pour les exports TensorRT. Un export équivalent déjà en cours renvoie 409.
Formats pris en charge :
Utilise l'argument format du tableau d'export commun ci-dessous. PyTorch est le format source et n'est pas une cible d'export de l'API.
| Format | Argument format | Modèle | Métadonnées | Arguments |
|---|---|---|---|---|
| PyTorch | - | yolo26n.pt | ✅ | - |
| TorchScript | torchscript | yolo26n.torchscript | ✅ | imgsz, quantize, dynamic, nms, batch, device |
| ONNX | onnx | yolo26n.onnx | ✅ | imgsz, quantize, dynamic, simplify, opset, nms, batch, data, fraction, device |
| OpenVINO | openvino | yolo26n_openvino_model/ | ✅ | imgsz, quantize, dynamic, nms, batch, data, fraction, device |
| TensorRT | engine | yolo26n.engine | ✅ | imgsz, quantize, dynamic, simplify, opset, workspace, nms, batch, data, fraction, device |
| CoreML | coreml | yolo26n.mlpackage | ✅ | imgsz, dynamic, quantize, nms, batch, device |
| Apple Core AI | coreai | yolo26n.aimodel | ✅ | imgsz, batch, quantize |
| TF SavedModel | saved_model | yolo26n_saved_model/ | ✅ | imgsz, quantize, opset, nms, batch, data, fraction, device |
| TF GraphDef | pb | yolo26n.pb | ❌ | imgsz, opset, batch, device |
| TF Edge TPU | edgetpu | yolo26n_edgetpu.tflite | ✅ | imgsz, quantize, opset, data, fraction, device |
| LiteRT | litert | yolo26n.tflite | ✅ | imgsz, quantize, batch, data, fraction, device |
| PaddlePaddle | paddle | yolo26n_paddle_model/ | ✅ | imgsz, batch, device |
| MNN | mnn | yolo26n.mnn | ✅ | imgsz, batch, dynamic, quantize, simplify, opset, nms, device |
| NCNN | ncnn | yolo26n_ncnn_model/ | ✅ | imgsz, quantize, batch, device |
| IMX500 | imx | yolo26n_imx_model/ | ✅ | imgsz, quantize, data, fraction, nms, device |
| RKNN | rknn | yolo26n_rknn_model/ | ✅ | imgsz, batch, name, quantize, simplify, opset, data, fraction, device |
| ExecuTorch | executorch | yolo26n_executorch_model/ | ✅ | imgsz, batch, device |
| Axelera | axelera | yolo26n_axelera_model/ | ✅ | imgsz, batch, quantize, data, fraction, device |
| DEEPX | deepx | yolo26n_deepx_model/ | ✅ | imgsz, quantize, simplify, opset, data, optimize, device |
| Qualcomm QNN | qnn | yolo26n_qnn.onnx | ✅ | imgsz, batch, name, quantize, simplify, opset, data, fraction, device |
| Hailo | hailo | yolo26n_hailo_model/ | ✅ | imgsz, name, quantize, data, fraction, simplify, conf, iou, device |
| Huawei Ascend | ascend | yolo26n_ascend_model/ | ✅ | imgsz, batch, name, quantize, opset, simplify, nms, device |
| AMD Xilinx | xilinx | yolo26n_xilinx_model/ | ✅ | imgsz, name, quantize, data, fraction, opset, simplify, device |
nms=None produit par défaut des sorties brutes pour la NMS externe. Définis nms=False pour sélectionner une tête disponible sans NMS ; les formats non pris en charge utilisent leur voie de sortie native. Les entrées nms ci-dessus désignent les formats qui peuvent intégrer la NMS avec nms=True.
Obtenir l'état de l'export#
GET /api/models/{owner}/{project}/{model}/exports/{exportId}SDK Python : client.exports.retrieve(owner, project, model, export_id)
Renvoie l'objet export avec status, format, args, gpuType (TensorRT uniquement), les horodatages et — une fois l'export terminé — un objet file contenant size, downloadUrl et downloadFilename.
Annuler ou supprimer un export#
DELETE /api/models/{owner}/{project}/{model}/exports/{exportId}SDK Python : client.exports.delete(owner, project, model, export_id)
Annule un export actif ou supprime un export terminé et son fichier. La réponse indique ce qui s'est produit :
{
"success": true,
"action": "cancelled"
}API des déploiements#
Déploie des modèles sur des points de terminaison d'inférence dédiés avec des vérifications d'état et une surveillance. Consulte la documentation sur les points de terminaison.
graph LR
A[Create]:::start --> B[Deploying]:::proc
B --> C[Ready]:::out
C -->|action stop| D[Stopped]:::extern
C -->|action replace| B
D -->|action start| C
C -->|delete| E[Deleted]:::error
D -->|delete| E
C -->|predict| F[Inference Results]:::out
classDef start fill:#4CAF50,color:#fff
classDef proc fill:#2196F3,color:#fff
classDef out fill:#9C27B0,color:#fff
classDef error fill:#F44336,color:#fff
classDef extern fill:#607D8B,color:#fffLister les déploiements#
GET /api/deployments/{owner}SDK Python : client.deployments.list(owner)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
status | chaîne | creating, deploying, ready, stopping, stopped ou failed |
model | chaîne | Filtrer par {project}/{model}, par exemple inspection/v3 |
limit | int | Nombre maximal de déploiements à renvoyer (par défaut : 20, maximum : 100) |
Les appelants anonymes doivent filtrer sur un modèle public ; lister un espace de travail entier nécessite une authentification.
Créer un déploiement#
POST /api/deployments/{owner}SDK Python : client.deployments.create(owner, project=..., model=..., deployment=..., name=..., region=...)
Corps :
{
"project": "inspection",
"model": "v3",
"deployment": "edge-1",
"name": "Edge 1",
"region": "us-central1"
}| Champ | Type | Obligatoire | Description |
|---|---|---|---|
project | chaîne | Oui | Projet contenant le modèle |
model | chaîne | Oui | Modèle à déployer |
deployment | chaîne | Oui | Nom du déploiement utilisé dans les URL de la plateforme |
name | chaîne | Oui | Nom affiché |
region | chaîne | Oui | L'une des 42 régions de déploiement prises en charge |
cpu | nombre | Non | Cœurs vCPU : 1 (par défaut), 2, 4, 6 ou 8 |
memoryGi | nombre | Non | Mémoire en Gio : 2 (par défaut), 4, 8, 16, 24 ou 32 |
Réponse (201) : id, deployment, status (creating), message et region.
La configuration par défaut de 1 vCPU / 2 Gio passe à zéro lorsqu'elle est inactive et peut bénéficier d'un quota de déploiement gratuit ; les autres configurations sont facturées selon une tarification à l'usage. Les valeurs actuelles sont renvoyées dans l'objet resources à chaque lecture du déploiement.
Choisis une région proche de tes utilisateurs pour réduire la latence. L'interface de la plateforme affiche des estimations de latence pour les 42 régions disponibles.
Obtenir un déploiement#
GET /api/deployments/{owner}/{deployment}SDK Python : client.deployments.retrieve(owner, deployment)
Renvoie l’objet deployment avec status, statusMessage, region, serviceUrl, resources et metadata personnalisés, ainsi que camera et cameraApplying pour le propriétaire.
Mettre à jour un déploiement#
PATCH /api/deployments/{owner}/{deployment}SDK Python : client.deployments.update(owner, deployment, body=...)
Envoie l'un de ces corps :
{ "name": "Edge 1 (primary)" }Le renommage définit la valeur deployment de l’URL avec un slug du nouveau nom, renvoyé sous la forme deployment ; l’ancien chemin renvoie 404 et le serviceUrl reste inchangé. Un objet metadata vide supprime les métadonnées personnalisées. Le remplacement déploie une nouvelle révision tout en conservant l’ID du déploiement, la région et l’URL du point de terminaison ; la révision existante reste active si le déploiement échoue. Le modèle de remplacement doit être un modèle terminé dont les poids sont accessibles avec ta clé. L’action caméra enregistre une caméra RTSP ou RTSPS sur laquelle un point de terminaison prêt doté de ressources personnalisées continue d’exécuter l’inférence (voir Caméra en arrière-plan) ; "url": null la supprime, tout comme le redimensionnement à la taille par défaut, et l’enregistrement d’une caméra sur un point de terminaison de taille par défaut renvoie 403. Un changement de caméra renvoie 202 avec status ready pendant son application : interroge le déploiement jusqu’à ce que cameraApplying ne soit plus true, puis vérifie camera ; si le changement échoue, la caméra précédente est conservée et statusMessage est défini. Les opérations terminées renvoient 200 avec status ready ou stopped ; les autres opérations encore en cours de déploiement renvoient 202 avec deploying ou stopping.
Supprimer le déploiement#
DELETE /api/deployments/{owner}/{deployment}SDK Python : client.deployments.delete(owner, deployment)
Supprime définitivement le point de terminaison d’inférence.
Vérification de l’état#
GET /api/deployments/{owner}/{deployment}/healthSDK Python : client.deployments.health(owner, deployment)
Envoie une requête ping au point de terminaison et le réchauffe, puis renvoie healthy, latencyMs et le code status en amont.
Exécuter l’inférence sur un déploiement#
POST /api/deployments/{owner}/{deployment}/predictSDK Python : client.deployments.predict(owner, deployment, body=...)
Achemine une image ou une vidéo via le point de terminaison dédié. Les contrats de requête et de réponse sont identiques à ceux de l’inférence de modèle. Les flux de caméra ne sont pas relayés ; envoie-les à l’URL du point de terminaison comme indiqué dans Inférence en direct avec une caméra.
Formulaire multipart :
| Paramètre | Type | Valeur par défaut | Plage | Description |
|---|---|---|---|---|
file | fichier | - | - | Fichier image ou vidéo (obligatoire sauf si source est défini) |
conf | float | 0.25 | 0.01 – 1.0 | Seuil de confiance minimal |
iou | float | 0.7 | 0.0 – 0.95 | Seuil IoU de la NMS |
imgsz | int | - | 32 – 1280 | Taille de l’image d’entrée en pixels ; par défaut, la taille utilisée pour l’entraînement du modèle (640 si elle n’est pas disponible) |
normalize | bool | false | - | Renvoyer les coordonnées des boîtes englobantes entre 0 et 1 |
decimals | int | 5 | 0 – 10 | Précision décimale des valeurs de coordonnées |
vid_stride | int | 1 | ≥ 1 | Prédire une image vidéo sur N ; les images fixes ne sont pas concernées |
bits | int | 8 | 8, 12, 16 | Quantification de la carte de profondeur, modèles de profondeur uniquement |
source | chaîne | - | - | URL d’image ou chaîne encodée en base64 (alternative à file) ; 4 096 caractères max. via l’API de la plateforme |
Obtenir les métriques#
GET /api/deployments/{owner}/{deployment}/metricsSDK Python : client.deployments.metrics(owner, deployment)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
range | chaîne | 1h, 6h, 24h (par défaut), 7d ou 30d |
sparkline | booléen | Renvoie le résumé compact du tableau de bord au lieu des séries complètes (par défaut : false) |
view | chaîne | overview renvoie uniquement les métriques des requêtes, des erreurs et de la latence P95 |
La réponse complète contient summary (totaux des requêtes, taux d’erreur, latence moyenne et p50/p95/p99) et timeSeries (requêtes, erreurs, latence, CPU, mémoire, nombre d’instances). La réponse sous forme de graphique sparkline renvoie requests24h (nombre de requêtes par heure ; les heures sans requête sont omises), totalRequests, errorRate et avgLatencyMs (moyenne des latences P95 horaires). Avec view=overview, summary contient totalRequests, errorRate et p95LatencyMs, tandis que timeSeries contient requests, errors et latencyP95.
Obtenir les journaux#
GET /api/deployments/{owner}/{deployment}/logsSDK Python : client.deployments.logs(owner, deployment)
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
severity | chaîne | Séparés par des virgules : DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY |
limit | int | Nombre d’entrées à renvoyer (par défaut : 50, max. : 200) |
pageToken | chaîne | Jeton de pagination provenant d’une réponse précédente |
API Agents#
Enregistre et gère les workflows Agents. L’API stocke les définitions des agents ; les exécutions démarrent depuis le canevas Agents, où https://platform.ultralytics.com/agents?workflow={id} ouvre un agent enregistré. Les méthodes du SDK Python nécessitent ultralytics-platform>=0.1.74.
Chaque opération accepte un paramètre de requête facultatif owner contenant le nom d’utilisateur d’un espace de travail auquel tu appartiens (par défaut : le tien). La consultation nécessite un accès de lecteur ; l’enregistrement et la suppression nécessitent un accès de rédacteur.
Lister les agents#
GET /api/workflowsSDK Python : client.agents.list()
| Paramètre | Type | Description |
|---|---|---|
owner | chaîne | Nom d’utilisateur de l’espace de travail (par défaut : le tien) |
id | chaîne | Renvoie un agent avec son graph |
search | chaîne | Filtrer par nom d’agent |
La réponse répertorie jusqu’à 100 agents dans workflows, du plus récemment mis à jour au moins récemment, chacun avec id, username, name, version, createdAt et updatedAt. Si tu demandes un id, la réponse renvoie aussi le graph de l’agent.
Enregistrer un agent#
PUT /api/workflowsSDK Python : client.agents.save(name=..., graph=..., version=...)
Envoie version: 0 pour créer un agent. Pour en mettre un à jour, envoie son id et le version renvoyé lors de ta dernière opération de liste ou d’enregistrement ; un version obsolète renvoie 409. Répertorie donc à nouveau l’agent et réessaie. Un graphe dont les connexions forment un cycle ou donnent plusieurs entrées à un bloc renvoie 400.
from ultralytics_platform import Platform
def block(node_id, kind, x, config):
return {
"id": node_id,
"type": "agent",
"position": {"x": x, "y": 0},
"data": {"label": kind, "type": kind, "config": config},
}
graph = {
"nodes": [
block("images", "Dataset", 0, {"dataset": "official:coco8", "split": "val", "maxInputs": 2}),
block("yolo", "YOLO", 220, {"model": "ul://ultralytics/yolo26/yolo26n", "task": "detect"}),
block("output", "Output", 440, {}),
],
"edges": [{"id": "e1", "source": "images", "target": "yolo"}, {"id": "e2", "source": "yolo", "target": "output"}],
"templateId": "",
}
with Platform() as client:
saved = client.agents.save(name="Detect COCO8", graph=graph, version=0)
print(saved["id"], saved["version"], saved["errors"])La réponse renvoie l’agent id, son nouveau version et errors : les blocs que le canevas signalerait, par exemple un bloc Dataset sans jeu de données sélectionné. L’agent est enregistré dans tous les cas. Consulte openapi.json pour connaître tous les types de blocs et leur configuration.
Supprimer un agent#
DELETE /api/workflows?id={id}SDK Python : client.agents.delete(id=...)
Supprime l’agent et annule ses exécutions actives. Les agents supprimés n’apparaissent pas dans la corbeille et ne peuvent pas être restaurés.
API Corbeille#
Consulte, restaure et supprime définitivement les projets, jeux de données et modèles supprimés de manière réversible. Les éléments sont purgés automatiquement après 30 jours. Consulte la documentation sur la corbeille.
Lister le contenu de la corbeille#
GET /api/trashSDK Python : client.lifecycle.trash()
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
type | chaîne | all (par défaut), project, dataset ou model |
page | int | Numéro de page (par défaut : 1) |
limit | int | Nombre d’éléments par page (par défaut : 50, max. : 200) |
id | chaîne | Avec type project ou model, prévisualise les modèles et déploiements concernés par sa suppression |
La réponse inclut items (chacun avec daysRemaining), total, page, limit, totalPages et un summary contenant les totaux par type. Avec id, elle renvoie plutôt resources : les modèles concernés et les déploiements qui seraient supprimés définitivement.
Restaurer un élément#
POST /api/trashSDK Python : client.lifecycle.restore(id=..., type=...)
{
"id": "65f1c0a2b3d4e5f601234567",
"type": "dataset"
}La restauration d’un projet restaure également les modèles qui ont été placés dans la corbeille avec lui, indiqués par restoredModels.
Supprimer définitivement#
DELETE /api/trashSDK Python : client.lifecycle.delete_trash(body=...)
Supprime un seul élément :
{
"id": "65f1c0a2b3d4e5f601234567",
"type": "dataset"
}Ou vide entièrement la corbeille :
{
"all": true
}La réponse indique deletedCount, ainsi que cascadedModels et survivingDeployments le cas échéant.
La suppression définitive est irréversible. La ressource et toutes les données associées sont supprimées.
API de téléversement#
Téléverse des fichiers directement vers le stockage cloud à l’aide d’URL signées. La finalisation du téléversement d’un modèle associe ses poids ; la finalisation du téléversement d’une archive de jeu de données la vérifie. Tu transmets ensuite la session à l’ingestion du jeu de données, qui finalise également le téléversement si tu as ignoré cette étape. Consulte la documentation sur les données.
Obtenir une URL de téléversement signée#
POST /api/upload/signed-urlSDK Python : client.upload.signed_url(body=...)
Corps :
{
"assetType": "datasets",
"assetId": "65f1c0a2b3d4e5f601234567",
"filename": "warehouse.zip",
"contentType": "application/zip",
"totalBytes": 52428800
}| Champ | Type | Obligatoire | Description |
|---|---|---|---|
assetType | chaîne | Oui | datasets ou models |
assetId | chaîne | Oui | ID du jeu de données ou du modèle cible |
filename | chaîne | Oui | Nom de fichier d’origine (256 caractères max.) |
contentType | chaîne | Oui | Type MIME |
totalBytes | nombre | Oui | Taille du fichier en octets |
Lorsque assetType est datasets, filename doit se terminer par .zip, .tar, .tar.gz, .tgz ou .ndjson. Regroupe les images individuelles dans une archive avant le téléversement.
Réponse :
{
"sessionId": "session_abc123",
"uploadUrl": "https://storage.googleapis.com/...&signature=...",
"expiresAt": "2026-02-22T12:00:00Z",
"headers": { "x-goog-if-generation-match": "0" }
}Téléverse le fichier en envoyant une requête PUT à uploadUrl, avec le même Content-Type que celui que tu as indiqué et tous les en-têtes renvoyés dans headers. Les URL de téléversement de jeux de données sont valides pendant 12 heures et ne permettent que la création : un deuxième PUT vers la même URL renvoie 412, et un PUT sans les en-têtes renvoyés entraîne 400.
Finaliser le téléversement#
POST /api/upload/completeSDK Python : client.upload.complete(session_id=...)
{
"sessionId": "session_abc123",
"md5": "<optional md5 hex>"
}Réponse : success et un objet file contenant size et contentType. Pour les modèles, cette opération associe les poids ; pour les archives de jeux de données, appelle ensuite ingest pour démarrer le traitement.
Lorsque md5 est fourni, sa valeur est comparée à l’objet stocké. Une divergence renvoie 400 ; si la session n’est pas encore terminée, le fichier téléversé est également supprimé et la session reste incomplète. Demande donc une nouvelle URL signée et recommence le téléversement. Une session de jeu de données terminée peut l’être à nouveau tant que son archive existe, mais des tentatives de finalisation simultanées avec des empreintes différentes renvoient 409 ; les sessions de modèles sont supprimées à la finalisation. checksum est stocké comme métadonnée du fichier du modèle et n’est pas vérifié.
API des intégrations de stockage#
Connecte des comptes Google Cloud Storage, Amazon S3 ou Azure Blob Storage en lecture seule, puis parcoure-les comme sources de jeux de données. Consulte la documentation sur les intégrations.
La découverte et la connexion de stockage nécessitent un accès administrateur à l’espace de travail et un forfait Pro ou Enterprise (403 dans le cas contraire) ; la consultation des intégrations et des objets nécessite un accès de rédacteur.
Lister les intégrations#
GET /api/integrations/bucketsSDK Python : client.storage_integrations.list()
Renvoie integrations, chacun contenant id, provider, credentialIdentity, targets et createdAt. Les identifiants ne sont jamais renvoyés.
Découvrir les emplacements#
POST /api/integrations/buckets/discoverSDK Python : client.storage_integrations.discover(body=...)
Répertorie les compartiments ou conteneurs accessibles avec les identifiants fournis, sans les enregistrer.
{
"provider": "gcs",
"credentials": {
"client_email": "svc@project.iam.gserviceaccount.com",
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
"project_id": "my-project"
}
}Réponse : {"targets": ["my-bucket", "another-bucket"]}
Connecter un stockage#
POST /api/integrations/bucketsSDK Python : client.storage_integrations.create(body=...)
Utilise les mêmes formats d’identifiants que pour la découverte, auxquels s’ajoute un tableau targets obligatoire contenant de 1 à 50 noms de compartiments ou de conteneurs. Renvoie 201 avec l’intégration enregistrée. Les identifiants temporaires S3 (ASIA clés d’accès) sont refusés.
Parcourir les objets#
GET /api/integrations/buckets/{id}/objectsSDK Python : client.storage_integrations.objects(id, target=...)
Paramètres de requête :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
target | chaîne | Oui | Nom du compartiment ou du conteneur |
prefix | chaîne | Non | Préfixe du dossier (1024 caractères max.) |
cursor | chaîne | Non | Curseur de pagination du fournisseur provenant d’une page précédente |
Renvoie entries (chaque kind est folder ou file) et un cursor facultatif pour la page suivante.
Déconnecter le stockage#
DELETE /api/integrations/buckets/{id}SDK Python : client.storage_integrations.delete(id)
Supprime les identifiants enregistrés sans supprimer les données du fournisseur. Les jeux de données connectés restent visibles, mais leurs fichiers sont indisponibles jusqu’à ce que le même compte de stockage soit reconnecté. Cette opération nécessite un accès administrateur à l’espace de travail.
API d’importation de jeux de données#
Importe des jeux de données depuis des services tiers. Consulte l’intégration Roboflow.
Prévisualiser une importation Roboflow#
POST /api/integrations/roboflow/previewSDK Python : client.datasets.preview_roboflow(api_key=...)
Convertit une clé API Roboflow en plan d’importation : détails de l’espace de travail, newDatasets à importer, nombre de projets déjà importés (skippedCount), sans version, non pris en charge et non résolus, bytesTotal et capacité restante storage. La clé API Roboflow est lue dans le corps de la requête et n’est pas conservée.
{
"apiKey": "ROBOFLOW_API_KEY"
}Importer depuis Roboflow#
POST /api/integrations/roboflow/importSDK Python : client.datasets.import_roboflow(api_key=..., items=...)
Met en file d’attente des tâches d’ingestion pour un maximum de 500 versions de projets Roboflow sélectionnées, à partir des éléments renvoyés par la prévisualisation.
{
"apiKey": "ROBOFLOW_API_KEY",
"items": [
{
"workspace": "my-workspace",
"projectId": "warehouse-safety",
"projectName": "Warehouse Safety",
"projectType": "object-detection",
"latestVersion": 4
}
]
}Réponse (201) : tableaux imported, failed et skipped. Les importations nécessitent une capacité de stockage disponible, et chaque jeu de données doit respecter la limite de taille par importation de ton forfait.
API du compte#
Consulte ton compte Platform, tes clés, ton stockage et tes profils publics. Consulte la documentation sur les paramètres.
Résumé du compte#
GET /api/account/summarySDK Python : client.account.summary()
Renvoie le forfait, le solde de crédits et le nombre de ressources pour l’espace de travail qui a émis la clé.
{
"username": "acme-vision",
"name": "Acme Vision",
"accountType": "team",
"plan": "pro",
"creditsCents": 2500,
"counts": { "projects": 4, "datasets": 7, "models": 21 },
"teams": []
}Pour un compte personnel, teams répertorie les espaces de travail d’équipe auxquels tu appartiens, chacun avec ton role et un deniedReason lorsque l’espace de travail est actuellement inaccessible, par exemple après l’expiration de son forfait. Les espaces de travail d’équipe renvoient une liste vide.
Lister les clés API#
GET /api/api-keysSDK Python : client.account.api_keys()
Renvoie keys avec keyId, name, keyPrefix et createdAt pour l’espace de travail associé à la clé. Les requêtes authentifiées par clé API ne reçoivent que les métadonnées ; les valeurs complètes des clés sont visibles par le propriétaire de l’espace de travail dans Paramètres > Clés API, dans l’interface Platform, où les clés sont également créées et révoquées.
Vérifier l’utilisation du stockage#
GET /api/storageSDK Python : client.account.storage()
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
details | booléen | Inclure les dix plus gros consommateurs de stockage (par défaut : false) |
Réponse :
{
"tier": "pro",
"usage": {
"storage": { "current": 1073741824, "limit": 536870912000, "percent": 0 },
"datasets": { "current": 2, "limit": -1, "percent": 0 },
"models": { "current": 4, "limit": 500, "percent": 1 }
},
"breakdown": {
"byCategory": {
"datasets": { "bytes": 536870912, "count": 2 },
"models": { "bytes": 268435456, "count": 4 },
"exports": { "bytes": 268435456, "count": 3 }
},
"topItems": [
{
"_id": "65f1c0a2b3d4e5f601234567",
"name": "Warehouse",
"slug": "warehouse",
"sizeBytes": 536870912,
"type": "dataset"
}
]
},
"region": "us",
"username": "acme-vision",
"updatedAt": "2026-01-15T10:00:00Z"
}usage indique le nombre de projects, datasets, models, images, annotations et deployments, ainsi que le nombre d’octets de storage. Un limit égal à -1 signifie que la limite est illimitée, et percent est un pourcentage entier de la limite.
Obtenir le profil public d’un utilisateur#
GET /api/usersSDK Python : client.account.profile(username=...)
Paramètres de requête :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
username | chaîne | Oui | Nom d’utilisateur à rechercher |
Renvoie le profil public user avec followerCount et, pour les appelants authentifiés, isFollowed.
Suivre ou ne plus suivre un utilisateur#
PATCH /api/usersSDK Python : client.account.follow(username=..., followed=...)
{
"username": "target-user",
"followed": true
}Réponse : followed et la valeur mise à jour de followerCount.
API de facturation#
Consulte l’utilisation de ton forfait et ton registre de crédits. Consulte la documentation sur la facturation.
Les montants de facturation sont des nombres entiers exprimés en cents américains, où 100 = $1.00.
Consulter le forfait et l’utilisation#
GET /api/billing/usage-summarySDK Python : client.billing.usage_summary()
Renvoie plan (ID, statut, cycle de facturation, fin de période), metrics (limite et utilisation du stockage), trainingCredit, features, creditsCents et le nombre de sièges.
Consulter les transactions#
GET /api/billing/transactionsSDK Python : client.billing.transactions()
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
from | chaîne | Horodatage de la transaction la plus ancienne (ISO 8601) |
to | chaîne | Horodatage de la transaction la plus récente (ISO 8601) |
Chaque transaction comprend id, type (par exemple purchase, training, monthly_grant ou refund), amountCents, balanceAfter, createdAt, un receiptUrl facultatif et le contexte du modèle pour les frais d’entraînement. Les détails de facturation internes ne sont jamais renvoyés.
API d’exploration#
Recherche des projets publics et des jeux de données partagés par la communauté, ou des images en fonction de leur contenu. Consulte la documentation d’Explorer.
Rechercher du contenu public#
GET /api/explore/searchSDK Python : client.explore.search()
Paramètres de requête :
| Paramètre | Type | Description |
|---|---|---|
q | chaîne | Terme de recherche (200 caractères maximum) ; pour les jeux de données, les correspondances textuelles s’affichent d’abord, puis les jeux de données dont les images correspondent |
type | chaîne | all (par défaut), projects, datasets ou images (ignore sort) |
sort | chaîne | newest (par défaut), oldest, stars, name-asc, name-desc, count-desc, count-asc |
offset | int | Nombre de résultats à ignorer (par défaut : 0) |
limit | int | Nombre maximal de résultats par type de ressource (par défaut : 20, max. : 100) |
task | chaîne | Filtres de tâche séparés par des virgules : detect, segment, semantic, depth, classify, pose, obb |
author | chaîne | Filtre par nom d’utilisateur du propriétaire |
starred | booléen | Renvoyer uniquement le contenu mis en favori par l’appelant authentifié ; une clé API est requise |
Réponse : projects, datasets et hasMore. type=images renvoie les correspondances dans images, par ordre de pertinence décroissante, chacune avec son dataset source et un score de similarité compris entre 0 et 1 ; cette option nécessite q et recherche dans les jeux de données publics, ainsi que dans tes propres jeux de données et ceux de ton équipe si tu fournis une clé API.
curl "https://platform.ultralytics.com/api/explore/search?type=datasets&task=detect&sort=stars&limit=20"SDK Python#
ultralytics-platform est un client Python typé généré à partir du contrat OpenAPI, avec une méthode par point de terminaison (client.datasets.list, client.models.predict, client.exports.create, ...). Chaque méthode accepte les paramètres de chemin sous forme positionnelle, les autres entrées sous forme d’arguments nommés, ainsi que timeout et extra_headers facultatifs pour chaque requête.
pip install "ultralytics-platform>=0.1.45" # Python 3.11+from ultralytics_platform import Platform
with Platform() as client: # lit ULTRALYTICS_API_KEY ou la clé enregistrée par yolo login
dataset = client.datasets.retrieve("acme-vision", "warehouse")
images = client.datasets.images("acme-vision", "warehouse", limit=10)
export = client.exports.create("acme-vision", "inspection", "v3", format="onnx")AsyncPlatform expose la même arborescence de ressources pour le code async/await, les réponses infructueuses déclenchent APIError avec status_code, body et json analysé, et les échecs de connexion déclenchent APIConnectionError. Consulte le référentiel du SDK pour lire le README complet.
Intégration Python#
Pour les workflows d’entraînement et d’inférence, utilise le package Python Ultralytics, qui gère automatiquement l’authentification, les téléversements et la diffusion des métriques en temps réel. Avec Python 3.11 ou version ultérieure, pip install ultralytics installe aussi le SDK ultralytics-platform. Lorsque model.train(project=...) cible Platform, les callbacks d’entraînement transmettent les événements via client.training.metrics() du SDK et demandent les URL de téléversement des points de contrôle via client.models.upload_checkpoint(), les opérations POST /api/webhooks/training/metrics et POST /api/webhooks/models/upload du document OpenAPI ; tu n’as donc rien à appeler toi-même.
Installation et configuration#
L’intégration à Platform nécessite Python>=3.11 et ultralytics>=8.4.120 :
pip install "ultralytics>=8.4.120"Vérifie l’installation :
yolo checkAuthentification#
yolo login YOUR_API_KEYUtiliser les jeux de données de la plateforme#
Référence les jeux de données avec les URI ul:// :
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# Entraîne le modèle sur ton jeu de données Platform
model.train(
data="ul://your-username/datasets/your-dataset",
epochs=100,
imgsz=640,
)Format de l’URI :
| Modèle | Description |
|---|---|
ul://username/datasets/slug | Jeu de données |
ul://username/project/model-name | Modèle spécifique |
ul://ultralytics/yolo26/yolo26n | Modèle officiel |
Envoyer des données vers Platform#
Envoie les résultats vers un projet Platform :
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# Les résultats sont automatiquement synchronisés avec Platform
model.train(
data="coco8.yaml",
epochs=100,
project="your-username/my-project",
name="experiment-1",
)Éléments synchronisés :
- Métriques d’entraînement (en temps réel)
- Poids finaux du modèle
- Graphiques de validation
- La sortie de la console
- Métriques système
- Arguments d’entraînement et environnement hôte (nom d’hôte, système d’exploitation, Python, matériel, commit Git, ligne de commande)
Exemples d’API#
Charger un modèle depuis Platform :
# Ton propre modèle
model = YOLO("ul://username/project/model-name")
# Modèle officiel
model = YOLO("ul://ultralytics/yolo26/yolo26n")Exécuter l’inférence :
results = model("image.jpg")
# Accéder aux résultats
for r in results:
boxes = r.boxes # Boîtes de détection
masks = r.masks # Masques de segmentation
keypoints = r.keypoints # Points clés de pose
probs = r.probs # Probabilités de classificationExporter le modèle :
# Exporter au format ONNX
model.export(format="onnx", imgsz=640, quantize=16)
# Exporter vers TensorRT
model.export(format="engine", imgsz=640, quantize=16)
# Exporter vers CoreML
model.export(format="coreml", imgsz=640) # utiliser imgsz=224 pour la classificationValidation :
metrics = model.val(data="ul://username/datasets/my-dataset")
print(f"mAP50: {metrics.box.map50}")
print(f"mAP50-95: {metrics.box.map}")FAQ#
Utilise les mêmes segments de propriétaire et de nom que ceux qui apparaissent dans l’URL Platform. Un modèle à
https://platform.ultralytics.com/acme-vision/inspection/v3correspond àGET /api/models/acme-vision/inspection/v3. Les ID de base de données sont toujours renvoyés dans les réponses (sous la formeid), et quelques routes les prennent directement — les routes d’image prennent unimageId, les téléversements prennent unassetIdetPOST /api/training/startprend unmodelId.Cela dépend de la collection. La plupart des points de terminaison de liste acceptent
limit:curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://platform.ultralytics.com/api/datasets/acme-vision?limit=50"Les images de jeux de données, le clustering et la recherche Explore utilisent
offsetaveclimitet renvoienthasMore:curl "https://platform.ultralytics.com/api/explore/search?type=datasets&offset=20&limit=20&sort=stars"Pour parcourir de très grands ensembles d’images, le plus simple est d’utiliser le curseur renvoyé sous la forme
nextCursor:curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://platform.ultralytics.com/api/datasets/acme-vision/warehouse/images?limit=1000&includeTotal=false&cursor=LAST_IMAGE_ID"La corbeille utilise
page, et les journaux de déploiement utilisent la valeur opaquepageTokenrenvoyée sous la formenextPageToken.Oui. Chaque opération de cette page est une requête HTTPS standard, et le contrat complet est publié au format OpenAPI 3.2 à l’adresse platform.ultralytics.com/openapi.json, que tu peux fournir à un générateur de client dans n’importe quel langage. Le package
ultralytics-platformest précisément cela : un client typé généré à partir du contrat, tandis que le packageultralyticsajoute la diffusion des métriques en temps réel et le téléversement automatique des modèles pendant l’entraînement et l’inférence. Les opérations de compte réservées aux sessions du navigateur, comme le paiement de la facturation et la gestion d’équipe, restent dans l’interface de Platform.Utilise l’en-tête
Retry-Afterde la réponse429pour attendre le délai approprié :import time import requests def api_request_with_retry(url, headers, max_retries=3): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code != 429: return response wait = int(response.headers.get("Retry-After", 2**attempt)) time.sleep(wait) raise RuntimeError("Rate limit exceeded")404signifie que la ressource n’existe pas ou qu’elle n’est pas du tout visible pour ta clé.403signifie que la ressource a été trouvée, mais que l’action nécessite des droits supérieurs à ceux dont dispose ta clé — un accès éditeur pour modifier un jeu de données, un accès propriétaire pour supprimer un déploiement, un accès administrateur pour déconnecter le stockage, ou un forfait ou quota supérieur pour les exportations et les déploiements.La lecture des jeux de données, projets et modèles publics, y compris leurs images, les URL d’image signées, les statistiques de classes, le statut des embeddings, la disposition du clustering, les modèles entraînés sur un jeu de données et la liste des exportations ; la vérification de la progression de l’entraînement d’un modèle public ; le téléchargement des fichiers d’un modèle public ; l’exécution de l’inférence sur un modèle public ; la consultation du profil d’un utilisateur public ; la liste des déploiements filtrés par un modèle public ; et la recherche Explore.
GET /api/training/gpu-availabilityest entièrement public, sauf si tu demandes une capacité gérée. Tout le reste nécessite une clé, et en fournir une sur un point de terminaison public révèle également tes ressources privées.