curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Idempotency-Key: 6baf0940-25d6-4ec2-9131-925250840fa7' \
--data '{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"image_urls": ["https://upload.apimart.ai/f/image/..."],
"cache_only": true,
"include_mask_rle": false
}'
{
"code": 200,
"data": [{ "status": "submitted", "task_id": "task_..." }]
}
Grok Imagine 2.0 Ext
Calques et édition de zones Grok Imagine 2.0 Ext
Utilisez segment pour récupérer les calques d’objets et les masques précis, puis modifiez des polygones, cadres ou objets détectés avec region_edit.
POST
/
v1
/
images
/
generations
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Idempotency-Key: 6baf0940-25d6-4ec2-9131-925250840fa7' \
--data '{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"image_urls": ["https://upload.apimart.ai/f/image/..."],
"cache_only": true,
"include_mask_rle": false
}'
{
"code": 200,
"data": [{ "status": "submitted", "task_id": "task_..." }]
}
segment et region_edit utilisent le point d’entrée d’images asynchrone existant. Enregistrez le task_id, puis interrogez Obtenir le statut de la tâche ; la requête de création ne renvoie pas directement les calques ou images finaux.N’exposez jamais une clé API dans le bundle du navigateur, LocalStorage, une URL ou les journaux frontend. Appelez APIMart via votre backend ou BFF.
curl --request POST \
--url https://api.apimart.ai/v1/images/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Idempotency-Key: 6baf0940-25d6-4ec2-9131-925250840fa7' \
--data '{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"image_urls": ["https://upload.apimart.ai/f/image/..."],
"cache_only": true,
"include_mask_rle": false
}'
{
"code": 200,
"data": [{ "status": "submitted", "task_id": "task_..." }]
}
Vue d’ensemble des opérations
| Objectif | Entrée principale | Résultat final | Facturation |
|---|---|---|---|
segment: Détecter les objets et récupérer calques, cadres et masques précis | source_task_id ou image_urls contenant une image téléversée | image_id, image_url, objects | Gratuit |
region_edit: Modifier un polygone, rectangle ou objet détecté | image_id, prompt, sélection | Nouvelle URL et image_id | Facturé par tâche terminée |
task_id terminée ─────────────┐
├→ segment → image_id + mask_rle
URL publique d'image téléversée┘ → selection_regions → region_edit → nouvelle task_id + image_id
Choisissez exactement une source pour
segment : source_task_id ou image_urls. Ces champs et image_id ne sont pas interchangeables ; region_edit utilise toujours l’ID d’asset renvoyé par segment. Pour segmenter une image modifiée, utilisez l’ID de la tâche region_edit terminée comme nouveau source_task_id.En-têtes de requête
UtilisezAuthorization: Bearer <APIMART_API_KEY>, Content-Type: application/json et Accept: application/json.
Idempotency-Key est facultatif et fortement recommandé pour les requêtes region_edit payantes. Il accepte 1 à 191 caractères ASCII visibles ; un UUID est recommandé. Utilisez une nouvelle clé par opération logique. Une nouvelle tentative réseau de la même requête doit réutiliser la clé et le corps d’origine. Si le résultat est indéterminé, ne relancez pas automatiquement avec une nouvelle clé.
Flux de tâche asynchrone
Une création réussie renvoie HTTP200 et data[0].task_id. Interrogez GET /v1/tasks/{task_id}?language=fr toutes les 2 secondes, puis jusqu’à 5 secondes maximum, avec une limite globale de 10 minutes. Arrêtez l’ancien polling lorsque l’image source change.
Une consultation peut renvoyer HTTP
200 alors que data.status vaut failed. Déterminez toujours le résultat via data.status et affichez data.error s’il existe.segment
Paramètres de requête
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
model | string | ✅ | Fixé à grok-imagine-2.0-ext |
operation | string | ✅ | Fixé à segment |
nsfw_check | boolean | — | Valeur par défaut : false.true : vérifier l’image source avec omni-moderation-latest.false ou omis : ne pas envoyer de requête de modération. |
source_task_id | string | Conditionnel | Tâche Grok terminée à image unique de l’utilisateur actuel ; incompatible avec image_urls |
image_urls | string[] | Conditionnel | Exactement une URL HTTP(S) absolue et publiquement accessible ; incompatible avec source_task_id. Téléversez les images locales via POST /v1/uploads/images, puis utilisez l’url renvoyée |
include_mask_rle | boolean | — | Valeur par défaut : true ; false omet les masques RLE mais renvoie toujours l’ID d’asset, les index et les cadres |
cache_only | boolean | — | Valeur par défaut : false ; doit être true avec image_urls ; vérifie uniquement le cache de segmentation |
cached_only | boolean | — | Valeur par défaut : false ; indication de cache amont réservée aux sources de tâche |
refresh | boolean | — | Valeur par défaut : false ; contournement du cache réservé aux sources de tâche |
segment ne nécessite pas de prompt. N’envoyez pas image_id, image_index, billing_model_name, n, size ou response_format. Envoyez exactement l’un de source_task_id et image_urls. Le mode URL exige cache_only=true et ne prend pas en charge cached_only ni refresh.
Exemples de requête
- Utiliser l'ID de tâche
- Utiliser une image téléversée
- Tester le cache de tâche
{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"source_task_id": "<COMPLETED_SINGLE_IMAGE_TASK_ID>",
"include_mask_rle": true,
"cached_only": false
}
{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"image_urls": ["https://upload.apimart.ai/f/image/..."],
"cache_only": true,
"include_mask_rle": false
}
{
"model": "grok-imagine-2.0-ext",
"operation": "segment",
"source_task_id": "<COMPLETED_SINGLE_IMAGE_TASK_ID>",
"include_mask_rle": true,
"cache_only": true
}
cache_status (hit ou miss) ou from_cache ; ne déduisez pas un hit de cached.
Téléverser une image locale
Téléversez d’abord le fichier local et récupérez l’URL publique dans la réponse :curl --request POST \
--url https://api.apimart.ai/v1/uploads/images \
--header 'Authorization: Bearer <token>' \
--form 'file=@/path/to/source.png'
url renvoyée comme seul élément de image_urls. Le polling, la réponse terminée et region_edit fonctionnent ensuite comme avec un ID de tâche : lisez result.image_id et objects, puis envoyez la modification de sélection. Les URL téléversées sont temporaires et conservées 72 heures par défaut.
image_urls accepte exactement une URL HTTP(S) absolue et publiquement accessible. Le mode URL prend uniquement en charge cache_only=true ; n’envoyez pas également source_task_id, cached_only ou refresh.Réponse terminée
Poursegment, data.result contient directement le résultat de segmentation ; il n’est pas enveloppé dans images.
{
"code": 200,
"data": {
"id": "task_...",
"status": "completed",
"progress": 100,
"cost": 0,
"credits_cost": 0,
"result": {
"source_task_id": "task_...",
"image_id": "6b78a7c3-5f9e-4a3d-a928-9e9b42113a3f",
"image_url": "https://.../source.jpg",
"from_cache": true,
"cache_status": "hit",
"objects": [{
"index": 0,
"name": "red sports car",
"box_xyxy": [38.1, 689.8, 945.8, 1065.4],
"score": 0.9765625,
"mask_size": [1792, 1008],
"mask_url": "",
"mask_rle": { "size": [1792, 1008], "counts": "..." }
}]
}
}
}
| Champ | Description |
|---|---|
result.image_id | ID d’asset utilisé par region_edit |
result.image_url | URL HTTP(S) alignée avec image_id |
objects[].index | Indice serveur d’origine ; à conserver pour object_indices |
objects[].box_xyxy | Cadre de masque en pixels [x1,y1,x2,y2] |
objects[].score | Confiance de détection ; peut être null |
objects[].mask_size | Toujours [height,width] ; ne jamais figer les dimensions |
objects[].mask_rle | COCO compressed RLE pour les contours précis |
objects[].mask_url | URL d’image de masque facultative ; peut être vide |
mask_rle ou mask_url valide, un objet ne peut être modifié que par approximation rectangulaire.
Décoder mask_rle
mask_rle.counts est une chaîne de comptages compressés COCO, ni Base64 ni zlib. Elle se déploie par colonnes ; le premier run est l’arrière-plan, puis avant-plan et arrière-plan alternent.
Le TypeScript suivant la convertit en masque binaire par lignes adapté au navigateur :
export interface CocoRLE {
size: [height: number, width: number];
counts: string;
}
export interface BinaryMask {
width: number;
height: number;
data: Uint8Array; // data[y * width + x]
}
function decodeCompressedCounts(counts: string): number[] {
const runs: number[] = [];
let cursor = 0;
while (cursor < counts.length) {
let value = 0;
let shift = 0;
let more = true;
while (more) {
if (cursor >= counts.length) throw new Error("Truncated COCO RLE counts");
const current = counts.charCodeAt(cursor++) - 48;
value |= (current & 0x1f) << shift;
more = (current & 0x20) !== 0;
shift += 5;
if (!more && (current & 0x10) !== 0) value |= -1 << shift;
}
if (runs.length > 2) value += runs[runs.length - 2] ?? 0;
if (value < 0) throw new Error(\`Invalid COCO RLE run: \${value}\`);
runs.push(value);
}
return runs;
}
export function decodeCocoRLE(rle: CocoRLE): BinaryMask {
const [height, width] = rle.size;
if (!Number.isInteger(height) || !Number.isInteger(width) || height <= 0 || width <= 0) {
throw new Error(\`Invalid mask size: \${JSON.stringify(rle.size)}\`);
}
const pixelCount = width * height;
if (!Number.isSafeInteger(pixelCount) || pixelCount > 32_000_000) {
throw new Error(\`Mask exceeds the frontend safety limit: \${pixelCount}\`);
}
if (!rle.counts) throw new Error("Missing COCO RLE counts");
const data = new Uint8Array(pixelCount);
const runs = decodeCompressedCounts(rle.counts);
let position = 0;
let foreground = false;
for (const run of runs) {
if (position + run > data.length) throw new Error("COCO RLE exceeds mask_size");
if (foreground) {
for (let offset = 0; offset < run; offset++) {
const index = position + offset;
const y = index % height;
const x = (index - y) / height;
data[y * width + x] = 1;
}
}
position += run;
foreground = !foreground;
}
if (position !== data.length) throw new Error("COCO RLE does not cover the mask");
return { width, height, data };
}
mask_rle.counts dans les logs, analyses, URL ou rapports d’erreur.
Convertir les masques en sélections précises
interface SelectionBoundary { points: number[] }
interface SelectionRegion { outer: SelectionBoundary; holes?: SelectionBoundary[] }
0–1. Chaque anneau doit avoir au moins 3 points distincts, une aire non nulle et aucune auto-intersection. Conservez au plus les 16 plus grandes régions par calque et 400 points par anneau.
mask_size est [height,width] et utilise les coordonnées du masque source, pas les dimensions CSS. Avec object-fit: contain, retirez les marges, mettez à l’échelle selon la zone réellement dessinée et limitez le résultat à 0–1.mask_url exige CORS. Définissez crossOrigin = "anonymous" avant src ou récupérez un Blob. Le décodage direct de mask_rle évite cette dépendance.
Modifier une zone : region_edit
Paramètres de requête
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
model | string | ✅ | Fixé à grok-imagine-2.0-ext |
operation | string | ✅ | region_edit |
nsfw_check | boolean | — | Valeur par défaut : false.true : vérifier le prompt d’édition et l’image d’entrée avec omni-moderation-latest.false ou omis : ne pas envoyer de requête de modération. |
image_id | string | ✅ | ID de l’asset source ; utilisez d’abord le image_id de segment, puis le dernier résultat d’édition |
prompt | string | ✅ | Instruction non vide décrivant la modification |
selection_regions | array | * | Polygones normalisés sur 0–1 avec outer et holes facultatifs ; recommandé |
boxes | number[][] | * | Rectangles [x1,y1,x2,y2] ; les cadres en pixels exigent mask_size |
object_indices | integer[] | * | Valeurs objects[].index d’origine ; approximation rectangulaire uniquement |
mask_size | integer[] | * | Obligatoire pour les cadres en pixels ; [height,width] avec entiers positifs |
selection_regions, boxes ou object_indices doit être non vide. L’API accepte les combinaisons, mais le frontend devrait utiliser une seule méthode par requête.
N’envoyez pas
billing_model_name, size, aspect_ratio, source_aspect_ratio, source_size ou image_urls. Omettez n ou utilisez 1, omettez claim_asset ou utilisez false, omettez response_format ou utilisez url. Base64 et stream=true ne sont pas pris en charge.Méthodes de sélection
| Méthode | Source de sélection | Précision | Usage recommandé |
|---|---|---|---|
selection_regions | Polygones du frontend | Précise, trous compris | Édition de calques ou pinceau en production |
boxes | Rectangles du frontend | Approximation rectangulaire | Outil cadre ou MVP |
object_indices | Indices segment d’origine | Approximation rectangulaire | Test d’intégration rapide |
- Polygone précis
- Cadre normalisé
- Cadre en pixels
- Indice d'objet
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "<SOURCE_IMAGE_ID>",
"prompt": "Change the selected car to bright red and preserve the rest",
"selection_regions": [{
"outer": { "points": [0.12, 0.20, 0.48, 0.20, 0.48, 0.61, 0.12, 0.61] },
"holes": [{ "points": [0.30, 0.35, 0.38, 0.35, 0.38, 0.45, 0.30, 0.45] }]
}]
}
points peut être une liste plate ou des paires imbriquées. Chaque valeur doit être finie et dans 0–1 ; chaque anneau exige au moins 3 paires.{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "<SOURCE_IMAGE_ID>",
"prompt": "Change the car inside the box to bright red",
"boxes": [[0.04, 0.385, 0.938, 0.594]]
}
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "<SOURCE_IMAGE_ID>",
"prompt": "Change the car inside the box to bright red",
"boxes": [[40, 689.6, 945.9, 1064.4]],
"mask_size": [1792, 1008]
}
{
"model": "grok-imagine-2.0-ext",
"operation": "region_edit",
"image_id": "<SOURCE_IMAGE_ID>",
"prompt": "Change the selected car to bright red",
"object_indices": [0]
}
image_id. Ne les remplacez pas par ceux d’une liste frontend filtrée, triée ou groupée.Réponse terminée
{
"code": 200,
"data": {
"id": "task_...",
"status": "completed",
"progress": 100,
"cost": 0.016,
"credits_cost": 0.16,
"result": {
"images": [{
"url": ["https://.../result.jpg"],
"image_ids": ["<NEW_IMAGE_ID>"],
"items": [{
"url": "https://.../result.jpg",
"image_id": "<NEW_IMAGE_ID>",
"source_image_id": "<SOURCE_IMAGE_ID>",
"role": "region_edit"
}],
"expires_at": 1787040000
}]
}
}
}
result.images[0].items[0]. Pour une ancienne réponse, n’associez url[0] et image_ids[0] que si les tableaux ont la même longueur. Continuez uniquement après obtention d’une URL HTTP(S) et d’un nouveau image_id.
Utilisez expires_at comme référence d’expiration ; ne figez pas un nombre d’heures. Téléchargez ou conservez les assets nécessaires à long terme.
Édition continue
À la fin d’une édition, mettez à jour ensemble l’URL affichée, l’ID d’asset actuel et l’ID de tâche source, puis effacez les anciens calques et états de polling.- Segmenter à nouveau : utiliser l’ID de cette tâche
region_editcommesource_task_id - Modifier à nouveau : utiliser le nouveau
image_idrenvoyé - Ne transmettez jamais
image_idàsegmentet ne continuez jamais avec l’ancien ID d’image.
Gestion des erreurs
| HTTP / statut | Cause fréquente | Traitement |
|---|---|---|
| 400 source ou opération invalide | Mauvaise opération ; deux sources ou aucune ; tâche inutilisable ; URL invalide ; ou image_id/image_index envoyés à segment | Choisir exactement une source valide. Pour un téléversement, envoyer une URL HTTP(S) publique avec cache_only=true |
| 400 sélection invalide | Prompt vide, sélection absente, polygone, cadre ou indice invalide | Valider le prompt et la sélection avant l’envoi |
| 400 option non prise en charge | claim_asset, n, format, taille ou streaming invalide | Supprimer les champs non pris en charge et utiliser une sortie URL |
| 401 / 403 | Clé invalide ou autorisation du modèle absente | Vérifier la clé serveur et l’accès du compte |
| 402 | Solde insuffisant | Demander un rechargement avant de réessayer |
| 409 | Requête idempotente en cours, modifiée ou indéterminée | Suivre la réponse ; ne pas changer automatiquement de clé |
| 429 / 5xx | Limitation ou panne temporaire | Respecter Retry-After et appliquer un backoff limité |
| failed / task_failed | Échec de l’exécution asynchrone | Arrêter le polling et afficher data.error.message |
Facturation
segmentest gratuit et se termine aveccost=0etcredits_cost=0, mais exige une authentification et une source valide.region_editest payant. Utilisezcostetcredits_costde la tâche terminée ; ne figez pas les prix dans le frontend.- N’envoyez jamais le champ interne
billing_model_name.
Liste de contrôle frontend
- Conserver la clé API uniquement dans le backend ou BFF.
- Envoyer une seule source à
segment:source_task_idouimage_urlsavec une URL publique. Ne pas envoyerimage_idniimage_index. - Avec
image_urls, définircache_only=trueet omettrecached_onlyetrefresh. - Utiliser le
image_idde segment pourregion_editavec au moins une méthode de sélection. - Utiliser
selection_regionspour l’édition précise ;object_indicesn’est qu’une approximation rectangulaire. - Toujours lire
mask_sizecomme[height,width]et gérer mise à l’échelle et marges. - Réutiliser la clé idempotente d’origine pour le même retry et valider l’URL ainsi que le nouveau
image_id.