# Up to 50 payouts in one call

`POST /payouts/batches` · Skerry · Paying out

Up to 50 payouts in one call. All are checked first, and the batch's total per customer and currency is checked against the caller's daily and monthly limits before anything is sent; each then runs as its own payout and reports its own outcome. Needs an Idempotency-Key. A dry run checks every item and the totals and sends nothing.

- Scope: payouts:write
- Moves money: yes
- Idempotency: required
- Untrusted: reference, payouts.reference

## Parameters

- `Idempotency-Key` (header, required), string: A repeat with the same key and body returns the first answer instead of acting twice.

## Request body

`application/json`

```json
{
  "type": "object",
  "required": [
    "payouts"
  ],
  "properties": {
    "payouts": {
      "type": "array",
      "minItems": 1,
      "maxItems": 50,
      "items": {
        "type": "object",
        "required": [
          "customer_id",
          "from",
          "to"
        ],
        "properties": {
          "customer_id": {
            "type": "string",
            "maxLength": 200
          },
          "amount": {
            "type": "string",
            "pattern": "^\\d{1,18}(\\.\\d{1,10})?$",
            "description": "The amount as a decimal string in `from.currency`. Send this or `amount_minor`."
          },
          "amount_minor": {
            "type": "integer",
            "minimum": 1,
            "description": "The same amount in integer minor units of `from.currency`."
          },
          "from": {
            "type": "object",
            "required": [
              "currency",
              "wallet_id"
            ],
            "properties": {
              "currency": {
                "type": "string",
                "description": "A lowercase currency code or stablecoin ticker."
              },
              "wallet_id": {
                "type": "string",
                "maxLength": 200
              }
            }
          },
          "to": {
            "type": "object",
            "required": [
              "currency"
            ],
            "properties": {
              "currency": {
                "type": "string",
                "description": "A lowercase currency code or stablecoin ticker."
              },
              "payee_id": {
                "type": "string",
                "maxLength": 200
              },
              "wallet_id": {
                "type": "string",
                "maxLength": 200
              },
              "address": {
                "type": "string",
                "maxLength": 200
              },
              "chain": {
                "type": "string",
                "maxLength": 40
              }
            },
            "description": "Exactly one of `payee_id`, `wallet_id` or `address`."
          },
          "rail": {
            "type": "string",
            "maxLength": 40
          },
          "speed": {
            "type": "string",
            "enum": [
              "fastest",
              "cheapest",
              "standard"
            ]
          },
          "quote_id": {
            "type": "string",
            "maxLength": 200,
            "description": "Executes exactly what was quoted, once."
          },
          "execute_at": {
            "type": "string",
            "format": "date-time"
          },
          "schedule": {
            "type": "object",
            "required": [
              "every",
              "unit"
            ],
            "properties": {
              "every": {
                "type": "integer",
                "minimum": 1
              },
              "unit": {
                "type": "string",
                "enum": [
                  "day",
                  "week",
                  "month"
                ]
              },
              "end_at": {
                "type": "string",
                "format": "date-time"
              },
              "count": {
                "type": "integer",
                "minimum": 1
              }
            }
          },
          "release_on": {
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "approval"
                ]
              },
              {
                "type": "object",
                "required": [
                  "event",
                  "object_id"
                ],
                "properties": {
                  "event": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "object_id": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "travel_rule": {
            "type": "object",
            "properties": {
              "originator": {
                "type": "object"
              },
              "beneficiary": {
                "type": "object"
              }
            }
          },
          "reference": {
            "type": "string",
            "maxLength": 500
          },
          "external_ref": {
            "type": "string",
            "maxLength": 200,
            "description": "The document this belongs to in your own system."
          },
          "external_kind": {
            "type": "string",
            "enum": [
              "invoice",
              "bill",
              "order",
              "booking",
              "other"
            ]
          },
          "remittance": {
            "type": "object",
            "properties": {
              "invoice_number": {
                "type": "string",
                "maxLength": 200
              },
              "amount": {
                "type": "string",
                "maxLength": 40
              },
              "date": {
                "type": "string",
                "maxLength": 40
              }
            }
          },
          "dry_run": {
            "type": "boolean",
            "description": "Check the request and report what would happen, without doing it."
          }
        }
      }
    },
    "reference": {
      "type": "string",
      "maxLength": 500
    },
    "dry_run": {
      "type": "boolean",
      "description": "Check the request and report what would happen, without doing it."
    }
  }
}
```

## Responses

- `200`: Success.
- `202`: requires_approval — Not an error: the operation is held for a person. The body names the approval.
- `400`: price_below_minimum — The price is below the smallest single payment for a method (`detail.method`, `detail.minimum`), or has a part of a cent. Set `credit_only`, raise the price, or drop the method.
- `401`: dpop_invalid — The token is bound to a key and the DPoP proof was missing, wrong for this request, or already used.
- `402`: payment_failed — The payer's bank or card refused. `detail.reason` says why in plain terms.
- `403`: agent_payment_over_max — The merchant asks for more than `max_amount`. Nothing was signed. `detail.asked_minor` is the lowest price asked, in US cents.
- `404`: not_found — No such object in this project — including one that belongs to somebody else.
- `409`: token_not_issued — A delegated payment token could not be issued ready to use, for instance because the payer would have to act. Nothing was sent to the merchant.
- `429`: too_many_waiters — This key already has as many requests waiting (`?wait=`) as it may. Let one finish, or read without wait.
- `500`: internal_error — Ours. Quote the `request_id` and we can find the call.
- `502`: platform_error — A provider failed. Safe to retry with the same Idempotency-Key.
- `503`: oauth_unavailable — The authorisation server's keys could not be read, so tokens cannot be checked. API keys still work.

## Example

```sh
curl -X POST 'https://api.skerry.xyz/payouts/batches' \
  -H 'Authorization: Bearer $KEY' \
  -H 'Content-Type: application/json' \
  -d '"{ payouts: [ ...as POST /payouts ], reference?, dry_run? }"'
```
