Ultralytics YOLO27 :
Get Started

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.

Documentation interactive de l’API de la plateforme Ultralytics

Démarrage rapide
# List the datasets owned by a workspace
curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://platform.ultralytics.com/api/datasets/YOUR_USERNAME

Chaque 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.

Référence interactive de l’API

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
RessourceDescriptionOpérations clés
Jeux de donnéesCollections d’images annotéesCRUD, ingestion, versions, classes, partitions, clonage, copie
ImagesImages et annotations individuellesLire, annoter, déplacer vers une partition, supprimer, annoter automatiquement, flouter les visages
ProjetsEspaces de travail des modèlesCRUD, clonage
ModèlesPoints de contrôle entraînésCRUD, prédiction, téléchargement, clonage, état de l’entraînement
EntraînementTâches d’entraînement sur GPU dans le cloudDisponibilité du GPU, démarrage, progression, annulation
ExportationsTâches de conversion de formatCréer, lister, consulter l’état, annuler
DéploiementsPoints de terminaison d’inférence dédiésCréer, mettre à jour, démarrer/arrêter, prédire, consulter les métriques et les journaux
AgentsFlux de travail visuels enregistrésLister, enregistrer, supprimer
CorbeilleRessources supprimées de façon réversibleLister, restaurer, supprimer définitivement
StockageIntégrations de stockage cloudConnecter, découvrir, parcourir, déconnecter
CompteOffre, crédits, stockage, profilRécapitulatif du compte, clés API, utilisation du stockage, recherche d’utilisateurs
FacturationUtilisation de l’offre et registre des opérationsRécapitulatif de l’utilisation, transactions
ExplorerRecherche de contenu publicRechercher 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#

  1. Va dans Settings > API Keys
  2. Clique sur Add Key, conserve Ultralytics comme fournisseur, saisis un nom, puis clique sur Create Key
  3. 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_KEY
Format de la clé API

Les 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/summary

URL de base#

Tous les points de terminaison de l’API utilisent :

https://platform.ultralytics.com/api

Chemins 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 :

RessourceCheminExemple
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 PATCH modifie simultanément son name d’affichage et son nom dans l’URL. La réponse renvoie le nom actuel dans l’URL pour que tu puisses continuer à l’utiliser.
Sélection de l’espace de travail

À 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égorieLimiteS’applique à
Par défaut100 requêtes/minToutes les routes non répertoriées ci-dessous
Entraînement10 requêtes/minPOST /api/training/start
Téléverser10 requêtes/minURL de téléversement signées, finalisation du téléversement et ingestion de jeux de données
Prédiction20 requêtes/minInférence sur les modèles et les déploiements via les routes de l’API de la plateforme
Exporter20 requêtes/minListe 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écharger30 requêtes/minTéléchargements de fichiers de modèles
Modification10 requêtes/minListe 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)
Hydratation20 requêtes/minPOST /api/datasets/{owner}/{dataset}/images (récupération d’un ensemble sélectionné d’images) et GET /api/images/{imageId}/similar
Regroupement10 requêtes/minGET /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é.

Gestion des limites de débit

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 HTTPSignification
200Réussite
201Date de création
202Acceptée, le traitement se poursuit de manière asynchrone
400Chemin, requête ou corps de requête invalide
401Authentification manquante ou invalide
402Crédits insuffisants (entraînement)
403Autorisations, formule ou quota insuffisants
404Ressource introuvable
409Conflit avec l'état actuel (nom en double, tâche en cours)
413Entrée de prédiction trop volumineuse
422Les classes du modèle ne correspondent pas au jeu de données, ou une clé de fournisseur est manquante ou refusée (annotation automatique)
429Limite de débit dépassée
500Erreur du serveur
502Échec de l'appel au fournisseur ou au service en amont
503Service dépendant temporairement indisponible

Pagination#

Le style de pagination dépend de la collection :

StylePoints de terminaisonParamètres
Limite uniquementListes de jeux de données, projets, modèles, exports et déploiementslimit
Décalage et limiteImages de jeux de données, regroupement d'images, recherche Exploreoffset, limit, plus hasMore dans la réponse
CurseurImages de jeux de données (grands jeux de données)cursor, includeTotal, plus nextCursor
Numéro de pageCorbeillepage, limit, plus totalPages
Jeton de page opaqueJournaux de déploiementpageToken, 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ètreTypeDescription
limitintNombre maximal de jeux de données à renvoyer (par défaut : 1000, maximum : 1000)
includeSamplesbooléenInclure des aperçus d'images d'exemple (par défaut : true)
includeImageUrlsbooléenInclure 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/datasets

SDK 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"
}
ChampTypeObligatoireDescription
datasetchaîneOuiNom du jeu de données utilisé dans les URL de la plateforme (minuscules, mots séparés par des tirets, 128 caractères maximum)
namechaîneOuiNom d'affichage (100 caractères maximum)
descriptionchaîneNonDescription (1000 caractères maximum)
taskchaîneNonType de tâche (par défaut : detect)
classNamestableauNonNoms des classes par ordre d’index (25 000 maximum) ; aucun doublon, casse ignorée pour les noms de plus de 2 caractères
formatchaîneNonFormat d'annotation : yolo (par défaut), coco, raw, ndjson
visibilitychaîneNonpublic ou private
blurFacesbooléenNonFlouter les visages dans les images importées dans le jeu de données (voir Flouter les visages)
tagstableauNonJusqu'à 50 étiquettes de 50 caractères chacune
licensechaîneNonIdentifiant de licence du jeu de données
metadataobjetNonMétadonnées JSON personnalisées
ownerchaîneNonIdentifiant 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.

Tâches prises en charge

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}/clone

SDK 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}/export

SDK 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ètreTypeDescription
ventierNumé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}/export

SDK 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}/export

SDK 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}/restore

SDK 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ètreTypeDescription
baseintVersion de départ de la comparaison
headintVersion d'arrivée de la comparaison
cursorchaînenextCursor de la page précédente
hashchaîneLe 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-stats

SDK 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/merge

SDK 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/delete

SDK 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).

Les ID de classe sont positionnels

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

SDK 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}/embeddings

SDK 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/clustering

SDK 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}/models

SDK 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}/images

SDK Python : client.datasets.images(owner, dataset)

Paramètres de requête :

ParamètreTypeDescription
limitintNombre maximal d’images à renvoyer (par défaut : 50, maximum : 5 000)
offsetintNombre d’images à ignorer (par défaut : 0)
cursorchaîneID de la dernière image de la page précédente, pour la pagination par curseur
includeTotalbooléenInclure le nombre total de résultats correspondants (par défaut : true)
splitchaîneFiltrer par partition : train, val, test
hasLabelbooléenFiltrer par état d’annotation
hasErrorbooléenFiltrer par état d’erreur de traitement
classIdschaîneID de classe séparés par des virgules ; renvoie les images qui en contiennent au moins un
searchchaîneCorrespondance de sous-chaîne dans le nom de fichier, le nom de classe et les métadonnées personnalisées (200 caractères maximum)
qchaîneClasse 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)
sortchaînenewest (par défaut), oldest, name-asc, name-desc, height-asc, height-desc, width-asc, width-desc, size-asc, size-desc, labels-asc, labels-desc
includeThumbnailsbooléenInclure les URL signées des miniatures (par défaut : true)
includeImageUrlsbooléenInclure les URL signées des images en pleine résolution (par défaut : false)
includeLabelsbooléenInclure 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}/images

SDK 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/adopt

SDK 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}/ingest

SDK 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 :

ChampTypeDescription
sessionIdchaîneSession 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é
sourceUrlchaîneURL HTTP ou HTTPS publique d’un fichier ZIP, TAR, TAR.GZ, TGZ ou NDJSON (4 096 caractères maximum)
referenceobjetUne source connectée : stockage cloud (provider: "cloud", integrationId, target, prefix) ou sur site (provider: "local", keyId, root, prefix)
targetSplitchaînetrain, val ou test ; remplace la structure de partitions de l’archive
conflictPolicychaîneskip, keep_both ou replace en cas de conflit de nom de fichier ou de contenu
classMappingobjetAssocie les noms de classe entrants à un index de classe, à un nom de classe existant ou nouveau, ou à null pour les ignorer
imageMetadataobjetMé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.

Mappage des classes

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:#fff
Té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 }
}
Format des coordonnées

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}/predict

SDK 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.

ChampTypeObligatoireDescription
modelIdchaîneOuiURI 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
confidencefloatNonSeuil 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
ioufloatNonSeuil 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
classMappingtableauNonPour 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}/similar

SDK 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/batch

SDK 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/bulk

SDK 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/bulk

SDK 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/urls

SDK 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ètreTypeDescription
limitintNombre 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/projects

SDK Python : client.projects.create(project=..., name=...)

ChampTypeObligatoireDescription
projectchaîneOuiNom du projet utilisé dans les URL de la plateforme
namechaîneOuiNom d'affichage (100 caractères maximum)
descriptionchaîneNonDescription (1000 caractères maximum)
visibilitychaîneNonpublic ou private
tagstableauNonJusqu’à 50 étiquettes
licensechaîneNonIdentifiant de licence du projet
metadataobjetNonMétadonnées JSON personnalisées
ownerchaîneNonIdentifiant 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/projects

Ré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}/clone

SDK 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ètreTypeDescription
limitintNombre 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ètreTypeDescription
analysisintDé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/models

SDK 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.

ChampTypeObligatoireDescription
projectchaîneOuiNom du projet de destination
ownerchaîneNonIdentifiant de l'espace de travail ; par défaut, ton espace de travail personnel
modelchaîneNonNom du modèle utilisé dans les URL de la plateforme ; généré s'il n'est pas fourni
namechaîneNonNom affiché (accepté uniquement avec model)
descriptionchaîneNonDescription (1000 caractères maximum)
taskchaîneNondetect, segment, semantic, depth, classify, pose ou obb
metadataobjetNonMétadonnées JSON personnalisées
trainArgsobjetNonArguments d'entraînement à enregistrer
metricsobjetNonMétriques telles que mAP50, mAP50-95, precision, recall
epochsnombreNonNombre d'époques pour un modèle déjà entraîné
versionchaîneNonLibellé de version (50 caractères maximum)

Réponse (201) : id, owner, project, model, region.

Téléversement de fichier de modèle

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}/files

SDK 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-images

SDK 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}/clone

SDK 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"
}
ChampTypeObligatoireDescription
projectchaîneOuiNom du projet de destination
ownerchaîneNonEspace de travail de destination ; par défaut, ton espace personnel
modelchaîneNonNom du modèle de destination
namechaîneNonNom affiché de destination
descriptionchaîneNonDescription du clone

Exécuter l’inférence#

POST /api/models/{owner}/{project}/{model}/predict

SDK 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ètreTypeValeur par défautPlageDescription
filefichier--Fichier image ou vidéo (obligatoire sauf si source est défini)
conffloat0.250.01 – 1.0Seuil de confiance minimal
ioufloat0.70.0 – 0.95Seuil IoU de la NMS
imgszint-32 – 1280Taille 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)
normalizeboolfalse-Renvoyer les coordonnées des boîtes englobantes entre 0 et 1
decimalsint50 – 10Précision décimale des valeurs de coordonnées
vid_strideint1≥ 1Prédire une image vidéo sur N ; les images fixes ne sont pas concernées
bitsint88, 12, 16Quantification de la carte de profondeur, modèles de profondeur uniquement
sourcechaî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/predict

Ré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}/training

SDK 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}/training

SDK 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:#fff

Obtenir la disponibilité des GPU#

GET /api/training/gpu-availability

SDK 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/start

SDK Python : client.training.start(model_id=..., train_args=...)

ChampTypeObligatoireDescription
modelIdchaîneOuiID du modèle à entraîner
trainArgsobjetOuiArguments d'entraînement YOLO ; model, data et epochs sont obligatoires
gpuTypechaîneNonGPU cloud à utiliser (par défaut : rtx-4090)
captureDatasetVersionbooléenNonEnregistrer 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/start

Ré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é.

Types de GPU

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}/exports

SDK Python : client.exports.list(owner, project, model)

Paramètres de requête :

ParamètreTypeDescription
statuschaîneFiltrer par queued, starting, running, completed, failed ou cancelled
limitintNombre maximal d'exports à renvoyer (par défaut : 20, maximum : 100)

Créer un export#

POST /api/models/{owner}/{project}/{model}/exports

SDK Python : client.exports.create(owner, project, model, format=...)

ChampTypeObligatoireDescription
formatchaîneOuiFormat d'export cible (voir le tableau ci-dessous)
gpuTypechaîneConditionnelObligatoire lorsque format est engine ; utilise une cible GPU ou Jetson prise en charge
argsobjetNonOptions 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/exports

Chaque 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.

FormatArgument formatModèleMétadonnéesArguments
PyTorch-yolo26n.pt✅-
TorchScripttorchscriptyolo26n.torchscript✅imgsz, quantize, dynamic, nms, batch, device
ONNXonnxyolo26n.onnx✅imgsz, quantize, dynamic, simplify, opset, nms, batch, data, fraction, device
OpenVINOopenvinoyolo26n_openvino_model/✅imgsz, quantize, dynamic, nms, batch, data, fraction, device
TensorRTengineyolo26n.engine✅imgsz, quantize, dynamic, simplify, opset, workspace, nms, batch, data, fraction, device
CoreMLcoremlyolo26n.mlpackage✅imgsz, dynamic, quantize, nms, batch, device
Apple Core AIcoreaiyolo26n.aimodel✅imgsz, batch, quantize
TF SavedModelsaved_modelyolo26n_saved_model/✅imgsz, quantize, opset, nms, batch, data, fraction, device
TF GraphDefpbyolo26n.pb❌imgsz, opset, batch, device
TF Edge TPUedgetpuyolo26n_edgetpu.tflite✅imgsz, quantize, opset, data, fraction, device
LiteRTlitertyolo26n.tflite✅imgsz, quantize, batch, data, fraction, device
PaddlePaddlepaddleyolo26n_paddle_model/✅imgsz, batch, device
MNNmnnyolo26n.mnn✅imgsz, batch, dynamic, quantize, simplify, opset, nms, device
NCNNncnnyolo26n_ncnn_model/✅imgsz, quantize, batch, device
IMX500imxyolo26n_imx_model/✅imgsz, quantize, data, fraction, nms, device
RKNNrknnyolo26n_rknn_model/✅imgsz, batch, name, quantize, simplify, opset, data, fraction, device
ExecuTorchexecutorchyolo26n_executorch_model/✅imgsz, batch, device
Axeleraaxelerayolo26n_axelera_model/✅imgsz, batch, quantize, data, fraction, device
DEEPXdeepxyolo26n_deepx_model/✅imgsz, quantize, simplify, opset, data, optimize, device
Qualcomm QNNqnnyolo26n_qnn.onnx✅imgsz, batch, name, quantize, simplify, opset, data, fraction, device
Hailohailoyolo26n_hailo_model/✅imgsz, name, quantize, data, fraction, simplify, conf, iou, device
Huawei Ascendascendyolo26n_ascend_model/✅imgsz, batch, name, quantize, opset, simplify, nms, device
AMD Xilinxxilinxyolo26n_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:#fff

Lister les déploiements#

GET /api/deployments/{owner}

SDK Python : client.deployments.list(owner)

Paramètres de requête :

ParamètreTypeDescription
statuschaînecreating, deploying, ready, stopping, stopped ou failed
modelchaîneFiltrer par {project}/{model}, par exemple inspection/v3
limitintNombre 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"
}
ChampTypeObligatoireDescription
projectchaîneOuiProjet contenant le modèle
modelchaîneOuiModèle à déployer
deploymentchaîneOuiNom du déploiement utilisé dans les URL de la plateforme
namechaîneOuiNom affiché
regionchaîneOuiL'une des 42 régions de déploiement prises en charge
cpunombreNonCœurs vCPU : 1 (par défaut), 2, 4, 6 ou 8
memoryGinombreNonMémoire en Gio : 2 (par défaut), 4, 8, 16, 24 ou 32

Réponse (201) : id, deployment, status (creating), message et region.

Dimensionnement des ressources

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.

Sélection de région

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}/health

SDK 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}/predict

SDK 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ètreTypeValeur par défautPlageDescription
filefichier--Fichier image ou vidéo (obligatoire sauf si source est défini)
conffloat0.250.01 – 1.0Seuil de confiance minimal
ioufloat0.70.0 – 0.95Seuil IoU de la NMS
imgszint-32 – 1280Taille 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)
normalizeboolfalse-Renvoyer les coordonnées des boîtes englobantes entre 0 et 1
decimalsint50 – 10Précision décimale des valeurs de coordonnées
vid_strideint1≥ 1Prédire une image vidéo sur N ; les images fixes ne sont pas concernées
bitsint88, 12, 16Quantification de la carte de profondeur, modèles de profondeur uniquement
sourcechaî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}/metrics

SDK Python : client.deployments.metrics(owner, deployment)

Paramètres de requête :

ParamètreTypeDescription
rangechaîne1h, 6h, 24h (par défaut), 7d ou 30d
sparklinebooléenRenvoie le résumé compact du tableau de bord au lieu des séries complètes (par défaut : false)
viewchaîneoverview 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}/logs

SDK Python : client.deployments.logs(owner, deployment)

Paramètres de requête :

ParamètreTypeDescription
severitychaîneSéparés par des virgules : DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY
limitintNombre d’entrées à renvoyer (par défaut : 50, max. : 200)
pageTokenchaîneJeton 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/workflows

SDK Python : client.agents.list()

ParamètreTypeDescription
ownerchaîneNom d’utilisateur de l’espace de travail (par défaut : le tien)
idchaîneRenvoie un agent avec son graph
searchchaîneFiltrer 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/workflows

SDK 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/trash

SDK Python : client.lifecycle.trash()

Paramètres de requête :

ParamètreTypeDescription
typechaîneall (par défaut), project, dataset ou model
pageintNuméro de page (par défaut : 1)
limitintNombre d’éléments par page (par défaut : 50, max. : 200)
idchaîneAvec 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/trash

SDK 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/trash

SDK 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.

Irréversible

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-url

SDK Python : client.upload.signed_url(body=...)

Corps :

{
    "assetType": "datasets",
    "assetId": "65f1c0a2b3d4e5f601234567",
    "filename": "warehouse.zip",
    "contentType": "application/zip",
    "totalBytes": 52428800
}
ChampTypeObligatoireDescription
assetTypechaîneOuidatasets ou models
assetIdchaîneOuiID du jeu de données ou du modèle cible
filenamechaîneOuiNom de fichier d’origine (256 caractères max.)
contentTypechaîneOuiType MIME
totalBytesnombreOuiTaille du fichier en octets
Noms de fichiers des archives de jeux de données

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

SDK 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/buckets

SDK 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/discover

SDK 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/buckets

SDK 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}/objects

SDK Python : client.storage_integrations.objects(id, target=...)

Paramètres de requête :

ParamètreTypeObligatoireDescription
targetchaîneOuiNom du compartiment ou du conteneur
prefixchaîneNonPréfixe du dossier (1024 caractères max.)
cursorchaîneNonCurseur 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/preview

SDK 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/import

SDK 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/summary

SDK 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": []
}
Liste des équipes

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-keys

SDK 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/storage

SDK Python : client.account.storage()

Paramètres de requête :

ParamètreTypeDescription
detailsbooléenInclure 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/users

SDK Python : client.account.profile(username=...)

Paramètres de requête :

ParamètreTypeObligatoireDescription
usernamechaîneOuiNom 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/users

SDK 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.

Unités monétaires

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-summary

SDK 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/transactions

SDK Python : client.billing.transactions()

Paramètres de requête :

ParamètreTypeDescription
fromchaîneHorodatage de la transaction la plus ancienne (ISO 8601)
tochaîneHorodatage 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/search

SDK Python : client.explore.search()

Paramètres de requête :

ParamètreTypeDescription
qchaîneTerme 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
typechaîneall (par défaut), projects, datasets ou images (ignore sort)
sortchaînenewest (par défaut), oldest, stars, name-asc, name-desc, count-desc, count-asc
offsetintNombre de résultats à ignorer (par défaut : 0)
limitintNombre maximal de résultats par type de ressource (par défaut : 20, max. : 100)
taskchaîneFiltres de tâche séparés par des virgules : detect, segment, semantic, depth, classify, pose, obb
authorchaîneFiltre par nom d’utilisateur du propriétaire
starredbooléenRenvoyer 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 check

Authentification#

yolo login YOUR_API_KEY

Utiliser 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èleDescription
ul://username/datasets/slugJeu de données
ul://username/project/model-nameModèle spécifique
ul://ultralytics/yolo26/yolo26nModè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 classification

Exporter 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 classification

Validation :

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/v3 correspond à GET /api/models/acme-vision/inspection/v3. Les ID de base de données sont toujours renvoyés dans les réponses (sous la forme id), et quelques routes les prennent directement — les routes d’image prennent un imageId, les téléversements prennent un assetId et POST /api/training/start prend un modelId.

  • 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 offset avec limit et renvoient hasMore :

    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 opaque pageToken renvoyée sous la forme nextPageToken.

  • 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-platform est précisément cela : un client typé généré à partir du contrat, tandis que le package ultralytics ajoute 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-After de la réponse 429 pour 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")
  • 404 signifie que la ressource n’existe pas ou qu’elle n’est pas du tout visible pour ta clé. 403 signifie 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-availability est 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.

Commentaires