# Задачи

`POST /v1/tasks`

Изображения создаются задачами, других видов задач пока нет. Вы присылаете, что сделать и какой моделью, и получаете один и тот же объект задачи: готовой или ещё идущей. Это не формат OpenAI, поэтому SDK OpenAI и Vercel AI для изображений не подходят, хватает обычного HTTP, как в примерах. Доступные модели и их возможности: `GET /v1/tasks/models`.

Запрос ждёт результата до `wait` секунд. Если задача успела, ответ `200` с результатом приходит сразу. Если нет, ответ `202`, дальше опрос, см. «Опрос и повтор». Перед запуском резервируем стоимость, списываем по цене модели на момент создания и не больше резерва. Неудавшаяся задача не списывается никогда.

- `id` (string) — UUID задачи, 36 символов с дефисами, любой, кроме нулевого; вернётся строчными. Свой id известен до ответа, с ним запрос можно безопасно повторить. Каждой новой задаче нужен новый UUID: id, занятый другим запросом, даёт 409. Без id создадим UUIDv4 и вернём
- `kind` (string, обязательно) — Вид задачи в форме группа/действие, от него зависят поля input. Сейчас только `image/generate`, другой даёт 400 с `param` `/kind`
- `model` (string, обязательно) — Модель, например `google/gemini-3-pro-image`. Модели по умолчанию нет: от неё зависят результат и цена. На неизвестную модель или модель чата ответ 404 `not_found` с `param` `/model`
- `input` (object, обязательно) — Поля вида задачи, см. ниже. Неизвестное поле или значение, которого модель не умеет, дают 400 с путём к полю в `param`, до резерва и без списания
- `options` (object) — Поля отдельных моделей. Сейчас ни одна модель их не объявляет, любое поле внутри даёт 400
- `metadata` (object) — До 16 пар «строка → строка»: ключ до 40 символов из `a-z0-9_`, значение до 500 символов. Возвращается в задаче, по нему можно фильтровать список
- `wait` (integer) — Сколько секунд ждать результата: от 0 до 60, по умолчанию 60. Больше 60 или не целое число: 400 с `param` `/wait`

**Пример запроса**

curl:

```bash
TASK_ID=$(uuidgen)
curl https://api.polyapi.ru/v1/tasks \
  -H "Authorization: Bearer $POLYAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "'$TASK_ID'",
    "kind": "image/generate",
    "model": "google/gemini-3-pro-image",
    "input": {"prompt": "Рыжий кот на подоконнике, акварель", "aspect_ratio": "16:9", "resolution": "2K"}
  }'
```

Python:

```python
import os, uuid, requests

r = requests.post(
    "https://api.polyapi.ru/v1/tasks",
    headers={"Authorization": "Bearer " + os.environ["POLYAPI_KEY"]},
    json={
        "id": str(uuid.uuid4()),
        "kind": "image/generate",
        "model": "google/gemini-3-pro-image",
        "input": {"prompt": "Рыжий кот на подоконнике, акварель", "aspect_ratio": "16:9", "resolution": "2K"},
    },
)
r.raise_for_status()
task = r.json()
print(task["id"], task["status"])
```

Node.js:

```js
const r = await fetch("https://api.polyapi.ru/v1/tasks", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.POLYAPI_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "id": crypto.randomUUID(),
    "kind": "image/generate",
    "model": "google/gemini-3-pro-image",
    "input": {"prompt": "Рыжий кот на подоконнике, акварель", "aspect_ratio": "16:9", "resolution": "2K"},
  }),
});
if (!r.ok) throw new Error(await r.text());
let task = await r.json();
console.log(task.id, task.status);
```

**Ответ 200**

```json
{
  "id": "0f6e4c1a-8a7b-4d2e-9c55-3b1f2a7d9e10",
  "kind": "image/generate",
  "model": "google/gemini-3-pro-image",
  "status": "completed",
  "events": [
    {
      "type": "task.queued",
      "at": "2026-11-07T12:00:00Z"
    },
    {
      "type": "attempt.started",
      "at": "2026-11-07T12:00:00Z",
      "attempt": 1
    },
    {
      "type": "task.completed",
      "at": "2026-11-07T12:00:34Z"
    }
  ],
  "output": [
    {
      "type": "image",
      "url": "https://storage.yandexcloud.net/…/0f6e4c1a-8a7b-4d2e-9c55-3b1f2a7d9e10/0.png?X-Amz-Expires=7200&X-Amz-Signature=…",
      "expires_at": "2026-11-07T14:00:00Z",
      "media_type": "image/png",
      "retained_until": "2026-12-07T12:00:34Z",
      "width": 2752,
      "height": 1536,
      "bytes": 6214533
    }
  ],
  "usage": {
    "cost": {
      "amount": "17.18",
      "currency": "rub"
    }
  }
}
```

**Поля input у image/generate.** Модель принимает только поля из своего `input` в `GET /v1/tasks/models`; поле, которого там нет, даёт 400.

- `prompt` (string, обязательно) — Описание изображения или правки, до `max_length` символов модели
- `count` (integer) — Сколько изображений, от 1 до `max` модели, по умолчанию 1. Цена умножается на count
- `aspect_ratio`, `resolution` (string) — Кадр, например `16:9` и `2K`, допустимые сочетания в `variants` модели. Без обоих полей кадр по умолчанию. Если прислано одно из двух, второе берётся из варианта по умолчанию или из единственного подходящего
- `size` (string) — Кадр пикселями из `variants`, например `2048x2048`. Вместе с aspect_ratio или resolution нельзя: 400
- `format`, `quality` (string) — Формат файла и качество из `values` модели, если она их объявляет
- `seed` (integer) — От 0 до 4294967295, если модель его принимает. Если модерация отклонила готовое изображение, повтор уходит с новым seed. С каким seed сделано изображение, видно в `output[].seed`, если модель его сообщает
- `references` (array) — Ссылки https или data URL (png, jpeg, webp, base64, до 10 МиБ). Сколько можно, задаёт модель; у некоторых моделей от числа референсов зависит цена. Data URL проверяем до резерва: `reference_too_large`, `reference_unsupported`. Ссылку https скачивает провайдер; если не смог, задача `failed`, без списания

**Ответ.** Объект задачи, один для всех видов и состояний. Поля без значения не возвращаются. Решения принимайте только по `status`: HTTP-код (200 или 202) лишь подсказка, а `events` история.

- `id`, `kind`, `model` (string) — Как в запросе
- `status` (string) — `queued`, `in_progress`, `completed` или `failed`
- `events` (array) — История по порядку: `type` и `at` (время RFC 3339, UTC, до секунды). Первое событие `task.queued`, его `at` и есть время создания; последнее `task.completed` или `task.failed`. Незнакомые `type` пропускайте
- `output` (array, completed) — Список частей. У image: `type`, `url`, `media_type`, `expires_at`, `retained_until`, `width`, `height`, `bytes`, `expired` (только `true`, см. «Хранение») и, если модель его знает, `seed`. Частей не больше `count`: если провайдер отклонил часть изображений модерацией, придут остальные, и платите вы только за них
- `error` (object, failed) — Объект ошибки, см. «Ошибки задач»
- `usage` (object) — Пока задача идёт, `reserved`: столько зарезервировано, больше этого не спишется. У завершённой `cost`, окончательная цена. У `failed` он равен `"0"`
- `deadline_at` (string, пока задача идёт) — Время, к которому задача гарантированно завершится
- `poll_after` (integer, пока задача идёт) — Через сколько секунд спросить снова
- `metadata` (object) — Как в запросе, если присылали

Деньги везде один объект: `{ "amount": "42.50", "currency": "rub" }`. Сумма десятичной строкой, точно как списано, не меньше двух знаков после точки; ноль пишется `"0"`.

Источник: https://polyapi.ru/docs/tasks
