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
Capas y edición de regiones de Grok Imagine 2.0 Ext
Usa segment para obtener capas de objetos y máscaras precisas, y edita polígonos, cuadros u objetos detectados con 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 y region_edit usan el endpoint asíncrono de imágenes existente. Guarda el task_id devuelto y consulta Obtener estado de la tarea; la solicitud de creación no devuelve las capas ni imágenes finales.Nunca expongas una API Key en el paquete del navegador, LocalStorage, una URL o los registros del frontend. Llama a APIMart desde tu backend o 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_..." }]
}
Resumen de operaciones
| Finalidad | Entrada principal | Resultado final | Facturación |
|---|---|---|---|
segment: Detectar objetos y obtener capas, cuadros y máscaras precisas | source_task_id o image_urls con una imagen subida | image_id, image_url, objects | Gratis |
region_edit: Editar un polígono, rectángulo u objeto detectado | image_id, prompt, selección | URL nueva e image_id | Se cobra por tarea completada |
task_id completada ──────────┐
├→ segment → image_id + mask_rle
URL pública de imagen subida┘ → selection_regions → region_edit → nueva task_id + image_id
Elige exactamente un origen para
segment: source_task_id o image_urls. Estos campos y image_id no son intercambiables; region_edit sigue usando el ID de recurso devuelto por segment. Para segmentar una imagen editada, usa el ID de la tarea region_edit completada como nuevo source_task_id.Encabezados de solicitud
UsaAuthorization: Bearer <APIMART_API_KEY>, Content-Type: application/json y Accept: application/json.
Idempotency-Key es opcional y se recomienda especialmente para solicitudes region_edit de pago. Admite entre 1 y 191 caracteres ASCII visibles; se recomienda un UUID. Usa una clave nueva por operación lógica. Un reintento de red de la misma solicitud debe reutilizar la clave original y el mismo cuerpo. Si el resultado es indeterminado, no reintentes automáticamente con otra clave.
Flujo de tarea asíncrona
Una creación correcta devuelve HTTP200 y data[0].task_id. Consulta GET /v1/tasks/{task_id}?language=es cada 2 segundos, aumenta hasta un máximo de 5 segundos y limita el total a 10 minutos. Detén el sondeo anterior al cambiar la imagen de origen.
La consulta puede devolver HTTP
200 aunque data.status sea failed. Determina siempre el resultado mediante data.status y muestra data.error cuando exista.segment
Parámetros de solicitud
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
model | string | ✅ | Fijo: grok-imagine-2.0-ext |
operation | string | ✅ | Fijo: segment |
nsfw_check | boolean | — | Valor predeterminado: false.true: revisar la imagen de origen con omni-moderation-latest.false u omitido: no enviar una solicitud de moderación. |
source_task_id | string | Condicional | Tarea Grok completada, de una sola imagen y del usuario actual; incompatible con image_urls |
image_urls | string[] | Condicional | Exactamente una URL HTTP(S) absoluta y accesible públicamente; incompatible con source_task_id. Sube imágenes locales con POST /v1/uploads/images y usa la url devuelta |
include_mask_rle | boolean | — | Valor predeterminado: true; false omite las máscaras RLE, pero sigue devolviendo el ID del recurso, los índices y los cuadros |
cache_only | boolean | — | Valor predeterminado: false; debe ser true con image_urls; solo consulta la caché de segmentación |
cached_only | boolean | — | Valor predeterminado: false; sugerencia de caché solo para orígenes de tarea, sin garantía local |
refresh | boolean | — | Valor predeterminado: false; omite la caché solo para orígenes de tarea; no usar en el flujo normal |
segment no necesita prompt. No envíes image_id, image_index, billing_model_name, n, size ni response_format. Envía exactamente uno de source_task_id e image_urls. El modo de URL requiere cache_only=true y no admite cached_only ni refresh.
Ejemplos de solicitud
- Usar ID de tarea
- Usar imagen subida
- Consultar caché de tarea
{
"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 o miss) o from_cache; no deduzcas el acierto mediante cached.
Subir una imagen local
Sube primero el archivo local y lee la URL pública de la respuesta:curl --request POST \
--url https://api.apimart.ai/v1/uploads/images \
--header 'Authorization: Bearer <token>' \
--form 'file=@/path/to/source.png'
url devuelta como único elemento de image_urls. El sondeo, la respuesta completada y region_edit funcionan igual que con un ID de tarea: lee result.image_id y objects, y envía la edición de selección. Las URL subidas son temporales y se conservan 72 horas de forma predeterminada.
image_urls acepta exactamente una URL HTTP(S) absoluta y accesible públicamente. El modo de URL solo admite cache_only=true; no envíes también source_task_id, cached_only ni refresh.Respuesta completada
Ensegment, data.result contiene directamente la segmentación y no está dentro de 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": "..." }
}]
}
}
}
| Campo | Descripción |
|---|---|
result.image_id | ID del recurso usado por region_edit |
result.image_url | URL HTTP(S) alineada con image_id |
objects[].index | Índice original del servidor; consérvalo para object_indices |
objects[].box_xyxy | Cuadro de píxeles de máscara [x1,y1,x2,y2] |
objects[].score | Confianza de detección; puede ser null |
objects[].mask_size | Siempre [height,width]; no fijes dimensiones |
objects[].mask_rle | COCO compressed RLE para contornos precisos |
objects[].mask_url | URL opcional de máscara; puede estar vacía |
mask_rle ni mask_url válido solo admite edición aproximada por cuadro.
Decodificar mask_rle
mask_rle.counts es una cadena de conteos comprimidos COCO, no Base64 ni zlib. Se expande por columnas; el primer tramo es fondo y luego alterna primer plano y fondo.
El siguiente TypeScript lo convierte en una máscara binaria por filas adecuada para el navegador:
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 a registros, analítica, URLs ni informes de errores.
Convertir máscaras en selecciones precisas
interface SelectionBoundary { points: number[] }
interface SelectionRegion { outer: SelectionBoundary; holes?: SelectionBoundary[] }
0–1. Cada anillo requiere al menos 3 puntos distintos, área no nula y no debe autointersecarse. Conserva como máximo las 16 regiones mayores por capa y 400 puntos por anillo.
mask_size es [height,width] y usa coordenadas de la máscara original, no del tamaño CSS. Con object-fit: contain, resta los márgenes, escala según el área dibujada y limita el resultado a 0–1.mask_url requiere CORS. Define crossOrigin = "anonymous" antes de src o recupera un Blob. Decodificar mask_rle directamente evita esta dependencia.
Editar una región: region_edit
Parámetros de solicitud
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
model | string | ✅ | Fijo: grok-imagine-2.0-ext |
operation | string | ✅ | region_edit |
nsfw_check | boolean | — | Valor predeterminado: false.true: revisar el prompt de edición y la imagen de entrada con omni-moderation-latest.false u omitido: no enviar una solicitud de moderación. |
image_id | string | ✅ | ID del recurso de origen; primero usa image_id de segment y después el resultado de edición más reciente |
prompt | string | ✅ | Instrucción no vacía que describe el cambio |
selection_regions | array | * | Polígonos normalizados a 0–1 con outer y holes opcionales; recomendado |
boxes | number[][] | * | Rectángulos [x1,y1,x2,y2]; los cuadros en píxeles requieren mask_size |
object_indices | integer[] | * | Valores originales de objects[].index; solo edición aproximada por cuadro |
mask_size | integer[] | * | Obligatorio para cuadros en píxeles; [height,width] con enteros positivos |
selection_regions, boxes u object_indices debe contener datos. La API permite combinarlos, pero el frontend debería usar un solo método por solicitud.
No envíes
billing_model_name, size, aspect_ratio, source_aspect_ratio, source_size ni image_urls. Omite n o usa 1; omite claim_asset o usa false; omite response_format o usa url. No se admiten Base64 ni stream=true.Métodos de selección
| Método | Origen de selección | Precisión | Uso recomendado |
|---|---|---|---|
selection_regions | Polígonos del frontend | Exacta, con huecos | Edición de capas o pincel en producción |
boxes | Rectángulos del frontend | Aproximación rectangular | Herramienta de cuadro o MVP |
object_indices | Índices originales de segment | Aproximación rectangular | Prueba rápida de integración |
- Polígono preciso
- Cuadro normalizado
- Cuadro en píxeles
- Índice de objeto
{
"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 puede ser plano o pares anidados. Cada valor debe ser finito y estar entre 0–1; cada anillo necesita al menos 3 pares.{
"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. No los sustituyas por índices de una lista filtrada, ordenada o agrupada en el frontend.Respuesta completada
{
"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]. En respuestas antiguas, empareja url[0] con image_ids[0] solo si ambas matrices tienen la misma longitud. Continúa únicamente tras obtener una URL HTTP(S) y un image_id nuevo.
Usa expires_at como referencia de caducidad; no fijes un número de horas. Descarga o guarda los recursos necesarios a largo plazo.
Edición continua
Al completar una edición, actualiza a la vez la URL visible, el ID del recurso y el ID de la tarea de origen, y limpia las capas y el sondeo anteriores.- Volver a segmentar: usa el ID de esta tarea
region_editcomosource_task_id - Volver a editar: usa el nuevo
image_iddevuelto - Nunca envíes
image_idasegmentni sigas editando el ID de la imagen anterior.
Gestión de errores
| HTTP / estado | Causa habitual | Tratamiento |
|---|---|---|
| 400 origen u operación no válidos | Operación incorrecta; ambos orígenes o ninguno; tarea inutilizable; URL no válida; o image_id/image_index enviados a segment | Elegir exactamente un origen válido. Para subidas, enviar una URL HTTP(S) pública con cache_only=true |
| 400 selección no válida | Prompt vacío, selección ausente o polígono, cuadro o índice inválido | Validar prompt y selección antes de enviar |
| 400 opción no admitida | claim_asset, n, formato, tamaño o streaming no válido | Eliminar campos no admitidos y usar salida URL |
| 401 / 403 | Clave no válida o sin permiso del modelo | Revisar la clave del servidor y el acceso de la cuenta |
| 402 | Saldo insuficiente | Solicitar recarga antes de reintentar |
| 409 | Solicitud idempotente en curso, modificada o indeterminada | Seguir la respuesta y no cambiar la clave automáticamente |
| 429 / 5xx | Límite o fallo temporal | Respetar Retry-After y aplicar retroceso limitado |
| failed / task_failed | Falló la ejecución asíncrona | Detener el sondeo y mostrar data.error.message |
Facturación
segmentes gratuito y termina concost=0ycredits_cost=0, pero requiere autenticación y un origen válido.region_edites de pago. Usacostycredits_costde la tarea completada; no fijes precios en el frontend.- Nunca envíes el campo interno
billing_model_name.
Lista de comprobación del frontend
- Mantener la API Key solo en el backend o BFF.
- Enviar un origen a
segment:source_task_idoimage_urlscon una URL pública. No enviarimage_idniimage_index. - Con
image_urls, establecercache_only=truey omitircached_onlyyrefresh. - Usar el
image_idde segment pararegion_edity aportar al menos un método de selección. - Usar
selection_regionspara edición precisa;object_indicessolo aproxima un cuadro. - Interpretar siempre
mask_sizecomo[height,width]y compensar escala y márgenes. - Reutilizar la clave idempotente original en el mismo reintento y validar tanto la URL como el nuevo
image_id.