> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Grok Imagine 2.0 Ext Ebenen- und Bereichsbearbeitung

> Mit segment Objektebenen und präzise Masken abrufen und anschließend Polygone, Rechtecke oder erkannte Objekte mit region_edit bearbeiten.

<Info>
  `segment` und `region_edit` verwenden beide den vorhandenen asynchronen Bild-Endpunkt. Speichern Sie die zurückgegebene `task_id` und fragen Sie anschließend den [Aufgabenstatus](/de/api-reference/tasks/status) ab; die Erstellungsanfrage liefert noch keine finalen Ebenen oder Bilder.
</Info>

<Warning>
  API-Keys dürfen niemals in Browser-Bundles, LocalStorage, URLs oder Frontend-Logs gelangen. Rufen Sie APIMart über Ihr Backend oder BFF auf.
</Warning>

<RequestExample>
  ```bash cURL theme={null}
  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",
      "source_task_id": "<COMPLETED_SINGLE_IMAGE_TASK_ID>",
      "include_mask_rle": true,
      "cached_only": false
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "code": 200,
    "data": [{ "status": "submitted", "task_id": "task_..." }]
  }
  ```
</ResponseExample>

## Übersicht der Operationen

| Zweck                                                                      | Wichtige Eingabe              | Abschlussergebnis                  | Abrechnung                              |
| -------------------------------------------------------------------------- | ----------------------------- | ---------------------------------- | --------------------------------------- |
| `segment`: Objekte erkennen und Ebenen, Boxen sowie präzise Masken abrufen | `source_task_id`              | `image_id`, `image_url`, `objects` | Kostenlos                               |
| `region_edit`: Polygon, Rechteck oder erkanntes Objekt bearbeiten          | `image_id`, `prompt`, Auswahl | Neue URL und `image_id`            | Pro abgeschlossener Aufgabe abgerechnet |

```text theme={null}
task_id → segment(source_task_id) → image_id + mask_rle
        → selection_regions → region_edit → new task_id + image_id
```

<Note>
  `source_task_id` und `image_id` sind nicht austauschbar. `segment` erwartet die Quell-Task-ID, `region_edit` die Bild-Asset-ID. Um ein bearbeitetes Bild erneut zu segmentieren, verwenden Sie die abgeschlossene `region_edit`-Task-ID als neue `source_task_id`.
</Note>

## Request-Header

Verwenden Sie `Authorization: Bearer <APIMART_API_KEY>`, `Content-Type: application/json` und `Accept: application/json`.

`Idempotency-Key` ist optional und wird für kostenpflichtige `region_edit`-Anfragen dringend empfohlen. Er akzeptiert 1–191 sichtbare ASCII-Zeichen; empfohlen wird eine UUID. Verwenden Sie pro neuer logischer Operation einen neuen Key. Ein Netzwerk-Retry derselben Anfrage muss den ursprünglichen Key und identischen Body wiederverwenden. Wiederholen Sie eine kostenpflichtige Bearbeitung mit unklarem Ergebnis nicht automatisch mit einem neuen Key.

## Asynchroner Aufgabenablauf

Eine erfolgreiche Erstellung liefert HTTP `200` und `data[0].task_id`. Fragen Sie `GET /v1/tasks/{task_id}?language=de` zunächst alle 2 Sekunden, später höchstens alle 5 Sekunden und maximal 10 Minuten lang ab. Stoppen Sie alte Abfragen beim Wechsel des Quellbilds.

<Warning>
  Eine Aufgabenabfrage kann HTTP `200` liefern, obwohl `data.status` den Wert `failed` hat. Entscheiden Sie immer anhand von `data.status` und zeigen Sie gegebenenfalls `data.error` an.
</Warning>

## `segment`

### Anfrageparameter

| Feld               | Typ     | Pflicht | Standard | Beschreibung                                                           |
| ------------------ | ------- | :-----: | -------- | ---------------------------------------------------------------------- |
| `model`            | string  |    ✅    | —        | Fest `grok-imagine-2.0-ext`                                            |
| `operation`        | string  |    ✅    | —        | Fest `segment`                                                         |
| `source_task_id`   | string  |    ✅    | —        | Abgeschlossene Grok-Einzelbildaufgabe des aktuellen Benutzers          |
| `include_mask_rle` | boolean |    —    | `true`   | COCO compressed RLE zurückgeben; für präzise Bearbeitung `true` lassen |
| `cache_only`       | boolean |    —    | `false`  | Nur Segmentierungs-Cache prüfen; bei Miss kein Upstream-Aufruf         |
| `cached_only`      | boolean |    —    | `false`  | Upstream-Cachehinweis, keine lokale Garantie                           |
| `refresh`          | boolean |    —    | `false`  | Cache umgehen; nicht im normalen Editorablauf verwenden                |

`segment` benötigt keinen `prompt`. Senden Sie weder `image_id`, `image_index`, `billing_model_name`, `n`, `size` noch `response_format`. `cache_only=true` und `refresh=true` schließen sich aus.

### Anfragebeispiele

<Tabs>
  <Tab title="Ebenen abrufen">
    ```json theme={null}
    {
      "model": "grok-imagine-2.0-ext",
      "operation": "segment",
      "source_task_id": "<COMPLETED_SINGLE_IMAGE_TASK_ID>",
      "include_mask_rle": true,
      "cached_only": false
    }
    ```
  </Tab>

  <Tab title="Cache prüfen">
    ```json theme={null}
    {
      "model": "grok-imagine-2.0-ext",
      "operation": "segment",
      "source_task_id": "<COMPLETED_SINGLE_IMAGE_TASK_ID>",
      "include_mask_rle": true,
      "cache_only": true
    }
    ```
  </Tab>
</Tabs>

Ein Cache-Miss ist weiterhin eine erfolgreiche Aufgabe. Verwenden Sie `cache_status` (`hit` oder `miss`) oder `from_cache`; leiten Sie keinen Treffer aus `cached` ab.

### Abgeschlossene Antwort

Bei `segment` ist `data.result` direkt das Segmentierungsergebnis und nicht in `images` verpackt.

```json theme={null}
{
  "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": "..." }
      }]
    }
  }
}
```

| Feld                  | Beschreibung                                                      |
| --------------------- | ----------------------------------------------------------------- |
| `result.image_id`     | Asset-ID für `region_edit`                                        |
| `result.image_url`    | Mit `image_id` ausgerichtete HTTP(S)-URL                          |
| `objects[].index`     | Originaler Serverindex; für `object_indices` unverändert behalten |
| `objects[].box_xyxy`  | Masken-Pixelbox `[x1,y1,x2,y2]`                                   |
| `objects[].score`     | Erkennungswahrscheinlichkeit; kann `null` sein                    |
| `objects[].mask_size` | Immer `[height,width]`; Maße nie fest codieren                    |
| `objects[].mask_rle`  | COCO compressed RLE für präzise Konturen                          |
| `objects[].mask_url`  | Optionale Maskenbild-URL; kann leer sein                          |

Ein Objekt ohne gültiges `mask_rle` oder `mask_url` kann nur näherungsweise per Box bearbeitet werden.

## `mask_rle` dekodieren

`mask_rle.counts` ist eine COCO-komprimierte Zählzeichenfolge, weder Base64 noch zlib. Sie wird spaltenweise expandiert; der erste Lauf ist Hintergrund, danach wechseln Vorder- und Hintergrund.

Das folgende TypeScript wandelt sie in eine browserfreundliche, zeilenweise Binärmaske um:

```ts theme={null}
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 };
}
```

Dekodieren Sie große Masken in einem Web Worker. Vollständige `mask_rle.counts` dürfen nicht in Logs, Analysen, URLs oder Fehlerberichte gelangen.

### Masken in präzise Auswahlbereiche umwandeln

```ts theme={null}
interface SelectionBoundary { points: number[] }
interface SelectionRegion { outer: SelectionBoundary; holes?: SelectionBoundary[] }
```

Ermitteln Sie zusammenhängende Bereiche und Löcher, vereinfachen Sie die Konturen und normalisieren Sie jeden Punkt auf `0–1`. Jeder Ring braucht mindestens 3 unterschiedliche Punkte, eine Fläche größer null und darf sich nicht selbst schneiden. Behalten Sie höchstens 16 größte Regionen pro Ebene und 400 Punkte pro Ring.

<Warning>
  `mask_size` ist `[height,width]` und bezieht sich auf die Quellmaske, nicht auf CSS-Abmessungen. Bei `object-fit: contain` müssen Letterbox-Versatz und tatsächlicher Zeichenbereich berücksichtigt und Werte auf `0–1` begrenzt werden.
</Warning>

Das Lesen von Pixeln aus Quellbild oder `mask_url` erfordert CORS. Setzen Sie `crossOrigin = "anonymous"` vor `src` oder laden Sie einen Blob. Direktes Dekodieren von `mask_rle` vermeidet diese Abhängigkeit.

## Bereich bearbeiten: `region_edit`

### Anfrageparameter

| Feld                | Typ          | Pflicht | Beschreibung                                                                                     |
| ------------------- | ------------ | :-----: | ------------------------------------------------------------------------------------------------ |
| `model`             | string       |    ✅    | Fest `grok-imagine-2.0-ext`                                                                      |
| `operation`         | string       |    ✅    | `region_edit`                                                                                    |
| `image_id`          | string       |    ✅    | Quell-Asset-ID; zuerst `image_id` aus `segment`, danach das jeweils neueste Bearbeitungsergebnis |
| `prompt`            | string       |    ✅    | Nicht leere Anweisung für die gewünschte Änderung                                                |
| `selection_regions` | array        |    \*   | Auf `0–1` normalisierte Polygone mit `outer` und optionalen `holes`; empfohlen                   |
| `boxes`             | number\[]\[] |    \*   | Rechtecke `[x1,y1,x2,y2]`; Pixelboxen benötigen `mask_size`                                      |
| `object_indices`    | integer\[]   |    \*   | Originalwerte aus `objects[].index`; nur näherungsweise Boxbearbeitung                           |
| `mask_size`         | integer\[]   |    \*   | Für Pixelboxen erforderlich; `[height,width]` mit positiven Ganzzahlen                           |

Mindestens eines von `selection_regions`, `boxes` oder `object_indices` muss nicht leer sein. Die API akzeptiert Kombinationen, im Frontend sollte pro Anfrage nur eine Methode verwendet werden.

<Warning>
  Senden Sie weder `billing_model_name`, `size`, `aspect_ratio`, `source_aspect_ratio`, `source_size` noch `image_urls`. `n` weglassen oder auf `1` setzen; `claim_asset` weglassen oder `false`; `response_format` weglassen oder `url`. Base64 und `stream=true` werden nicht unterstützt.
</Warning>

### Auswahlmethoden

| Methode             | Quelle der Auswahl       | Genauigkeit                    | Empfohlene Nutzung                        |
| ------------------- | ------------------------ | ------------------------------ | ----------------------------------------- |
| `selection_regions` | Frontend-Polygone        | Präzise, einschließlich Löcher | Produktive Ebenen- oder Pinselbearbeitung |
| `boxes`             | Frontend-Rechtecke       | Box-Näherung                   | Rechteckwerkzeug oder MVP                 |
| `object_indices`    | Originale Segmentindizes | Box-Näherung                   | Schneller Integrationstest                |

<Tabs>
  <Tab title="Präzises Polygon">
    ```json theme={null}
    {
      "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` kann flach oder als verschachtelte Paare angegeben werden. Jeder Wert muss endlich und zwischen `0–1` liegen; jeder Ring benötigt mindestens 3 Koordinatenpaare.
  </Tab>

  <Tab title="Normalisierte Box">
    ```json theme={null}
    {
      "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]]
    }
    ```
  </Tab>

  <Tab title="Pixelbox">
    ```json theme={null}
    {
      "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]
    }
    ```
  </Tab>

  <Tab title="Objektindex">
    ```json theme={null}
    {
      "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]
    }
    ```

    Indizes müssen aus der Segmentantwort derselben `image_id` stammen. Ersetzen Sie sie nicht durch Indizes einer im Frontend gefilterten, sortierten oder gruppierten Liste.
  </Tab>
</Tabs>

### Abgeschlossene Antwort

```json theme={null}
{
  "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
      }]
    }
  }
}
```

Bevorzugen Sie `result.images[0].items[0]`. Bei älteren Antworten dürfen `url[0]` und `image_ids[0]` nur bei gleich langen Arrays gepaart werden. Fahren Sie erst fort, wenn sowohl eine HTTP(S)-URL als auch eine neue `image_id` vorhanden sind.

Für den URL-Ablauf ist `expires_at` maßgeblich; keine feste Stundenzahl codieren. Langfristig benötigte Assets rechtzeitig herunterladen oder speichern.

## Fortlaufende Bearbeitung

Nach Abschluss einer Bearbeitung aktualisieren Sie Anzeige-URL, aktuelle Asset-ID und Quell-Task-ID gemeinsam und löschen alte Ebenen sowie Abfragestatus.

* Erneut segmentieren: diese `region_edit`-Task-ID als `source_task_id` verwenden
* Erneut bearbeiten: die neu zurückgegebene `image_id` verwenden
* Übergeben Sie niemals `image_id` an `segment` und bearbeiten Sie nicht weiter die vorherige Bild-ID.

## Fehlerbehandlung

| HTTP / Status                       | Häufige Ursache                                                                     | Behandlung                                                                              |
| ----------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| 400 ungültige Quelle oder Operation | Falsche Operation, unbrauchbare Quellaufgabe oder `image_id/image_index` an segment | Operation prüfen und abgeschlossene Einzelbildaufgabe des aktuellen Benutzers verwenden |
| 400 ungültige Auswahl               | Leerer Prompt, fehlende Auswahl oder ungültiges Polygon, Rechteck bzw. Objektindex  | Prompt und Auswahl vor dem Senden prüfen                                                |
| 400 nicht unterstützte Option       | Ungültiges `claim_asset`, `n`, Ausgabeformat, Größe oder Streaming                  | Nicht unterstützte Felder entfernen und URL-Ausgabe verwenden                           |
| 401 / 403                           | Ungültiger Key oder fehlende Modellberechtigung                                     | Server-Key und Kontozugriff prüfen                                                      |
| 402                                 | Unzureichendes Guthaben                                                             | Vor erneutem Versuch aufladen                                                           |
| 409                                 | Idempotenzanfrage läuft, wurde geändert oder ist unbestimmt                         | Antwort befolgen; Key nicht automatisch wechseln                                        |
| 429 / 5xx                           | Rate-Limit oder vorübergehender Dienstfehler                                        | `Retry-After` beachten und begrenzt zurücksetzen                                        |
| failed / task\_failed               | Asynchrone Ausführung fehlgeschlagen                                                | Polling stoppen und `data.error.message` anzeigen                                       |

## Abrechnung

* `segment` ist kostenlos und endet mit `cost=0` sowie `credits_cost=0`, erfordert aber Authentifizierung und eine gültige Quellaufgabe.
* `region_edit` ist kostenpflichtig. Verwenden Sie `cost` und `credits_cost` der abgeschlossenen Aufgabe; Preise nicht im Frontend fest codieren.
* Das interne Feld `billing_model_name` darf nie gesendet werden.

## Frontend-Checkliste

* API-Key nur im Backend oder BFF speichern.
* An `segment` nur `source_task_id` senden, nie `image_id` oder `image_index`.
* Für `region_edit` die `image_id` aus segment und mindestens eine Auswahlmethode verwenden.
* Für präzise produktive Bearbeitung `selection_regions` verwenden; `object_indices` ist nur eine Box-Näherung.
* `mask_size` stets als `[height,width]` lesen und Skalierung sowie Letterboxing berücksichtigen.
* Bei demselben Netzwerk-Retry den ursprünglichen Idempotenz-Key wiederverwenden und Ausgabe-URL sowie neue `image_id` prüfen.
