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는 기존 비동기 이미지 엔드포인트를 사용합니다. 반환된 task_id를 저장한 뒤 작업 상태 조회를 폴링하세요. 생성 요청은 최종 레이어나 이미지를 직접 반환하지 않습니다.API Key를 브라우저 번들, LocalStorage, URL 또는 프런트엔드 로그에 노출하지 마세요. 백엔드나 BFF를 통해 APIMart를 호출하세요.
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 또는 업로드 이미지 1개가 든 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는 계속 segment가 반환한 자산 ID를 사용합니다. 편집된 이미지를 다시 분할하려면 완료된 region_edit 작업 ID를 다음 source_task_id로 사용하세요.요청 헤더
Authorization: Bearer <APIMART_API_KEY>, Content-Type: application/json, Accept: application/json을 사용합니다.
Idempotency-Key는 선택 사항이지만 유료 region_edit 요청에는 강력히 권장합니다. 표시 가능한 ASCII 문자 1~191자를 지원하며 UUID를 권장합니다. 새 논리 작업마다 새 Key를 사용하고 같은 요청의 네트워크 재시도에는 원래 Key와 동일한 body를 재사용하세요. 결과가 불확실하면 새 Key로 자동 재시도하지 마세요.
비동기 작업 흐름
생성 성공 시 HTTP200과 data[0].task_id가 반환됩니다. GET /v1/tasks/{task_id}?language=ko를 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 정확히 1개. 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; 작업 원본 전용 업스트림 캐시 힌트 |
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로 hit를 판단하지 마세요.
로컬 이미지 업로드
먼저 로컬 파일을 업로드하고 응답에서 공개 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 정확히 1개만 허용합니다. 이미지 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 | region_edit에서 사용하는 자산 ID |
result.image_url | image_id와 대응하는 HTTP(S) URL |
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개 이상, 0이 아닌 면적, 자기 교차 없음 조건을 충족해야 합니다. 레이어당 최대 16개 영역, 링당 최대 400개 점을 유지합니다.
mask_size는 [height,width]이며 CSS 표시 좌표가 아닌 원본 마스크 좌표입니다. object-fit: contain에서는 여백을 빼고 실제 그리기 영역으로 변환한 뒤 0–1로 제한하세요.mask_url 픽셀을 읽으려면 CORS가 필요합니다. src보다 먼저 crossOrigin = "anonymous"를 설정하거나 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. 처음에는 segment의 image_id, 이후에는 최신 편집 결과 사용 |
prompt | string | ✅ | 원하는 변경을 설명하는 비어 있지 않은 지시문 |
selection_regions | array | * | outer와 선택적 holes가 있는 0–1 정규화 다각형. 권장 |
boxes | number[][] | * | 사각형 [x1,y1,x2,y2]. 픽셀 박스에는 mask_size 필요 |
object_indices | integer[] | * | 원본 objects[].index 값. 근사 박스 편집 전용 |
mask_size | integer[] | * | 픽셀 박스에 필수. 양의 정수 [height,width] |
selection_regions, boxes, object_indices 중 하나 이상이 비어 있지 않아야 합니다. API는 조합을 허용하지만 프런트엔드는 요청당 한 방식만 사용하는 것이 좋습니다.
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 | 프런트엔드 다각형 | 구멍을 포함한 정밀 선택 | 프로덕션 레이어 또는 브러시 편집 |
boxes | 프런트엔드 사각형 | 박스 근사 | 박스 도구 또는 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의 segment 응답에서 가져와야 합니다. 프런트엔드에서 필터링, 정렬, 그룹화한 배열의 인덱스로 바꾸지 마세요.완료 응답
{
"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를 함께 갱신하고 이전 레이어와 폴링 상태를 지우세요.- 다시 분할: 이번
region_edit작업 ID를source_task_id로 사용 - 다시 편집: 새로 반환된
image_id사용 image_id를segment에 전달하지 말고 이전 이미지 ID를 계속 편집하지 마세요.
오류 처리
| HTTP / 상태 | 일반 원인 | 처리 |
|---|---|---|
| 400 원본 또는 작업 오류 | 잘못된 작업, 원본 둘 다 또는 미지정, 사용할 수 없는 작업, 잘못된 이미지 URL, 또는 segment에 image_id/image_index 전송 | 유효한 원본 하나만 선택. 업로드는 공개 HTTP(S) URL 1개와 cache_only=true 전송 |
| 400 선택 영역 오류 | 빈 프롬프트, 선택 없음, 또는 잘못된 다각형·박스·인덱스 | 전송 전에 프롬프트와 선택 영역 검증 |
| 400 미지원 옵션 | 잘못된 claim_asset, n, 출력 형식, 크기 또는 스트림 | 미지원 필드를 제거하고 URL 출력 사용 |
| 401 / 403 | Key 오류 또는 모델 권한 없음 | 서버 Key와 계정 권한 확인 |
| 402 | 잔액 부족 | 충전 후 재시도 |
| 409 | 멱등 요청 처리 중, 변경 또는 결과 불확실 | 응답에 따르고 Key를 자동 변경하지 않음 |
| 429 / 5xx | 요청 제한 또는 일시적 장애 | Retry-After에 따라 제한된 백오프 |
| failed / task_failed | 비동기 실행 실패 | 폴링 중지 후 data.error.message 표시 |
과금
segment는 무료이며cost=0,credits_cost=0으로 완료되지만 인증과 유효한 원본 입력이 필요합니다.region_edit는 유료입니다. 완료 작업의cost와credits_cost를 사용하고 프런트엔드에 가격을 고정하지 마세요.- 내부 필드
billing_model_name은 보내지 마세요.
프런트엔드 체크리스트
- API Key는 백엔드 또는 BFF에만 보관합니다.
segment원본은 하나만 보냅니다:source_task_id또는 공개 URL 1개가 든image_urls.image_id나image_index는 보내지 않습니다.image_urls사용 시cache_only=true를 설정하고cached_only와refresh는 생략합니다.region_edit에는 segment의image_id와 하나 이상의 선택 방식을 사용합니다.- 정밀 편집은
selection_regions를 사용하고object_indices는 박스 근사로만 사용합니다. mask_size를 항상[height,width]로 해석하고 표시 배율과 여백을 보정합니다.- 같은 네트워크 재시도에는 원래 멱등 Key를 재사용하고 URL과 새
image_id를 모두 검증합니다.