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

# Create Payout Batch

> Create a payout batch containing 1 to 200 items.

The request must include `Idempotency-Key`. Reusing the same key for the same merchant returns the previously created batch. Ensure the same key is associated with the same request content.

Create a payout batch in draft status. Reusing the same Idempotency-Key for the same merchant returns the previously created batch.

Merchant identity is determined by authentication through stablepay-auth. Do not include merchant\_id in request parameters. Batch statuses and business rules are determined by the StablePay Payout service.

## Authentication and Headers

Authenticate with a Bearer API Key and the three signing headers below. Compute HMAC-SHA256 over `{timestamp}.{nonce}.{requestBody}` with the API Secret, then encode the result as lowercase hex. Sign the exact request body bytes; use an empty string when no body is sent. See [Authentication and Signing](/en/api/getting-started#authentication-and-signing).

<ParamField header="Authorization" type="string" required>
  Bearer API Key: `Bearer sk_live_xxx`.
</ParamField>

<ParamField header="X-StablePay-Timestamp" type="string" required>
  Unix timestamp in seconds, within 5 minutes of the server time.
</ParamField>

<ParamField header="X-StablePay-Nonce" type="string" required>
  Random string for replay protection. Use a new nonce for each request. Minimum length: 16. Maximum length: 64.
</ParamField>

<ParamField header="X-StablePay-Signature" type="string" required>
  Request signature encoded as lowercase hexadecimal.
</ParamField>

<ParamField header="Idempotency-Key" type="string" required>
  Idempotency key for batch creation, scoped to the merchant. Maximum length: 128 characters. Minimum length: 1. Maximum length: 128.
</ParamField>

## Request Body

`application/json` (required).

Only the fields defined below are allowed.

<ParamField body="currency" type="string" required>
  Allowed values: `USDT`, `USDC`.
</ParamField>

<ParamField body="description" type="string" />

<ParamField body="items" type="object[]" required>
  Minimum items: 1. Maximum items: 200.

  <Expandable title="Fields">
    Only the fields defined below are allowed.

    <ResponseField name="real_name" type="string" />

    <ResponseField name="network" type="string" required>
      Allowed values: `erc20`, `trc20`, `spl`.
    </ResponseField>

    <ResponseField name="address" type="string" required>
      Minimum length: 1. Maximum length: 256.
    </ResponseField>

    <ResponseField name="memo" type="string">
      Maximum length: 128.
    </ResponseField>

    <ResponseField name="amount" type="string" required>
      Decimal amount greater than zero, represented as a string with at most two decimal places. Pattern: `^(?:0\.(?:0[1-9]|[1-9][0-9]?)|[1-9][0-9]*(?:\.[0-9]{1,2})?)$`.
    </ResponseField>
  </Expandable>
</ParamField>

## Success Response

HTTP `200`, `application/json`. Created successfully.

Only the fields defined below are allowed.

<ResponseField name="batch_id" type="string" required />

<ResponseField name="status" type="string" required>
  Allowed values: `draft`, `needs_fix`, `pending`, `pending_approval`, `processing`, `partially_completed`, `completed`, `failed`, `canceled`, `rejected`.
</ResponseField>

<ResponseField name="currency" type="string" required>
  Allowed values: `USDT`, `USDC`.
</ResponseField>

<ResponseField name="network" type="string" required>
  Allowed values: `erc20`, `trc20`, `spl`.
</ResponseField>

<ResponseField name="total_count" type="integer" required>
  Minimum: 0.
</ResponseField>

<ResponseField name="valid_count" type="integer" required>
  Minimum: 0.
</ResponseField>

<ResponseField name="invalid_count" type="integer" required>
  Minimum: 0.
</ResponseField>

<ResponseField name="success_count" type="integer" required>
  Minimum: 0.
</ResponseField>

<ResponseField name="failed_count" type="integer" required>
  Minimum: 0.
</ResponseField>

<ResponseField name="total_amount" type="string" required>
  Nonnegative decimal amount represented as a string, with at most two decimal places. Pattern: `^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$`.
</ResponseField>

<ResponseField name="service_fee_amount" type="string" required>
  Nonnegative decimal amount represented as a string, with at most two decimal places. Pattern: `^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$`.
</ResponseField>

<ResponseField name="debit_amount" type="string" required>
  Nonnegative decimal amount represented as a string, with at most two decimal places. Pattern: `^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$`.
</ResponseField>

<ResponseField name="frozen_amount" type="string" required>
  Nonnegative decimal amount represented as a string, with at most two decimal places. Pattern: `^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$`.
</ResponseField>

<ResponseField name="charged_service_fee_amount" type="string" required>
  Nonnegative decimal amount represented as a string, with at most two decimal places. Pattern: `^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$`.
</ResponseField>

<ResponseField name="can_submit" type="boolean">
  Whether the batch can currently be submitted. This field is omitted when status is canceled.
</ResponseField>

<ResponseField name="validation_errors" type="object[]" required>
  <Expandable title="Fields">
    Only the fields defined below are allowed.

    <ResponseField name="field" type="string" required />

    <ResponseField name="code" type="string" required />

    <ResponseField name="message" type="string" required />
  </Expandable>
</ResponseField>

<ResponseField name="description" type="string | null" />

<ResponseField name="created_at" type="integer" required>
  Format: `int64`.
</ResponseField>

<ResponseField name="submitted_at" type="integer | null">
  Format: `int64`.
</ResponseField>

<ResponseField name="completed_at" type="integer | null">
  Format: `int64`.
</ResponseField>

### Response Headers

| Header | Description |
| - | - |
| `X-Request-ID` | Request tracing ID. |
| `Cache-Control` | The response must not be cached. Allowed values: `no-store`. |

## Error Responses

| HTTP | Description |
| - | - |
| 400 | Invalid HTTP request format or parameters, or the payout request failed business validation. Possible business error codes include address\_risk\_rejected, batch\_amount\_limit\_exceeded, batch\_amount\_too\_low, batch\_cannot\_submit, batch\_empty\_items, custody\_balance\_insufficient, insufficient\_balance, and quota\_blocked. |
| 401 | Authentication failed or a trusted merchant identity is missing. |
| 403 | The current merchant is not authorized to access or operate on this resource. |
| 500 | A payout business error that is not currently classified more specifically. |
| 503 | The payout service timed out or is temporarily unavailable. If this occurs during a write request, query the resource status before retrying. |

Only the fields defined below are allowed.

<ResponseField name="code" type="integer" required />

<ResponseField name="message" type="string" required />

<ResponseField name="errorCode" type="string" required />

<ResponseField name="data" type="null" required />

## Related Endpoints

* [Submit Payout Batch](/en/api/payouts/submit-batch)
* [Cancel Payout Batch](/en/api/payouts/cancel-batch)
* [Get Payout Batch](/en/api/payouts/get-batch)
* [List Payout Batches](/en/api/payouts/list-batches)
* [List Batch Items](/en/api/payouts/list-batch-items)
* [Get Payout Item](/en/api/payouts/get-item)

<RequestExample>
  Set `API_KEY` and `SECRET_KEY` before running this example. Set `BATCH_ID` or `ITEM_ID` when required by the endpoint.

  Replace the example recipient address before use. Reuse the same idempotency key and request content when retrying the same creation request.

  ```bash cURL theme={"system"}
  TIMESTAMP=$(date +%s)
  NONCE=$(uuidgen)
  BODY='{"currency":"USDT","description":"October contractor payouts","items":[{"real_name":"Example Recipient","network":"trc20","address":"TExampleAddressReplaceBeforeUse","amount":"125.00"}]}'
  IDEMPOTENCY_KEY='payout-create-example-001'
  SIGNATURE=$(printf '%s' "${TIMESTAMP}.${NONCE}.${BODY}" | openssl dgst -sha256 -hmac "${SECRET_KEY}" | awk '{print $NF}')

  curl --request POST "https://api.stablepay.co/api/v1/payout-batches" \
    -H "Authorization: Bearer ${API_KEY}" \
    -H "X-StablePay-Timestamp: ${TIMESTAMP}" \
    -H "X-StablePay-Nonce: ${NONCE}" \
    -H "X-StablePay-Signature: ${SIGNATURE}" \
    -H "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
    -H "Content-Type: application/json" \
    --data-raw "${BODY}"
  ```
</RequestExample>

<ResponseExample>
  ```json 400 theme={"system"}
  {
    "code": 400,
    "message": "Idempotency-Key header is required",
    "errorCode": "invalid_request",
    "data": null
  }
  ```

  ```json 401 theme={"system"}
  {
    "code": 401,
    "message": "authenticated merchant is required",
    "errorCode": "authentication_required",
    "data": null
  }
  ```

  ```json 403 theme={"system"}
  {
    "code": 403,
    "message": "access denied",
    "errorCode": "forbidden",
    "data": null
  }
  ```

  ```json 500 theme={"system"}
  {
    "code": 500,
    "message": "payout request failed",
    "errorCode": "payout_error",
    "data": null
  }
  ```

  ```json 503 theme={"system"}
  {
    "code": 503,
    "message": "payout service is temporarily unavailable",
    "errorCode": "service_unavailable",
    "data": null
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.