> ## 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.

# Offizielle Grok-Videomodelle

> Videos aus Text oder Referenzbildern mit grok-imagine-video und grok-imagine-video-1.5 erzeugen oder ein Quellvideo mit dem Basismodell bearbeiten.

<Info>
  Diese Seite gilt für die offiziellen Modelle `grok-imagine-video` und `grok-imagine-video-1.5`. Sie unterscheiden sich von `grok-imagine-1.5-video-ext` auf der bestehenden Generierungsseite; Modellnamen und Parameter dürfen nicht gemischt werden.
</Info>

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

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.apimart.ai/v1/videos/generations \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --header 'Idempotency-Key: 7d0141e4-a19a-4650-a717-dab777b3a330' \
    --data '{
      "model": "grok-imagine-video",
      "prompt": "A cinematic aerial shot of a coastal city at sunrise",
      "duration": 5,
      "resolution": "720p",
      "aspect_ratio": "16:9",
      "nsfw_check": true
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.apimart.ai/v1/videos/generations", {
    method: "POST",
    headers: {
      Authorization: "Bearer <token>",
      "Content-Type": "application/json",
      Accept: "application/json",
      "Idempotency-Key": crypto.randomUUID(),
    },
    body: JSON.stringify({
      model: "grok-imagine-video",
      prompt: "Improve motion consistency and apply cinematic color grading",
      video: { url: "https://cdn.example.com/source-video.mp4" },
    }),
  });

  console.log(response.status, await response.json());
  ```
</RequestExample>

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

  ```json 400 theme={null}
  {
    "error": {
      "message": "Invalid request parameters",
      "type": "invalid_request_error",
      "param": "resolution",
      "code": "invalid_request_error"
    }
  }
  ```
</ResponseExample>

## Integrationsübersicht

Alle Modi verwenden denselben asynchronen Endpunkt:

```http theme={null}
POST https://api.apimart.ai/v1/videos/generations
```

| Anfragefelder                 | Modus                   | Modelle                  |
| ----------------------------- | ----------------------- | ------------------------ |
| Ohne `image_urls` und `video` | Text zu Video           | Beide Modelle            |
| `image_urls`                  | Referenzbilder zu Video | Beide Modelle            |
| `video`                       | Videobearbeitung        | Nur `grok-imagine-video` |

Speichern Sie nach dem Senden `data[0].task_id` und fragen Sie dann ab:

```http theme={null}
GET https://api.apimart.ai/v1/tasks/{task_id}
```

<Warning>
  Senden Sie nicht `X-APIMart-Response-Version`. Dieser Header wechselt zu einem HTTP-`202`-Schema; diese Seite verwendet die ältere asynchrone HTTP-`200`-Antwort.
</Warning>

## Modellfunktionen

| Funktion                        | `grok-imagine-video` | `grok-imagine-video-1.5` |
| ------------------------------- | :------------------: | :----------------------: |
| Text zu Video                   |           ✅          |             ✅            |
| Ein oder mehrere Referenzbilder |           ✅          |             ✅            |
| Videobearbeitung                |           ✅          |             ❌            |
| `480p`                          |           ✅          |             ✅            |
| `720p`                          |           ✅          |             ✅            |
| `1080p`                         |           ❌          |             ✅            |
| Dauer: 1–15 Sekunden            |         1–15         |           1–15           |
| Prompt                          |        1–8000        |          1–8000          |

```text theme={null}
duration     = 8
resolution   = 480p
aspect_ratio = auto
```

Der öffentliche Vertrag definiert keine feste Obergrenze für Referenzbilder. Verwenden Sie ein nicht leeres Array gültiger URLs in Originalreihenfolge und übernehmen Sie keine Limits der Bildmodelle.

## Request-Header

<ParamField header="Authorization" type="string" required>
  `Bearer <APIMART_API_KEY>`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Immer `application/json` verwenden.
</ParamField>

<ParamField header="Accept" type="string">
  `application/json`
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  `Idempotency-Key` ist optional und für kostenpflichtige Generierung und Bearbeitung dringend empfohlen. Zulässig sind 1–191 sichtbare ASCII-Zeichen; empfohlen wird UUID. Netzwerk-Retries verwenden denselben Key und identischen Body. Bei unklarem Ergebnis keinen neuen Key verwenden.

  Für jede neue logische Aktion einen neuen Key verwenden. Ein Retry derselben Aktion muss Original-Key und identischen Body nutzen.
</ParamField>

## Anfrageparameter

### Gemeinsame Felder

<ParamField body="model" type="string" required>
  Offizieller Modellname; Videobearbeitung nur mit dem Basismodell

  * `grok-imagine-video`
  * `grok-imagine-video-1.5`
</ParamField>

<ParamField body="prompt" type="string" required>
  Nicht leere Anweisung, höchstens 8000 Unicode-Zeichen

  `Array.from(prompt).length`
</ParamField>

<ParamField body="nsfw_check" type="boolean" default={false}>
  Legt fest, ob vor dem Senden der Videoaufgabe eine Inhaltsprüfung erfolgt.

  * `true`: Prompt und Eingabebilder mit `omni-moderation-latest` prüfen
  * `false` oder nicht angegeben: Keine Prüfung anfordern; keine zusätzlichen Prüfkosten oder Verzögerung (Standard)
</ParamField>

### Generierungsfelder

<ParamField body="duration" type="integer" default={8}>
  Nur Generierung; Ganzzahl 1–15, Standard 8
</ParamField>

<ParamField body="resolution" type="string" default="480p">
  Base: `480p/720p`; 1.5: `480p/720p/1080p`; Standard `480p`

  * `grok-imagine-video`: `480p`, `720p`
  * `grok-imagine-video-1.5`: `480p`, `720p`, `1080p`
</ParamField>

<ParamField body="aspect_ratio" type="string" default="auto">
  Nur Generierung; `auto`, `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2` oder `2:3`

  * `auto`
  * `1:1`, `16:9`, `9:16`
  * `4:3`, `3:4`, `3:2`, `2:3`
</ParamField>

<ParamField body="image_urls" type="string[]">
  Optionales Referenzbild-Array; jede Position ist eine öffentliche HTTPS-URL; bei leerer Auswahl Feld weglassen

  * Jeder Eintrag muss eine öffentlich erreichbare HTTPS-URL sein; relative URLs, Data URLs und rohes Base64 werden nicht unterstützt.
  * Keine Aliasfelder wie `image`, `images` oder `input_reference` senden.
  * Die Reihenfolge bleibt erhalten; doppelte URLs belegen mehrere Eingabeplätze und können mehrfach berechnet werden.
</ParamField>

### Felder der Videobearbeitung

<ParamField body="video" type="object">
  Quellvideo `{url}` als öffentliche HTTPS-URL; nur Basismodell

  <Expandable title="URL">
    <ParamField body="url" type="string" required>
      HTTPS
    </ParamField>
  </Expandable>
</ParamField>

Eine Videobearbeitung erfordert `model`, `prompt` und `video`; optional ist `nsfw_check` zulässig. Senden Sie weder `duration`, `resolution`, `aspect_ratio` noch `image_urls`; die Plattform erkennt die Quelldauer.

## TypeScript-Anfragetypen

Eine diskriminierte Union verhindert, dass Generierungsfelder an die Videobearbeitung gesendet werden.

```ts theme={null}
type GrokVideoModel =
  | "grok-imagine-video"
  | "grok-imagine-video-1.5";

type GrokVideoResolution = "480p" | "720p" | "1080p";

type GrokVideoAspectRatio =
  | "auto"
  | "1:1"
  | "16:9"
  | "9:16"
  | "4:3"
  | "3:4"
  | "3:2"
  | "2:3";

interface GrokVideoGenerateRequest {
  model: GrokVideoModel;
  prompt: string;
  nsfw_check?: boolean;
  duration?: number;
  resolution?: GrokVideoResolution;
  aspect_ratio?: GrokVideoAspectRatio;
  image_urls?: string[];
}

interface GrokVideoEditRequest {
  model: "grok-imagine-video";
  prompt: string;
  nsfw_check?: boolean;
  video: { url: string };
}

type GrokVideoRequest =
  | GrokVideoGenerateRequest
  | GrokVideoEditRequest;
```

## Anfragebeispiele

<Tabs>
  <Tab title="Text zu Video">
    ```json theme={null}
    {"model":"grok-imagine-video","prompt":"A cinematic aerial shot at sunrise","duration":5,"resolution":"720p","aspect_ratio":"16:9"}
    ```
  </Tab>

  <Tab title="1.5 · 1080p">
    ```json theme={null}
    {"model":"grok-imagine-video-1.5","prompt":"A smooth studio product commercial","duration":5,"resolution":"1080p","aspect_ratio":"16:9"}
    ```
  </Tab>

  <Tab title="Ein oder mehrere Referenzbilder">
    ```json theme={null}
    {
      "model":"grok-imagine-video-1.5",
      "prompt":"Use the first image as subject and the second as style",
      "duration":5,
      "resolution":"720p",
      "aspect_ratio":"16:9",
      "image_urls":[
        "https://cdn.example.com/subject.jpg",
        "https://cdn.example.com/style.jpg"
      ]
    }
    ```
  </Tab>

  <Tab title="Videobearbeitung">
    ```json theme={null}
    {
      "model":"grok-imagine-video",
      "prompt":"Improve motion consistency and apply cinematic color grading",
      "video":{"url":"https://cdn.example.com/source.mp4"}
    }
    ```
  </Tab>
</Tabs>

## Asynchrone Aufgaben

### Erstellung erfolgreich

Eine erfolgreiche Erstellung liefert HTTP `200`. Speichern Sie `data[0].task_id`; die Übermittlung bedeutet noch nicht, dass das Video fertig ist. Eine Task-ID bedeutet gesendet, nicht abgeschlossen.

```json theme={null}
{
  "code":200,
  "data":[{"status":"submitted","task_id":"task_01M09Y4Y101HTFFPV2QPW9DQ3W"}]
}
```

### Task abfragen

```http theme={null}
GET https://api.apimart.ai/v1/tasks/{task_id}
Authorization: Bearer <APIMART_API_KEY>
Accept: application/json
```

Fragen Sie `GET /v1/tasks/{task_id}` alle 3–5 Sekunden ab. Nach Neuladen kann das Polling mit der gespeicherten Task-ID fortgesetzt werden.

| `data.status` | Bedeutung                    | Frontend-Aktion                                    |
| ------------- | ---------------------------- | -------------------------------------------------- |
| `pending`     | In Warteschlange             | Weiter abfragen                                    |
| `processing`  | Wird generiert               | Fortschritt zeigen und weiter abfragen             |
| `completed`   | Abgeschlossen                | Ergebnis lesen und stoppen                         |
| `failed`      | Fehlgeschlagen und erstattet | Fehler zeigen und stoppen                          |
| `unknown`     | Vorübergehend unbekannt      | Abfragefrequenz senken und später erneut versuchen |

### Abgeschlossene Antwort

```json theme={null}
{
  "code":200,
  "data":{
    "id":"task_xxx",
    "status":"completed",
    "progress":100,
    "created":1787040038,
    "completed":1787040081,
    "actual_time":43,
    "estimated_time":100,
    "cost":0.072,
    "credits_cost":0.72,
    "result":{"videos":[{"url":["https://cdn.example.com/result.mp4"],"expires_at":1787126481}]}
  }
}
```

`result.videos[0].url` ist ein String-Array, kein einzelner String. Prüfen Sie jeden Wert vor der Anzeige als HTTPS-URL. Eine Laufzeitprüfung wird empfohlen:

```ts theme={null}
function extractVideoURLs(payload: unknown): string[] {
  const groups = (payload as any)?.data?.result?.videos;
  if (!Array.isArray(groups)) return [];

  return groups.flatMap((group: any) =>
    Array.isArray(group?.url)
      ? group.url.filter(
          (url: unknown): url is string =>
            typeof url === "string" && /^https:///i.test(url),
        )
      : [],
  );
}
```

Für den Ablauf ist `expires_at` maßgeblich. Keine feste Lebensdauer codieren; Benutzer zum Download oder Speichern auffordern.

### Fehlerantwort

```json theme={null}
{
  "code":200,
  "data":{
    "id":"task_xxx",
    "status":"failed",
    "progress":100,
    "cost":0,
    "credits_cost":0,
    "error":{"message":"Task failed.","type":"task_failed","param":"","code":"task_failed"}
  }
}
```

<Warning>
  Eine Abfrage kann HTTP `200` liefern, obwohl `data.status` `failed` ist. Erfolg anhand von `data.status` bestimmen; fehlgeschlagene Tasks haben `cost=0`.
</Warning>

## Preiskatalog

```http theme={null}
GET https://api.apimart.ai/api/pricing/models/all
```

Lesen Sie `GET /api/pricing/models/all` und suchen Sie das Modell nach `id` in `data.models.video`. Preise sind Schätzungen; maßgeblich ist `data.cost` der Task-Antwort.

### Preis des Ausgabevideos

```json theme={null}
{
  "fixed_prices":{
    "unit":"usd_per_second",
    "dimension":"resolution",
    "items":[
      {"key":"480P","original_price":0.05,"after_discount":0.04},
      {"key":"720P","original_price":0.07,"after_discount":0.056}
    ]
  }
}
```

* Preisschlüssel sind `480P/720P/1080P`, Anfragewerte klein geschrieben; beim Nachschlagen normalisieren.
* `default` sind Kompatibilitätsdaten und keine wählbare Auflösung.
* `after_discount` direkt verwenden; Rabatt nicht erneut anwenden.

### Preis des Eingabematerials

```json theme={null}
{"unit":"usd_per_image","original_price":0.002,"after_discount":0.0016}
```

```json theme={null}
{"unit":"usd_per_second","original_price":0.01,"after_discount":0.008}
```

Der Videoeingabepreis ist ein skalares Objekt. `items`, `billing_mode` oder `max_billable_seconds` nicht verlangen. 1.5 hat keinen Videoeingabepreis.

### Schätzformeln

```text theme={null}
Generierung = rabattierter Ausgabepreis/Sekunde × Dauer + rabattierter Bildpreis × Bildanzahl
Bearbeitung = rabattierter 720P-Ausgabepreis/Sekunde × Quellsekunden + Videoeingabepreis × Quellsekunden
```

Benutzerspezifische Preise und Serverrundung können abweichen. Endgültig ist immer Task-`data.cost`.

## Frontend-Regeln

### Modellwechsel

* Base zeigt nur `480p/720p`; 1.5 zusätzlich `1080p`.
* Wechsel von 1.5 `1080p` zu Base fällt auf `480p` zurück.
* Videobearbeitung fixiert `grok-imagine-video`.

### Moduswechsel

| Modus            | Sichtbare Steuerelemente                             | Gesendete Felder                  | Zu löschen                                    |
| ---------------- | ---------------------------------------------------- | --------------------------------- | --------------------------------------------- |
| Generierung      | `prompt/duration/resolution/aspect_ratio/nsfw_check` | Generierungsfelder                | `image_urls/video`                            |
| Referenzbilder   | Generierungsfelder + `image_urls`                    | Generierungsfelder + `image_urls` | `video`                                       |
| Videobearbeitung | `prompt/video/nsfw_check`                            | `model/prompt/video/nsfw_check`   | `duration/resolution/aspect_ratio/image_urls` |

`nsfw_check` ist in jedem Modus optional. Bei aktivierter Prüfung `true` senden; andernfalls weglassen oder `false` senden.

Deaktivieren Sie die Ausführung, wenn eine dieser Bedingungen erfüllt ist:

* Textmodus lässt `image_urls` und `video` weg.
* Referenzmodus sendet `image_urls` und lässt `video` weg.
* Videobearbeitung löscht alle reinen Generierungsfelder.
* Bei leerem/zu langem Prompt, ungültiger Dauer, Auflösung, Material-URL, laufendem Upload oder Doppelsenden deaktivieren.
* Prompt auf 8000 Unicode-Zeichen, Dauer auf Ganzzahl 1–15 begrenzen.
* Nur öffentliche HTTPS-URLs verwenden; leeres `image_urls` weglassen.

## Häufige Fehler

| HTTP / Status | Häufige Ursache                             | Behandlung                                    |
| ------------- | ------------------------------------------- | --------------------------------------------- |
| `400`         | Ungültige Parameter, Prompt-Limit oder Enum | Servermeldung und betroffenes Feld zeigen     |
| `401`         | API-Key fehlt oder ist ungültig             | Nicht wiederholen; Serverkonfiguration prüfen |
| `402`         | Guthaben reicht nicht                       | Zum Aufladen auffordern                       |
| `403`         | Modellberechtigung fehlt                    | Nicht automatisch wiederholen                 |
| `409`         | Idempotenzkonflikt oder Anfrage läuft       | Original-Key behalten und später wiederholen  |
| `429`         | Rate-Limit                                  | `Retry-After` oder exponentielles Backoff     |
| `500/502/503` | Vorübergehender Dienstfehler                | Begrenzt mit Original-Key wiederholen         |
| `failed`      | Asynchrone Aufgabe fehlgeschlagen           | Polling stoppen, Fehler zeigen; Kosten null   |

## Frontend-Checkliste

* API-Key nur im Backend oder BFF speichern.
* Offizielle Modellnamen nicht mit `grok-imagine-1.5-video-ext` mischen.
* Prompt auf 8000 Unicode-Zeichen, Dauer auf Ganzzahl 1–15 begrenzen.
* Nur öffentliche HTTPS-URLs verwenden; leeres `image_urls` weglassen.
* Für Videobearbeitung nur `model/prompt/video` plus optionales `nsfw_check` und das Basismodell verwenden.
* Beim Senden `data[0].task_id`, Endstatus aus `data.status` lesen.
* Ausgabe aus `result.videos[].url[]` lesen und `expires_at` beachten.
* Katalogpreise anzeigen, finalen Betrag aus Task-`data.cost` lesen.
