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
Слои и редактирование областей Grok Imagine 2.0 Ext
Получайте слои объектов и точные маски через segment, затем редактируйте полигоны, рамки или найденные объекты через 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 и region_edit используют существующий асинхронный endpoint изображений. Сохраните полученный task_id, затем опрашивайте Статус задачи; запрос создания не возвращает готовые слои или изображения.Никогда не размещайте API Key в браузерном bundle, LocalStorage, URL или frontend-логах. Вызывайте APIMart через backend или 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_..." }]
}
Обзор операций
| Назначение | Основной ввод | Готовый результат | Оплата |
|---|---|---|---|
segment: Найти объекты и получить слои, рамки и точные маски | source_task_id или image_urls с одним загруженным изображением | image_id, image_url, objects | Бесплатно |
region_edit: Изменить полигон, прямоугольник или найденный объект | image_id, prompt, выделение | Новый URL и image_id | Оплата за завершённую задачу |
завершённый task_id ─────────┐
├→ segment → image_id + mask_rle
публичный URL загрузки ──────┘ → selection_regions → region_edit → новые task_id + image_id
Выберите ровно один источник для
segment: source_task_id или image_urls. Эти поля и image_id не взаимозаменяемы; region_edit по-прежнему принимает ID ресурса, возвращённый segment. Чтобы сегментировать отредактированное изображение, используйте ID завершённой задачи region_edit как новый source_task_id.Заголовки запроса
ИспользуйтеAuthorization: Bearer <APIMART_API_KEY>, Content-Type: application/json и Accept: application/json.
Idempotency-Key необязателен, но настоятельно рекомендуется для платных запросов region_edit. Поддерживается 1–191 видимый символ ASCII; рекомендуется UUID. Используйте новый ключ для каждой логической операции. При сетевом повторе того же запроса используйте исходный ключ и идентичный body. Если результат неопределён, не повторяйте автоматически с новым ключом.
Асинхронный процесс
Успешное создание возвращает HTTP200 и data[0].task_id. Опрашивайте GET /v1/tasks/{task_id}?language=ru с интервалом от 2 до 5 секунд и общим лимитом 10 минут. Останавливайте старый опрос при смене исходного изображения.
Запрос задачи может вернуть HTTP
200, когда data.status равен failed. Всегда определяйте результат по data.status и показывайте data.error.segment
Параметры запроса
| Поле | Тип | Обязателен | Описание |
|---|---|---|---|
model | string | ✅ | Только grok-imagine-2.0-ext |
operation | string | ✅ | Только segment |
nsfw_check | boolean | — | По умолчанию: false.true: проверить исходное изображение с помощью omni-moderation-latest.false или параметр не указан: не отправлять запрос на проверку. |
source_task_id | string | Условно | Завершённая задача Grok с одним изображением текущего пользователя; несовместим с image_urls |
image_urls | string[] | Условно | Ровно один общедоступный абсолютный HTTP(S) URL; несовместим с source_task_id. Локальное изображение загрузите через POST /v1/uploads/images и используйте возвращённый url |
include_mask_rle | boolean | — | По умолчанию: true; при false маски RLE не возвращаются, но ID ресурса, индексы объектов и рамки сохраняются |
cache_only | boolean | — | По умолчанию: false; с image_urls обязательно true; проверяет только кэш сегментации |
cached_only | boolean | — | По умолчанию: false; подсказка upstream-кэша только для источника-задачи |
refresh | boolean | — | По умолчанию: false; обход кэша только для источника-задачи; не использовать в обычном редакторе |
segment не нужен prompt. Не отправляйте image_id, image_index, billing_model_name, n, size или response_format. Отправьте ровно одно из полей source_task_id и image_urls. Для режима URL требуется cache_only=true, а cached_only и refresh не поддерживаются.
Примеры запросов
- Использовать ID задачи
- Использовать загруженное изображение
- Проверить кэш задачи
{
"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 или from_cache; не определяйте попадание по cached.
Загрузить локальное изображение
Сначала загрузите локальный файл и возьмите публичный URL из ответа:curl --request POST \
--url https://api.apimart.ai/v1/uploads/images \
--header 'Authorization: Bearer <token>' \
--form 'file=@/path/to/source.png'
url единственным элементом image_urls. Опрос, завершённый ответ и вызов region_edit далее работают так же, как с ID задачи: прочитайте result.image_id и objects, затем отправьте редактирование выделения. URL загрузки временные и по умолчанию хранятся 72 часа.
image_urls принимает ровно один общедоступный абсолютный HTTP(S) URL. Режим URL поддерживает только cache_only=true; не отправляйте одновременно source_task_id, cached_only или refresh.Завершённый ответ
Дляsegment поле data.result непосредственно содержит сегментацию и не оборачивается в 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": "..." }
}]
}
}
}
| Поле | Описание |
|---|---|
result.image_id | ID изображения для region_edit |
result.image_url | HTTP(S) URL, соответствующий image_id |
objects[].index | Исходный серверный индекс; сохраняйте для object_indices |
objects[].box_xyxy | Рамка маски в пикселях [x1,y1,x2,y2] |
objects[].score | Уверенность распознавания; может быть null |
objects[].mask_size | Всегда [height,width]; не фиксируйте размеры |
objects[].mask_rle | COCO compressed RLE для точного контура |
objects[].mask_url | Необязательный URL маски; может быть пустым |
mask_rle или mask_url можно редактировать только приблизительно по рамке.
Декодирование mask_rle
mask_rle.counts — строка сжатых счётчиков COCO, а не Base64 или zlib. Она разворачивается по столбцам; первый run — фон, затем чередуются объект и фон.
Следующий TypeScript преобразует её в удобную для браузера двоичную маску по строкам:
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 в логи, аналитику, URL или отчёты об ошибках.
Преобразование маски в точное выделение
interface SelectionBoundary { points: number[] }
interface SelectionRegion { outer: SelectionBoundary; holes?: SelectionBoundary[] }
0–1. В каждом кольце должно быть не менее 3 разных точек, ненулевая площадь и не должно быть самопересечений. Оставляйте до 16 крупнейших областей на слой и 400 точек на кольцо.
mask_size имеет порядок [height,width] и использует координаты исходной маски, а не CSS. При object-fit: contain вычтите поля, масштабируйте по фактической области и ограничьте значения диапазоном 0–1.mask_url нужен CORS. Задайте crossOrigin = "anonymous" до src либо загрузите Blob. Прямое декодирование mask_rle не имеет этой зависимости.
Редактирование области: region_edit
Параметры запроса
| Поле | Тип | Обязателен | Описание |
|---|---|---|---|
model | string | ✅ | Только grok-imagine-2.0-ext |
operation | string | ✅ | region_edit |
nsfw_check | boolean | — | По умолчанию: false.true: проверить промпт редактирования и входное изображение с помощью omni-moderation-latest.false или параметр не указан: не отправлять запрос на проверку. |
image_id | string | ✅ | ID исходного изображения; сначала используйте image_id из segment, затем последнее значение из результата редактирования |
prompt | string | ✅ | Непустая инструкция с описанием изменения |
selection_regions | array | * | Нормализованные полигоны 0–1 с outer и необязательными holes; рекомендуется |
boxes | number[][] | * | Прямоугольники [x1,y1,x2,y2]; для пиксельных рамок нужен mask_size |
object_indices | integer[] | * | Исходные значения objects[].index; только приближённое редактирование рамки |
mask_size | integer[] | * | Обязателен для пиксельных рамок; [height,width] из положительных целых |
selection_regions, boxes или object_indices должно быть непустым. API разрешает комбинации, но frontend должен использовать один способ на запрос.
Не отправляйте
billing_model_name, size, aspect_ratio, source_aspect_ratio, source_size или image_urls. Пропустите n или задайте 1; пропустите claim_asset или задайте false; пропустите response_format или задайте url. Base64 и stream=true не поддерживаются.Способы выделения
| Способ | Источник выделения | Точность | Применение |
|---|---|---|---|
selection_regions | Полигоны frontend | Точно, включая отверстия | Работа со слоями и кистью |
boxes | Прямоугольники frontend | Приближение рамкой | Инструмент рамки или MVP |
object_indices | Исходные индексы segment | Приближение рамкой | Быстрая проверка интеграции |
- Точный полигон
- Нормализованная рамка
- Пиксельная рамка
- Индекс объекта
{
"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 может быть плоским массивом или вложенными парами. Все значения должны быть конечными и находиться в 0–1; в каждом кольце нужно не менее 3 пар.{
"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. Не заменяйте их индексами отфильтрованного, отсортированного или сгруппированного frontend-массива.Завершённый ответ
{
"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]. Для старого ответа сопоставляйте url[0] и image_ids[0] только при равной длине массивов. Продолжайте лишь после получения HTTP(S) URL и нового image_id.
Срок URL определяйте по expires_at; не фиксируйте число часов. Нужные надолго файлы скачивайте или сохраняйте.
Последовательное редактирование
После завершения одновременно обновите отображаемый URL, текущий ID изображения и ID исходной задачи, затем очистите старые слои и состояние опроса.- Повторная сегментация: использовать ID этой задачи
region_editкакsource_task_id - Повторное редактирование: использовать новый
image_id - Не передавайте
image_idвsegmentи не продолжайте редактировать предыдущий ID изображения.
Обработка ошибок
| HTTP / статус | Частая причина | Действие |
|---|---|---|
| 400 неверный источник или операция | Неверная операция; указаны оба источника или ни одного; недоступная задача; неверный URL; либо image_id/image_index отправлен в segment | Выбрать ровно один допустимый источник. Для загрузки передать один публичный HTTP(S) URL с cache_only=true |
| 400 неверное выделение | Пустой prompt, нет выделения или неверный полигон, рамка либо индекс | Проверить prompt и выделение до отправки |
| 400 неподдерживаемая опция | Неверный claim_asset, n, формат, размер или streaming | Удалить неподдерживаемые поля и использовать URL |
| 401 / 403 | Неверный ключ или нет доступа к модели | Проверить серверный ключ и права аккаунта |
| 402 | Недостаточно средств | Пополнить баланс перед повтором |
| 409 | Идемпотентный запрос выполняется, изменён или неопределён | Следовать ответу и не менять ключ автоматически |
| 429 / 5xx | Лимит или временный сбой | Соблюдать Retry-After и ограниченный backoff |
| failed / task_failed | Ошибка асинхронного выполнения | Остановить опрос и показать data.error.message |
Оплата
segmentбесплатен и завершается сcost=0иcredits_cost=0, но требует авторизации и допустимого источника.region_editплатный. Используйтеcostиcredits_costзавершённой задачи; не фиксируйте цены во frontend.- Не отправляйте внутреннее поле
billing_model_name.
Проверка frontend
- Хранить API Key только на backend или BFF.
- Отправлять в
segmentодин источник:source_task_idлибоimage_urlsс одним публичным URL. Не отправлятьimage_idиimage_index. - С
image_urlsустановитьcache_only=trueи не передаватьcached_onlyиrefresh. - Использовать
image_idиз segment дляregion_editи передавать хотя бы один способ выделения. - Для точного редактирования использовать
selection_regions;object_indices— лишь приближение рамкой. - Всегда читать
mask_sizeкак[height,width]и учитывать масштаб и поля. - Для того же сетевого повтора использовать исходный ключ идемпотентности и проверять URL вместе с новым
image_id.