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

# Request bulk payout

Bulk payouts operation allows you to initiate multiple payouts for asynchronous processing. Read more about [Payouts](/payouts).

* Bulk requests with more than 20 payout transactions may be rejected by PawaPay.
* This API call is <em>idempotent</em>, which means it is safe to submit a request with the same `payoutId` multiple times.
* Duplicate requests with the same `payoutId` will be ignored with the `DUPLICATE_IGNORED` status.
* Since the request can be rejected, you must check the `status` code in the response for each submitted request. The `rejectionReason` in the response will contain information about the reason of the rejection.
* Callback will be delivered separately for each payout in the bulk request as the payouts are resolved to their final status.

Each individual request can get one of the statuses on initiation:

| Status              | <Tooltip tip="Will a callback be delivered after receiving this status on initiation?">Callback</Tooltip> | Description                                                                                                                                          |
| ------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ACCEPTED`          | Yes                                                                                                       | The payout request has been **accepted** by PawaPay for processing.                                                                                  |
| `ENQUEUED`          | Yes                                                                                                       | The payout request has been **accepted**, but has been enqueued for processing later. Read more about [enqueued payouts](/payouts#enqueued-payouts). |
| `REJECTED`          | No                                                                                                        | The payout request has been **rejected**. See `rejectionReason` for details.                                                                         |
| `DUPLICATE_IGNORED` | No                                                                                                        | The payout request has been **ignored** as a duplicate of an already accepted payout request. Duplication logic relies upon `payoutId`.              |

### How do i find out the final statuses of these payouts?

As the PawaPay Merchant API is an [asynchronous API](/implementation#asynchronous-api), you can find out the final status of the **accepted** payout by either:

<CardGroup cols={2}>
  <Card title="Waiting for a callback" icon="webhook" href="/v1/api-reference/payouts/payout-callback" horizontal="true">
    If you have configured callbacks, just wait for it.
  </Card>

  <Card title="Checking the status" icon="code-compare" href="/v1/api-reference/payouts/check-payout-status" horizontal="true">
    Or poll the Check Payout Status endpoint.
  </Card>
</CardGroup>

<Info>Headers related to [signatures](/using_the_api#signatures) must only be included if you have enabled “Only accept signed requests”. Read more about it from the [PawaPay Dashboard documentation](/dashboard/other/system_conf/api_tokens#signed-requests).</Info>


## OpenAPI

````yaml openapi_v1 post /payouts/bulk
openapi: 3.0.0
info:
  title: PawaPay Merchant API v1
  description: Please find complete documentation from https://docs.pawapay.io/.
  version: v1
  x-logo:
    url: >-
      https://global-uploads.webflow.com/62824591015aa314fd308df1/6411b26596e3de3f52551c00_Logopawapay-p-500.png
    href: https://docs.pawapay.io/
    altText: PawaPay logo
servers:
  - url: https://api.sandbox.pawapay.io
    description: PawaPay Merchant API sandbox
  - url: https://api.pawapay.io
    description: PawaPay Merchant API production
security:
  - bearerAuth: []
tags:
  - name: payouts
    x-displayName: Payouts
  - name: deposits
    x-displayName: Deposits
  - name: refunds
    x-displayName: Refunds
  - name: payment-page
    x-displayName: Payment Page
  - name: toolkit
    x-displayName: Toolkit
  - name: wallet-balances
    x-displayName: Wallet balances
paths:
  /payouts/bulk:
    post:
      tags:
        - payouts
      summary: Request bulk payout
      operationId: createPayouts
      parameters:
        - in: header
          name: Content-Digest
          schema:
            type: string
            format: string
            description: SHA-256 or SHA-512 hash of the request body.
          required: false
        - in: header
          name: Signature
          schema:
            type: string
            format: string
            description: >-
              Signature of the request according to
              [RFC-9421](https://datatracker.ietf.org/doc/rfc9421/).
          required: false
        - in: header
          name: Signature-Input
          schema:
            type: string
            format: string
            description: >-
              Signature-Input according to
              [RFC-9421](https://datatracker.ietf.org/doc/rfc9421/).
          required: false
        - in: header
          name: Accept-Signature
          schema:
            type: string
            format: string
            description: >-
              Expected signature algorithm of the response according to
              [RFC-9421](https://datatracker.ietf.org/doc/rfc9421/).
          required: false
        - in: header
          name: Accept-Digest
          schema:
            type: string
            format: string
            description: >-
              Expected digest algorithm of the response according to
              [RFC-9421](https://datatracker.ietf.org/doc/rfc9421/).
          required: false
      requestBody:
        $ref: '#/components/requestBodies/BulkPayoutCreationRequest'
      responses:
        '200':
          description: Request has been processed by PawaPay
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PayoutCreationResponse'
              examples:
                Mixed Response:
                  value:
                    - payoutId: f4401bd2-1568-4140-bf2d-eb77d2b2b639
                      status: ACCEPTED
                      created: '2020-10-19T11:17:01Z'
                    - payoutId: f4401bd2-1568-4140-bf2d-eb77d2b2b639
                      status: DUPLICATE_IGNORED
                      created: '2020-10-19T10:22:49Z'
                    - payoutId: f4401bd2-1568-4140-bf2d-eb77d2b2b639
                      status: REJECTED
                      rejectionReason:
                        rejectionCode: AMOUNT_TOO_LARGE
                        rejectionMessage: Amount should not be greater than 1000
        '400':
          description: >-
            Request was rejected due to incompatibility with PawaPay API
            specification
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                Missing Mandatory Field:
                  value:
                    errorId: 4f0d5e13-7e88-4cc6-827c-8c0640dc2cd3
                    errorCode: 1
                    errorMessage: 'Invalid input: Missing required property ''amount'''
        '401':
          description: Authentication Failure. Please check your authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                Authentication Failure:
                  value:
                    errorId: cad1529e-040b-4c9d-a21d-2ba3056ff750
                    errorCode: 2
                    errorMessage: Authentication error
        '403':
          description: Authorization Failure. Please check your authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                Authorization Failure:
                  value:
                    errorId: daa495f0-541d-4192-b636-a8877b25a510
                    errorCode: 3
                    errorMessage: Authorization error
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                System Error:
                  value:
                    errorId: d428a89e-fa8b-42b8-ba20-68be20d50af1
                    errorCode: 0
                    errorMessage: Internal error
components:
  requestBodies:
    BulkPayoutCreationRequest:
      content:
        application/json:
          schema:
            type: array
            items:
              $ref: '#/components/schemas/PayoutCreationRequest'
      required: true
  schemas:
    PayoutCreationResponse:
      required:
        - payoutId
        - status
      type: object
      properties:
        payoutId:
          minLength: 36
          maxLength: 36
          type: string
          format: uuid
          description: The `payoutId` of the payout transaction.
          example: f4401bd2-1568-4140-bf2d-eb77d2b2b639
        status:
          $ref: '#/components/schemas/PayoutCreationStatus'
        created:
          type: string
          description: >-
            The timestamp of when the payout was created in the PawaPay
            platform. Format defined by 'date-time' in RFC3339 section 5.6 from
            [IETF](https://tools.ietf.org/html/rfc3339#section-5.6)
          format: date-time
          example: '2020-02-21T17:32:29Z'
        rejectionReason:
          $ref: '#/components/schemas/PayoutRejectionReason'
    ErrorResponse:
      required:
        - errorId
        - errorCode
        - errorMessage
      type: object
      properties:
        errorId:
          maxLength: 36
          type: string
          description: A unique error ID in the PawaPay platform.
          example: 63743264-7292-11ea-bc55-0242ac130003
        errorCode:
          type: integer
          description: PawaPay internal error code.
          example: 1
        errorMessage:
          type: string
          description: Error message.
          example: Internal error
    PayoutCreationRequest:
      required:
        - payoutId
        - amount
        - currency
        - correspondent
        - recipient
        - customerTimestamp
        - statementDescription
      type: object
      properties:
        payoutId:
          minLength: 36
          maxLength: 36
          type: string
          format: uuid
          description: >-
            A UUIDv4 based ID specified by you, that uniquely identifies the
            payout.
          example: <INSERT_UUID_FOR_PAYOUT>
        amount:
          $ref: '#/components/schemas/Amount'
        currency:
          $ref: '#/components/schemas/Currency'
        country:
          $ref: '#/components/schemas/Country'
        correspondent:
          $ref: '#/components/schemas/Correspondent'
        recipient:
          $ref: '#/components/schemas/FinancialAddress'
        customerTimestamp:
          type: string
          description: >-
            The timestamp for when you initiated the payout process. Format
            defined by 'date-time' in RFC3339 section 5.6 from
            [IETF](https://tools.ietf.org/html/rfc3339#section-5.6)
          format: date-time
          example: '2020-02-21T17:32:28Z'
        statementDescription:
          minLength: 4
          maxLength: 22
          type: string
          pattern: ^[a-zA-Z0-9 ]+$
          description: >
            Short description for the transaction. 

            Depending on the specific MMO performing the transaction this
            message may be visible to the customer in the SMS receipt or within
            their transaction history.


            Must be between **4 and 22 alphanumeric characters**.
          example: Note of 4 to 22 chars
        metadata:
          $ref: '#/components/schemas/TransactionMetadataRequest'
    PayoutCreationStatus:
      type: string
      description: >
        Possible payout initiation statuses: 

        * `ACCEPTED` - The payout request has been **accepted** by PawaPay for
        processing.

        * `ENQUEUED` - The payout request has been **accepted**, but has been
        enqueued for processing later. Read more about [enqueued
        payouts](/payouts#enqueued-payouts).

        * `REJECTED` - The payout request has been **rejected** by PawaPay. See
        rejectionReason for details. 

        * `DUPLICATE_IGNORED` - The payout request has been **ignored** as a
        duplicate of an already accepted payout request. Duplication logic
        relies upon payoutId.
      enum:
        - ACCEPTED
        - ENQUEUED
        - REJECTED
        - DUPLICATE_IGNORED
    PayoutRejectionReason:
      required:
        - rejectionReason
      type: object
      properties:
        rejectionCode:
          type: string
          description: >
            Possible payout rejection codes: 

            * `BALANCE_INSUFFICIENT` - The balance of your PawaPay wallet does
            not have the funds to initiate this payout.

            * `INVALID_CORRESPONDENT` - The specified correspondent is not
            supported.

            * `INVALID_RECIPIENT_FORMAT` - The phone number (MISISDN) specified
            for the recipient is in an unrecognizable format.

            * `INVALID_AMOUNT`- The specified amount is not supported. 

            * `AMOUNT_TOO_SMALL` - The specified amount is smaller than the
            minimum allowed by the MMO specified as the correspondent. 

            * `AMOUNT_TOO_LARGE` - The specified amount is larger than the
            maximum allowed by the MMO specified as the correspondent. 

            * `INVALID_CURRENCY` - The specified currency is not supported by
            the MMO specified as the correspondent. 

            * `INVALID_COUNTRY` - The specified country is not supported for the
            MMO specified as the correspondent. 

            * `PARAMETER_INVALID` - One or more parameters are invalid. 

            * `INVALID_INPUT` - We were unable to parse the payload of the
            request. 

            * `PAYOUTS_NOT_ALLOWED` - Payouts are not allowed for this merchant
            or the MMO specified as the correspondent.

            * `CORRESPONDENT_TEMPORARILY_UNAVAILABLE` - The MMO specified as the
            correspondent is currently experiencing an outage and processing of
            payments has been temporarily halted. Please refer to our [Status
            Page](https://status.pawapay.io) for live information about MMO
            availability.
          example: INVALID_AMOUNT
          enum:
            - BALANCE_INSUFFICIENT
            - INVALID_CORRESPONDENT
            - INVALID_RECIPIENT_FORMAT
            - INVALID_AMOUNT
            - AMOUNT_TOO_SMALL
            - AMOUNT_TOO_LARGE
            - INVALID_CURRENCY
            - INVALID_COUNTRY
            - PARAMETER_INVALID
            - INVALID_INPUT
            - PAYOUTS_NOT_ALLOWED
            - CORRESPONDENT_TEMPORARILY_UNAVAILABLE
        rejectionMessage:
          type: string
          description: Additional optional rejection message
          example: You don't have access to this correspondent (MMO)
    Amount:
      minLength: 1
      maxLength: 23
      type: string
      pattern: ^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$
      description: >
        The amount to be collected (deposit) or disbursed (payout or refund). 


        Amount must follow below requirements or the request will be
        **rejected**:

        * Between zero and two decimal places can be supplied, depending on what
        the specific MMO supports. Learn about all [MMO supported decimal
        places](/using_the_api#correspondents).

        * The minimum and maximum amount depends on the limits of the specific
        MMO. You can find them from the [Active
        Configuration](/v1/api-reference/toolkit/active-configuration) endpoint.

        * Leading zeroes are not permitted except where the value is less than
        1. For any value less than one, one and only one leading zero must be
        supplied.

        * Trailing zeroes are permitted.


        Valid examples:

        `5`, `5.0`, `5.00`, `5.5`, `5.55`, `5555555`, `0.5`


        Not valid examples:

        `5.`, `5.555`, `5555555555555555555`, `.5`, `-5.5`, `00.5`, `00.00`,
        `00001.32`
      example: '15'
    Currency:
      type: string
      description: >
        The currency in which the `amount` is specified.


        Format must be the ISO 4217 three character currency code in upper case.
        Read more from
        [Wikipedia](https://en.wikipedia.org/wiki/ISO_4217#Active_codes).


        You can find all the supported currencies that the specific
        `correspondent` supports [from here](/using_the_api#correspondents).


        The [active
        configuration](/v1/api-reference/toolkit/active-configuration) endpoint
        provides the list of correspondents configured for your account together
        with the currencies.
      example: ZMW
    Country:
      type: string
      description: >
        The country in which the MMO operates. 


        Format is ISO 3166-1 alpha-3, three character country code in upper
        case. Read more from
        [Wikipedia](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3#Officially_assigned_code_elements).
      example: ZMB
    Correspondent:
      type: string
      description: >
        The correspondent code refers to the specific MMO that the specified
        phone number (MSISDN) has an active mobile money wallet with. 


        You can find all the supported correspondents [listed
        here](/using_the_api#correspondents). 


        The [active
        configuration](/v1/api-reference/toolkit/active-configuration) endpoint
        provides the list of correspondents configured for your account.


        You can use the [predict
        correspondent](/v1/api-reference/toolkit/predict-correspondent) enpoint
        to predict the correct correspondent to use based on the phone number
        (MSISDN).
      example: MTN_MOMO_ZMB
    FinancialAddress:
      required:
        - address
        - type
      type: object
      properties:
        type:
          type: string
          description: >-
            The type of financial address. At the moment, only **MSISDN** is
            supported as the financial address. 
          example: MSISDN
          enum:
            - MSISDN
        address:
          $ref: '#/components/schemas/AddressValue'
      description: >-
        The phone number (MSISDN) of the recipient or payer must be specified as
        the `value` of the `address`.
    TransactionMetadataRequest:
      description: >
        A list of metadata that you can attach to the payment for providing
        additional context about the payment.

        For example, adding `orderId` to indicate for which order this payment
        was for or `customerId` to know which customer this payment pertains to.


        Metadata will not be visible to the customer that is party to this
        payment. 

        It will be visible in the PawaPay Dashboard on the payment details page
        and in your financial statements as a JSON object to support automated
        reconciliation.

        It is also possible to search for recent payments in the PawaPay
        Dashboard using global search based on the values of metadata.


        Up to 10 metadata fields can be attached to a payment. 
      type: array
      items:
        $ref: '#/components/schemas/TransactionMetadataRequestItem'
      example:
        - fieldName: orderId
          fieldValue: ORD-123456789
        - fieldName: customerId
          fieldValue: customer@email.com
          isPII: true
    AddressValue:
      required:
        - value
      type: object
      properties:
        value:
          $ref: '#/components/schemas/MsisdnValue'
    TransactionMetadataRequestItem:
      required:
        - fieldName
        - fieldValue
      type: object
      properties:
        fieldName:
          type: string
          description: >-
            The name of the metadata that you are attaching to the payment. For
            example `orderId`.
          example: orderId
        fieldValue:
          type: string
          description: The value for this metadata field. For example `ORD-123456789`.
          example: ORD-123456789
        isPII:
          type: boolean
          default: false
          description: >-
            Indicates whether the field contains personally identifiable
            information. Used for enabling compliance with GDPR or other
            relevant data privacy laws.
          example: true
    MsisdnValue:
      type: string
      description: >
        The phone number (MSISDN) of the payer or recipient.

        The format is described in
        [Wikipedia](https://en.wikipedia.org/wiki/MSISDN). 


        MSISDN validation has following rules:
         * Only digits without whitespaces or any other separators or prefixes like '+'.
         * Should not start with zero.
         * Country code is mandatory.
         * Should not exceed or be less than the valid length of specified country.
         
         Valid examples for Zambia:
         `260763456789`
         
         Not valid examples for Zambia:
         `+260763456789`, `260 763 456789`, `260-7634-56789`, `0260763456789`, `2607634567`, `260763456789543`, `999558708954`, `37255870895`
      example: '260763456789'
  securitySchemes:
    bearerAuth:
      type: http
      description: See [Authentication](/using_the_api#authentication).
      scheme: bearer
      bearerFormat: JWT

````