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

# Массовые выплаты

Когда нужно выплатить многим получателям сразу, есть два пути. Выбор между ними — не вопрос вкуса:
неправильный упирается в лимит частоты запросов.

|                     | [`POST /v1/payout/batch`](/reference/payout-batch) | [`POST /v1/payout/mass`](/reference/payout-mass) |
| ------------------- | -------------------------------------------------- | ------------------------------------------------ |
| Максимум за раз     | **5000**                                           | 100                                              |
| Обработка           | Асинхронная (`batch_id` + поллинг)                 | Синхронная (результат сразу в ответе)            |
| Управление ошибками | `on_error`: `continue` / `stop`                    | Нет                                              |
| Статус              | **Рекомендуемый путь**                             | **Легаси**                                       |

<Warning>
  **Не нарезайте большой список на пачки по 100.** Раньше эта страница советовала именно так — и
  это прямой путь в `429 rate limit`: 5000 выплат = 50 запросов подряд, а лимит частоты считается по
  запросам (по умолчанию 120/мин на IP). Правильный ответ на «много выплат» — **батч**: один
  подписанный запрос на всю пачку. → [Массовые операции](/guides/batch-operations)
</Warning>

***

## Большие списки: батч

Для любого сколько‑нибудь серьёзного объёма используйте [`POST /v1/payout/batch`](/reference/payout-batch):

<CodeGroup>
  ```python Python theme={null}
  resp = call("/v1/payout/batch", {
      "payouts": [
          {"amount": "25", "currency": "USDT", "network": "tron", "address": "TXY...", "order_id": "p-1"},
          {"amount": "10", "currency": "USDT", "network": "tron", "address": "TZZ...", "order_id": "p-2"},
          # … до 5000 элементов
      ],
      "on_error": "continue",
  })["result"]

  batch_id = resp["batch_id"]     # результаты забираются позже, через /v1/batch/info
  ```

  ```js Node.js theme={null}
  const resp = (await call("/v1/payout/batch", {
    payouts: [
      { amount: "25", currency: "USDT", network: "tron", address: "TXY...", order_id: "p-1" },
      { amount: "10", currency: "USDT", network: "tron", address: "TZZ...", order_id: "p-2" },
      // … до 5000 элементов
    ],
    on_error: "continue",
  })).result;

  const batchId = resp.batch_id;  // результаты забираются позже, через /v1/batch/info
  ```
</CodeGroup>

Полный цикл (отправка → поллинг → поэлементный разбор), `on_error`, ошибки и практические правила —
на отдельной странице: **[Массовые операции](/guides/batch-operations)**.

***

## Маленькие пачки: легаси `/v1/payout/mass`

`/v1/payout/mass` (до 100 выплат) никуда не делся и продолжает работать. Он оправдан ровно в одном
случае: **пачка маленькая, и вам нужен результат прямо в ответе**, без поллинга.

Если сомневаетесь — берите батч.

### Ключевая идея: частичный успех — это норма

Массовая выплата **не** работает по принципу «весь список прошёл или весь откатился». Каждый элемент
живёт своей жизнью: у одного может не хватить баланса, у другого — некорректный адрес, а остальные
уйдут нормально. Поэтому результат нужно разбирать **поэлементно**. (В батче это правило то же самое.)

### Пример

<CodeGroup>
  ```python Python theme={null}
  resp = call("/v1/payout/mass", {"payouts": [
      {"amount": "25", "currency": "USDT", "network": "tron", "address": "TXY...", "order_id": "p-1"},
      {"amount": "10", "currency": "USDT", "network": "tron", "address": "TZZ...", "order_id": "p-2"},
      {"amount": "5",  "currency": "USDT", "network": "tron", "address": "TWW...", "order_id": "p-3"},
  ]})

  for item in resp["result"]["items"]:
      if item["success"]:
          print(item["order_id"], "→", item["status"])       # ушла в обработку
      else:
          print(item["order_id"], "ОШИБКА:", item["message"]) # не создана, причина в message
  ```

  ```js Node.js theme={null}
  const resp = await call("/v1/payout/mass", { payouts: [
    { amount: "25", currency: "USDT", network: "tron", address: "TXY...", order_id: "p-1" },
    { amount: "10", currency: "USDT", network: "tron", address: "TZZ...", order_id: "p-2" },
    { amount: "5",  currency: "USDT", network: "tron", address: "TWW...", order_id: "p-3" },
  ]});

  for (const item of resp.result.items) {
    if (item.success) {
      console.log(item.order_id, "→", item.status);        // ушла в обработку
    } else {
      console.log(item.order_id, "ОШИБКА:", item.message); // не создана, причина в message
    }
  }
  ```
</CodeGroup>

Поля каждого элемента `payouts[]` — те же, что у [`POST /v1/payout`](/reference/payout-create):
`amount`, `currency`, `address`, `order_id` (обязателен), опционально `network`, `memo`, `url_callback`
и другие.

### Ответ

```json theme={null}
{
  "state": 0,
  "result": {
    "items": [
      { "uuid": "…", "order_id": "p-1", "status": "process", "is_final": false,
        "approval_required": false, "success": true },
      { "order_id": "p-2", "success": false,
        "message": "available balance is less than the requested amount" }
    ]
  }
}
```

* **Успешный** элемент: `uuid`, `status`, `success: true`.
* **Неуспешный** элемент: `success: false` и текст причины в `message`.

### Ошибки уровня запроса

Если отклонён **весь** запрос (а не отдельные элементы):

| Код                          | Значение                                                                       |
| ---------------------------- | ------------------------------------------------------------------------------ |
| `400 request.bad_json`       | Тело не парсится.                                                              |
| `400 payout.empty_batch`     | Пустой массив `payouts`.                                                       |
| `400 payout.batch_too_large` | Больше 100 элементов → это сигнал перейти на [батч](/guides/batch-operations). |

***

## Рекомендации (для обоих путей)

* **Больше 100 выплат — только батч.** Не нарезайте на пачки: это лишние запросы и `429`.
* **Уникальный `order_id` на каждый элемент.** Каждая выплата идемпотентна по своему `order_id` — при
  повторе списка уже отправленные не уйдут дважды.
* **`Idempotency-Key` на сам запрос.** Защищает от «отправил список, ответ потерялся, отправил ещё раз».
  Особенно важно для батча: дубль из 5000 выплат — очень дорогая ошибка. →
  [Устойчивый клиент](/guides/resilient-client#главный-принцип)
* **Сохраняйте `uuid` успешных элементов** и сверяйте финальный статус через
  [`POST /v1/payout/info`](/reference/payout-info) или по вебхукам `payout.*`.
* **Проверьте баланс заранее** — при нехватке средств часть элементов вернёт `insufficient_funds`.
* **Разбирайте результат поэлементно.** Частичный успех — норма, а не сбой.

***

## Связанные страницы

<CardGroup cols={2}>
  <Card title="Массовые операции" href="/guides/batch-operations" icon="arrow-right" horizontal>
    батчи платежей, возвратов и выплат (до 5000).
  </Card>

  <Card title="POST /v1/payout/batch" href="/reference/payout-batch" icon="arrow-right" horizontal />

  <Card title="POST /v1/batch/info" href="/reference/batch-info" icon="arrow-right" horizontal />

  <Card title="POST /v1/payout/mass" href="/reference/payout-mass" icon="arrow-right" horizontal />

  <Card title="POST /v1/payout" href="/reference/payout-create" icon="arrow-right" horizontal />

  <Card title="Объект выплаты" href="/reference/payout-object" icon="arrow-right" horizontal />

  <Card title="Первая выплата" href="/guides/first-payout" icon="arrow-right" horizontal />

  <Card title="Ограничение частоты" href="/reference/basics-ratelimit" icon="arrow-right" horizontal>
    почему пачки по 100 упираются в лимит.
  </Card>
</CardGroup>
