# Żądania

Żądanie to jedno wywołanie jednego modelu. Ma identyfikator (`req_…`), status, koszt w kredytach API (1000 = 1 USD), a po
pomyślnym zakończeniu także wygenerowane pliki. Ten sam obiekt jest zwracany przez każdy z poniższych endpointów dla każdego modelu.

## Znajdowanie modelu

Katalog wszystkich 1496 modeli jest publicznym JSON-em (klucz nie jest wymagany):

```bash
curl "https://api.doitong.com/v1/models?category=text-to-video&lab=Google&limit=20"
```

| Parametr zapytania | Znaczenie |
|---|---|
| `q` | Słowa, które muszą wystąpić w nazwie, identyfikatorze, nazwie twórcy lub tagach, na przykład `kling 3`. |
| `category` | Jeden identyfikator kategorii, na przykład `text-to-video` lub `upscale`. `GET https://api.doitong.com/v1/categories` wyświetla wszystkie 21 wraz z ich liczebnością. |
| `lab` | Twórca modelu, według nazwy lub identyfikatora, na przykład `Google` lub `black-forest-labs`. |
| `family` | Identyfikator `family` z poprzedniego wiersza: każdy wariant jednego modelu (pro, fast, image-to-video, …). |
| `mode` | `exact` (cena jest obliczana na podstawie danych wejściowych), `measured` (na podstawie długości lub rozmiaru plików wejściowych), `estimate` (szacunkowa cena za uruchomienie) lub `metered` (opłata na podstawie rzeczywistego wykorzystania, do maksymalnej kwoty za uruchomienie). |
| `limit`, `cursor` | Rozmiar strony (od 1 do 100, domyślnie 50) oraz `next_cursor` z poprzedniej strony. |

Każdy wiersz zawiera `id`, `name`, `lab`, `category`, `family`, `summary`, `tags`, `output_kind`, `docs_url` oraz obiekt `price`
(zobacz [Cennik](https://doitong.com/developers/docs/pricing#price-objects)). `GET https://api.doitong.com/v1/models/{model_id}` dodaje
pełny schemat JSON danych wejściowych i wyniku, kanoniczne nazwy parametrów, reguły cenowe oraz przykładowe dane wejściowe. Nieznana
wartość `category` lub `mode` powoduje błąd `400 invalid_parameter`.

## Uruchamianie modelu

```bash
curl -X POST "https://api.doitong.com/v1/run/{model_id}?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1842-cover" \
  -d '{"prompt": "..."}'
```

- Treść żądania to dane wejściowe modelu, czyli obiekt JSON. Każda strona modelu zawiera listę jego parametrów.
- Dane wejściowe są sprawdzane przed naliczeniem jakiejkolwiek opłaty. Nieprawidłowe dane wejściowe zwracają `422 invalid_input` wraz z informacją o błędnym
  `param` i nie powodują żadnych kosztów.
- `?wait=N` (do 20 sekund) wstrzymuje wywołanie do czasu zakończenia żądania lub upływu czasu.
- `?webhook_url=https://…` wysyła podpisane żądanie POST na ten adres po zakończeniu żądania (zobacz [Webhooki](https://doitong.com/developers/docs/webhooks)).
- `?storage=permanent` lub `?storage=temporary` określa, jak długo przechowywane są pliki wyniku; bez tego parametru obowiązuje
  ustawienie konta (zobacz [Gdzie są przechowywane pliki](#storage)).

Odpowiedź ma status `202 Accepted`, gdy żądanie jest nadal przetwarzane, oraz `200 OK`, gdy zakończyło się w czasie oczekiwania (lub
gdy jest powtórzeniem, zobacz niżej). Nagłówki `Location` i `Doitong-Request-Id` zawierają adres URL i identyfikator żądania.

## Statusy

Cykl życia żądania: `queued` → `running` → `succeeded` | `failed` | `canceled` (final; nieudane i anulowane są zwracane).

| Status | Znaczenie | Końcowy |
|---|---|---|
| `queued` | Przyjęte i obciążone opłatą, oczekuje na wykonawcę. `queue_position` może wskazywać miejsce w kolejce. | nie |
| `running` | Model generuje wynik. | nie |
| `succeeded` | Zakończone. `outputs` zawiera listę plików. | tak |
| `failed` | Model lub limit zatrzymał żądanie. `error` wyjaśnia przyczynę. Kredyty API są zwracane. | tak |
| `canceled` | Anulowane przed wygenerowaniem wyniku. Kredyty API są zwracane. | tak |

Żądanie, które działa dłużej niż dozwolony limit czasu, kończy się błędem `timeout`, a opłata jest zwracana: 15 minut dla obrazów,
60 minut dla wideo, 30 minut dla audio i wszystkiego innego.

## Obiekt żądania

```json
{
  "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
  "object": "request",
  "model": "flux/schnell",
  "status": "succeeded",
  "created_at": "2026-10-20T12:00:00Z",
  "started_at": "2026-10-20T12:00:01Z",
  "completed_at": "2026-10-20T12:00:02Z",
  "queue_position": null,
  "cost": { "credits": 3, "usd": "0.003", "charged": 3, "refunded": 0 },
  "input": { "prompt": "..." },
  "output": { "images": [ { "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "width": 1024, "height": 768 } ] },
  "outputs": [
    { "type": "image", "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "content_type": "image/jpeg",
      "width": 1024, "height": 768, "file_size": 183920, "stored": true }
  ],
  "error": null,
  "metrics": { "inference_seconds": 1.2 },
  "storage": { "mode": "permanent", "bytes": 183920, "expires_at": null, "expired": false },
  "urls": {
    "self": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
  }
}
```

- `outputs` ma taką samą strukturę dla każdego modelu: po jednym wpisie dla każdego wygenerowanego pliku, z `type` (`image`, `video`, `audio`,
  `file` lub `3d`), adresem `url` w naszej przestrzeni dyskowej, `content_type` oraz, jeśli są znane, wartościami `file_size`, `width`, `height`,
  `duration`.
- `output` to własny obiekt wyniku modelu (jego pola są wymienione na stronie każdego modelu) zawierający te same adresy URL.
- `storage` określa sposób przechowywania plików: `mode` (`permanent` lub `temporary`), liczbę zapisanych `bytes`, `expires_at` (kiedy
  plik tymczasowy zostanie usunięty, `null` dla plików bezterminowych) oraz `expired` (`true`, gdy pliki zostaną usunięte).
- `cost.credits` to cena wywołania w kredytach API (`cost.usd` w USD), `cost.charged` to kwota pobrana z salda API, a `cost.refunded` to kwota zwrócona. W przypadku modelu `metered` `cost.credits` to maksymalna kwota zablokowana na początku (`cost.held`); po pomyślnym zakończeniu `cost.settled` wskazuje koszt wykorzystania, a pozostała część maksymalnej kwoty znajduje się w `cost.refunded` (zobacz [Opłaty za wykorzystanie](https://doitong.com/developers/docs/pricing#metered)).
- Gdy żądanie zakończy się niepowodzeniem, `error` ma postać `{ "type": …, "code": …, "message": … }`.

## Odczytywanie żądania

```bash
curl "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- `?wait=N` (do 20 sekund) wykonuje długie odpytywanie: wywołanie zwraca wynik natychmiast po zakończeniu żądania albo po N sekundach z bieżącym stanem. Powtarzanie tego wywołania to najprostszy sposób oczekiwania na wynik.
- `?logs=1` dodaje wiersze dziennika postępu modelu (ostatnie 50) jako `logs`.

Możesz odczytywać tylko żądania własnego konta; każdy inny identyfikator powoduje błąd `404 request_not_found`.

## Lista żądań

```bash
curl "https://api.doitong.com/v1/requests?limit=20&status=succeeded&model=flux/schnell" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

Od najnowszych. `limit` przyjmuje wartości od 1 do 100 (domyślnie 20), a `status` i `model` służą do filtrowania. Odpowiedź ma postać
`{ "object": "list", "data": [ … ], "has_more": true, "next_cursor": "req_…" }`; przekaż `cursor=<next_cursor>`, aby
pobrać następną stronę.

## Anulowanie żądania

```bash
curl -X POST "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- Anulowane przed uruchomieniem modelu: status zmienia się na `canceled`, kredyty API są zwracane, a odpowiedź ma status `200`.
- Model już generuje wynik: żądanie anulowania jest przekazywane dalej, a odpowiedź ma status `202` i zawiera `"cancel_requested": true`. Jeśli model
  mimo to zakończy działanie, żądanie kończy się pomyślnie i opłata jest naliczana.
- Już zakończone: `409 not_cancelable` (żądanie, które ma już status `canceled`, po prostu zwraca `200`).

## Usuwanie plików żądania

```bash
curl -X DELETE "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/files" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

Natychmiast usuwa nasze kopie plików wyniku żądania i zatrzymuje naliczanie opłaty za ich przechowywanie. Odpowiedź zawiera obiekt żądania
z `storage.expired: true`; jego adresy URL pozostają w rekordzie, ale przestają działać. Ponowne wywołanie niczego nie zmienia
(`200`). Żądanie o statusie `queued` lub `running` nie ma jeszcze plików: `409 request_active`. Wymaga `models:run`.

## Idempotencja: ponawianie bez podwójnej opłaty

Sieci zawodzą. Aby bezpiecznie ponowić uruchomienie, wyślij nagłówek `Idempotency-Key` (dowolny ciąg do 255 znaków, unikalny dla
operacji, na przykład własny identyfikator zamówienia):

- Ten sam klucz i ta sama treść jak wcześniej: otrzymasz pierwotne żądanie (`200`, nagłówek
  `Idempotent-Replayed: true`), a opłata nie zostanie naliczona ponownie.
- Ten sam klucz i treść po uruchomieniu, które nie powiodło się przed dotarciem do modelu (`upstream_error` lub `internal_error` podczas
  wysyłania, `insufficient_credits`, `budget_exceeded`, `too_many_inflight`): nic nie zostało wygenerowane ani obciążone, więc ponowienie
  uruchamia model zamiast zwracać błąd.
- Ten sam klucz z inną treścią: `409 idempotency_mismatch`.
- Klucze są przypisane do klucza API, który je wysłał.

## Gdzie są przechowywane pliki

Każdy plik wyniku jest kopiowany do naszej przestrzeni dyskowej przed oznaczeniem żądania jako `succeeded`, dlatego adresy URL w `outputs` znajdują się na
naszych hostach i można bezpośrednio tworzyć do nich odnośniki. To Ty wybierasz, jak długo pozostaną:

| Tryb | Czas przechowywania | Cena |
|---|---|---|
| `permanent` (domyślny) | Do usunięcia przez Ciebie | 100 kredytów API (0,10 $) za GB miesięcznie, pobierane codziennie z salda API |
| `temporary` | 7 dni, potem usuwane | Bezpłatnie |

- Ustawienie konta decyduje o nowych żądaniach: przełącznik „Przechowuj pliki bezterminowo” w
  [panelu](https://doitong.com/developers/dashboard#balance) albo `PATCH https://api.doitong.com/v1/account/storage` z
  `{"mode": "temporary"}`. `GET https://api.doitong.com/v1/account` pokazuje je w polu `storage`, wraz z przechowywaną liczbą bajtów i
  miesięcznym szacunkiem.
- `?storage=permanent|temporary` podczas uruchamiania (argument `storage` narzędzia MCP `run`) zastępuje to ustawienie dla danego uruchomienia.
- Zmiana ustawienia nigdy nie dotyka już posiadanych plików; usuń je za pomocą
  [`DELETE /requests/{id}/files`](#delete-files).
- Gdy saldo API nie wystarcza na opłacenie przestrzeni dyskowej, opłata nie jest pobierana i otrzymasz wiadomość e-mail: doładuj saldo w ciągu
  30 dni albo przechowywane pliki zostaną przełączone na tymczasowe i usunięte po kolejnych 7 dniach.

W rzadkim przypadku, gdy kopiowanie się nie powiedzie, wpis zawiera `"stored": false`, a adres URL jest oryginalnym adresem o krótkim czasie ważności:
pobierz plik możliwie szybko.
