# Forespørsler

En forespørsel er ett kall til én modell. Den har en ID (`req_…`), en status, kostnaden i API-kreditter (1000 = 1 USD) og, når den
lykkes, de genererte filene. Det samme objektet returneres fra hvert endepunkt nedenfor, for hver modell.

## Finn en modell

Katalogen over alle 1 496 modellene er offentlig JSON (ingen nøkkel kreves):

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

| Spørringsparameter | Betydning |
|---|---|
| `q` | Ord som alle må finnes i navnet, ID-en, produsenten eller taggene, for eksempel `kling 3`. |
| `category` | Én kategori-ID, for eksempel `text-to-video` eller `upscale`. `GET https://api.doitong.com/v1/categories` viser alle 21 med antallene sine. |
| `lab` | Modellens produsent, etter navn eller ID, for eksempel `Google` eller `black-forest-labs`. |
| `family` | En `family`-ID fra en tidligere rad: hver variant av én modell (pro, fast, image-to-video, …). |
| `mode` | `exact` (prisen beregnes fra inndataene), `measured` (fra lengden eller størrelsen på inndatafilene), `estimate` (en estimert pris per kjøring) eller `metered` (belastes etter faktisk bruk, opptil et maksimum per kjøring). |
| `limit`, `cursor` | Sidestørrelse (1 til 100, standard 50) og `next_cursor` fra forrige side. |

Hver rad har `id`, `name`, `lab`, `category`, `family`, `summary`, `tags`, `output_kind`, `docs_url` og et `price`-
objekt (se [Priser](https://doitong.com/developers/docs/pricing#price-objects)). `GET https://api.doitong.com/v1/models/{model_id}` legger til
fullstendig JSON Schema for inndata og utdata, kanoniske parameternavn, prisreglene og et eksempel på inndata. En ukjent
`category` eller `mode` gir `400 invalid_parameter`.

## Kjør en modell

```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": "..."}'
```

- Brødteksten er modellens inndata, et JSON-objekt. Hver modellside viser parameterne.
- Inndataene kontrolleres før noe belastes. Ugyldige inndata gir `422 invalid_input` med den aktuelle
  `param`, og koster ingenting.
- `?wait=N` (opptil 20 sekunder) holder kallet åpent til forespørselen er ferdig eller tiden løper ut.
- `?webhook_url=https://…` sender en signert POST til denne URL-en når forespørselen er ferdig (se [Webhooks](https://doitong.com/developers/docs/webhooks)).
- `?storage=permanent` eller `?storage=temporary` velger hvor lenge utdatafilene beholdes; uten dette brukes kontoens
  innstilling (se [Hvor filene lagres](#storage)).

Responsen er `202 Accepted` mens forespørselen fortsatt behandles, og `200 OK` når den ble ferdig innen ventetiden (eller
når det er en avspilling, se nedenfor). Headerne `Location` og `Doitong-Request-Id` inneholder forespørsels-URL-en og ID-en.

## Statuser

Forespørselens livssyklus: `queued` → `running` → `succeeded` | `failed` | `canceled` (endelig; mislykkede og avbrutte forespørsler refunderes).

| Status | Betydning | Endelig |
|---|---|---|
| `queued` | Godtatt og belastet, venter på en arbeider. `queue_position` kan vise plasseringen i køen. | nei |
| `running` | Modellen genererer. | nei |
| `succeeded` | Ferdig. `outputs` viser filene. | ja |
| `failed` | Modellen eller en grense stoppet den. `error` forklarer hvorfor. API-kredittene tilbakebetales. | ja |
| `canceled` | Avbrutt før den produserte et resultat. API-kredittene tilbakebetales. | ja |

En forespørsel som varer lenger enn tidsgrensen, mislykkes med koden `timeout` og blir refundert: 15 minutter for bilder,
60 minutter for video, 30 minutter for lyd og alt annet.

## Forespørselsobjektet

```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` er likt for alle modeller: én oppføring per generert fil med `type` (`image`, `video`, `audio`,
  `file` eller `3d`), en `url` på vår lagring, `content_type` og, når det er kjent, `file_size`, `width`, `height`,
  `duration`.
- `output` er modellens eget resultatobjekt (feltene vises på hver modellside) med de samme URL-ene.
- `storage` angir hvordan filene beholdes: `mode` (`permanent` eller `temporary`), lagrede `bytes`, `expires_at` (når en
  midlertidig fil slettes, `null` for permanente) og `expired` (`true` når filene er borte).
- `cost.credits` er prisen for kallet i API-kreditter (`cost.usd` i USD), `cost.charged` det som ble trukket fra
  API-saldoen, og `cost.refunded` det som kom tilbake. For en `metered`-modell er `cost.credits` maksimumsbeløpet som holdes av
  ved start (`cost.held`); når kjøringen lykkes, viser `cost.settled` hva bruken kom på, og resten av maksimumsbeløpet ligger i
  `cost.refunded` (se [Belastet etter bruk](https://doitong.com/developers/docs/pricing#metered)).
- Når en forespørsel mislykkes, er `error` `{ "type": …, "code": …, "message": … }`.

## Les en forespørsel

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

- `?wait=N` (opptil 20 sekunder) bruker long polling: kallet returnerer så snart forespørselen er endelig, eller etter N sekunder med
  gjeldende status. Å gjenta dette er den enkleste måten å vente på et resultat.
- `?logs=1` legger modellens fremdriftslogglinjer (de siste 50) til som `logs`.

Du kan bare lese forespørsler fra din egen konto; alle andre ID-er gir `404 request_not_found`.

## List opp forespørsler

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

Nyeste først. `limit` er 1 til 100 (standard 20), og `status` og `model` filtrerer. Responsen er
`{ "object": "list", "data": [ … ], "has_more": true, "next_cursor": "req_…" }`; send `cursor=<next_cursor>` for
neste side.

## Avbryt en forespørsel

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

- Avbrutt før modellen startet: statusen blir `canceled`, API-kredittene tilbakebetales, og du får `200`.
- Allerede under generering: avbrytningen videresendes, og du får `202` med `"cancel_requested": true`. Hvis modellen
  likevel blir ferdig, lykkes forespørselen som normalt og belastes.
- Allerede endelig: `409 not_cancelable` (en forespørsel som allerede er `canceled`, returnerer bare `200`).

## Slett filene til en forespørsel

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

Sletter våre kopier av forespørselens utdatafiler nå og stopper lagringskostnaden for dem. Responsen er forespørselsobjektet
med `storage.expired: true`; URL-ene forblir i posten, men fungerer ikke lenger. Et nytt kall gjør ingenting
(`200`). En forespørsel som fortsatt er `queued` eller `running`, har ingen filer ennå: `409 request_active`. Krever `models:run`.

## Idempotens: prøv på nytt uten å betale to ganger

Nettverk kan svikte. For å prøve en kjøring på nytt på en trygg måte, send en `Idempotency-Key`-header (en valgfri streng på opptil
255 tegn, unik per operasjon, for eksempel din egen ordre-ID):

- Samme nøkkel og samme brødtekst som tidligere: du får den opprinnelige forespørselen tilbake (`200`, headeren
  `Idempotent-Replayed: true`), og ingenting belastes på nytt.
- Samme nøkkel og brødtekst etter en kjøring som mislyktes før den nådde modellen (`upstream_error` eller `internal_error` ved
  innsending, `insufficient_credits`, `budget_exceeded`, `too_many_inflight`): ingenting ble produsert og ingenting
  belastes, så forsøket kjører modellen på nytt i stedet for å returnere feilen.
- Samme nøkkel med en annen brødtekst: `409 idempotency_mismatch`.
- Nøkler er knyttet til API-nøkkelen som sendte dem.

## Hvor filene lagres

Alle utdatafiler kopieres til lagringen vår før forespørselen markeres som `succeeded`, så URL-ene i `outputs` er på
våre egne verter, og du kan lenke direkte til dem. Hvor lenge de beholdes, velger du selv:

| Modus | Hvor lenge | Pris |
|---|---|---|
| `permanent` (standard) | Til du sletter dem | 100 API-kreditter (0,10 $) per GB per måned, belastet daglig fra API-saldoen |
| `temporary` | 7 dager, deretter slettet | Gratis |

- Kontoinnstillingen avgjør for nye forespørsler: bryteren «Lagre filer for alltid» i
  [dashbordet](https://doitong.com/developers/dashboard#balance), eller `PATCH https://api.doitong.com/v1/account/storage` med
  `{"mode": "temporary"}`. `GET https://api.doitong.com/v1/account` viser den under `storage`, med byteantallet du beholder og
  månedsestimatet.
- `?storage=permanent|temporary` ved en kjøring (`storage`-argumentet til MCP-verkøyet `run`) overstyrer den for denne kjøringen.
- Hvis du endrer innstillingen, påvirker det aldri filer du allerede har; slett dem med
  [`DELETE /requests/{id}/files`](#delete-files).
- Når API-saldoen ikke kan betale for lagring, belastes ingenting, og du får en e-post: fyll på innen
  30 dager, ellers blir de beholdte filene midlertidige og slettes 7 dager senere.

I det sjeldne tilfellet at kopieringen vår mislykkes, har oppføringen `"stored": false`, og URL-en er den opprinnelige,
kortvarige URL-en: last den ned snart.
