Bulk Payment step-by-step

Group multiple request on a single payment

📘

Premium feature!

Please if you don’t have access to it, talk to us!

The "Bulk Payment" API provides a payment gateway to fulfill multiple payment requests on a single transaction, automatically sending transactions to multiple recipients (destinations).

1. Configure a Smart Account

The smart account will interact as a proxy between your bank account and the multiple destinations, providing a single interface to complete payments.

To create a smart account go to Create Smart Account, you will be required to provide KYC information such as TaxNumber (CNPJ/CPF), name, email & phone number. We will create a Bank Account, that will be used for all future operations.

📘

Sandbox

We provide a Sandbox account that can be created by providing the isSandbox with true on the payload. In those cases, Bulk Payment will only work with "Mock Bank" our Open Finance Sandbox connector to make Payment Initiation.

An example of the request will be:

curl --location 'https://api.pluggy.ai/payments/smart-accounts' \
--header 'Content-Type: application/json' \
--header 'x-api-key: eyJh...' \
--data-raw '{
    "name": "Your Clients Name",
    "taxNumber": "123123123-12",
    "email": "[email protected]",
    "phoneNumber": "11 941233-3213",
    "address": {
        "city": "São Paulo"
    }
}'

2. Create the recipient for your Payment Request

A recipient is a person or company that will be paid. To create it, the recommended way is to do it using a Pix Key:

curl --location 'https://api.pluggy.ai/payments/recipients' \
--header 'Content-Type: application/json' \
--header 'x-api-key: eyJh.....' \
--data '{
    "pixKey": "my-pix-key"
}'

This will create a recipient with all the information associated to that Pix Key (name, taxNumber, paymentInstitutionId and account)

Also, you can create a recipient sending each field separately:

curl --location 'https://api.pluggy.ai/payments/recipients' \
--header 'Content-Type: application/json' \
--header 'x-api-key: eyJh.....' \
--data '{
    "name": "Nicolas Canuto Cernadas",
    "taxNumber": "321321321-22",
    "paymentInstitutionId": "c73b674a-08fa-4c6a-9535-16d6c03c08a6",
    "account": {
        "type": "CHECKING_ACCOUNT",
        "number": "3321332",
        "branch": "4212"
    }
}'

You can get the institutionId from: https://docs.pluggy.ai/reference/payment-recipients-institution-list

And know more about Recipients https://docs.pluggy.ai/reference/payment-recipient

curl --request POST \
     --url https://api.pluggy.ai/payments/requests/pix-qr \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "pixQrCode": "00020126490014br.gov.bcb.pix0108dict-key0215additional-info52040000530398654031005802BR5912example-name6006Cidade62090505tx-id63045E20"
}
'

3. Create Payment Requests

Create each payment that you want to include in the bulk payment, each payment can have the same or different PaymentRecipient that will be the final destination of the transfer.

To create a payment request you will be required to provide:

  • An amount
  • A description
  • A recipient, the final destination of the transaction.

Note: the recipientId is the ID of the 2nd step.

For more information review how to make a single payment request and the payment request API reference.

Additionally, you can create a payment request directly from a boleto or a PIX QR (without a recipient).

Payment Requests from boleto

curl --request POST \
     --url https://api.pluggy.ai/payments/requests/boleto \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "boletoDigitableLine": "27490.00101.10000.000116.60070.701507.2.970 1 0000002820"
}
'

Payment Requests from PIX QR

curl --request POST \
     --url https://api.pluggy.ai/payments/requests/pix-qr \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "pixQrCode": "00020126490014br.gov.bcb.pix0108dict-key0215additional-info52040000530398654031005802BR5912example-name6006Cidade62090505tx-id63045E20"
}
'

4. Create the Bulk Payment

Pick the paymentRequestId of each request created on the previous step and with the smart account, create a bulk payment.

Bulk payment requests can't be changed, so if there is a mistake on the request to complete, the bulk payment must be canceled and all the Payment Request will be deleted too

{
  "smartAccountId": "633ea66f-7599-4afe-8016-57cc3765fe00",
  "paymentRequestIds": [
    "04038a3e-d007-4bea-bae9-f808152ba672"
  ]
}

This will generate a bulk payment that can be paid through our Bulk Payment gateway using the paymentUrl provided on the response, sending it to the user to fulfill the payment.

{
  "id": "633ea66f-7599-4afe-8016-57cc3765fe00",
  "paymentUrl": "https://pay.pluggy.ai/bulk/633ea66f-7599-4afe-8016-57cc3765fe00"
}

For more information about the bulk payment API, visit the API Reference.

Send the bulk to the payer.

It will see the following screen:

Here your user will be able to select if he want to pay with PIX QR or PIS


After paying, your user will see all his payments being processed and you will receive each payment via webhook.


(OPTIONAL) 4. Pay the Bulk Payment through an intent

If you are not using Pluggy's Bulk Payment Gateway app, you can go through API.

A bulk payment can be settled using Payment Initiation (PIS) or paying a PIX QR directly in your bank.

  • Payment Initiation
    Paying the bulk payment request is the same as paying a single payment request. You need to create a PaymentIntent for a bulkPaymentId, providing the connectorId of the bank that will send the money and the payer's information.

    {
        "bulkPaymentId": "633ea66f-7599-4afe-8016-57cc3765fe00",
        "connectorId": 600,
        "parameters": {"cpf": "76109277673"},
        "paymentMethod": "PIS"
    }
    

  • PIX QR
    In this case, you need to create a PaymentIntent for a bulkPaymentId, providing the paymentMethod PIX.

    {
        "bulkPaymentId": "633ea66f-7599-4afe-8016-57cc3765fe00",
        "paymentMethod": "PIX"
    }
    
    This will return a property pixData in the response, with the PIX QR code in base64 format and the raw pix qr value to paste if it's needed.

    {
        "id": "bb37b8b3-0016-4d18-84bb-96a8d4405c3e",
        "status": "PAYMENT_PENDING",
        "createdAt": "2024-04-03T19:14:07.448Z",
        "updatedAt": "2024-04-03T19:14:07.448Z",
        "paymentRequest": null,
        "bulkPayment": {
            "id": "ce5bc603-9934-4b7c-af72-9c9dcba39325",
            "status": "TOP_UP_STARTED",
            "referenceId": null,
            "createdAt": "2024-04-03T19:13:59.112Z",
            "updatedAt": "2024-04-03T19:14:07.533Z",
            "totalAmount": 1.1,
            "feesAmount": 1,
            "grossAmount": 0.1
        },
        "connector": null,
        "consentUrl": null,
        "referenceId": null,
        "pixData": {
            "value": "00020126580014br.gov.bcb.pix013652259804-9ae4-40f7-bee7-df0c2a94dea352040000530398654041.105802BR5915NICOLAS MONTONE6009SAO PAULO62290525pdf99d439b99c1eedbe720c7263040637",
            "qr": "data:image/png;base64,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"
        },
        "paymentMethod": "PIX"
    }
    

Check bulk payment statuses and details

Once the payment has been completed, the Bulk Payment will change to TOP_UP_IN_PROGRESS waiting for the confirmation that the payment has been received on our SmartAccount.

Once the money has been received, transfers to all the different payment request recipients will start and bulk payment will change to PAYMENTS_IN_PROGRESS. You can check the Bulk Payment's status through our API, which will detail as well the status of each payment request to validate which ones are completed and which ones are still in progress.

{
    "id": "d81b2280-a825-4ef5-acc8-221da3512a07",
    "status": "PAYMENTS_IN_PROGRESS",
    "paymentRequests": [
        {
            "id": "30197dc2-dfa1-408d-b56a-54cc0e6796e7",
            "amount": 0.01,
            "description": "My first payment request",
            "status": "COMPLETED"
          	...
        },
        {
            "id": "6f8f7db9-288c-469d-81c9-cbb98459d9c9",
            "amount": 0.01,
            "description": "My Second payment request",
            "status": "IN_PROGRESS"
            ...
        }
    ],
    ...
}

Doing your a Bulk Payment with Sandbox


  1. First create a Sandbox Smart Account
    { "name": "My Test Sandbox Account", "taxNumber": "111111111-11", "email": "[email protected]", "phoneNumber": "1111111111", "isSandbox": true }
  2. Create some PaymentRequest, the sum of all requests including fees should sum up 1333.33
    For example:
    #1
    { "amount": 1001.33, "description": "Transferência #1", "recipientId": "207b7c20-758e-441f-8a5a-be339ced22f5" }
    #2
    { "amount": 330, "description": "Transferência #2", "recipientId": "207b7c20-758e-441f-8a5a-be339ced22f5" }
  3. Create the Bulk Payment using those requests and the sandbox account generated before.
    The bulk payment returned will contain a URL param to provide the sandbox connector
    https://pay.pluggy.ai/bulk/dfae651e-ab52-4a00-9a59-0a85458a8d09?include_sandbox=true


Refunds

if a payment fails, it will be refunded to the debtor account. For example, if you have a bulk payment with 2 payment requests and one fails, this will be the scenario:

{
    "id": "e6b6974b-e790-4dae-9826-c26e30e2cb5e",
    "status": "PARTIALLY_COMPLETED",
    "totalAmount": 302,
    "feesAmount": 2,
    "grossAmount": 200,
    "paymentRequests": [
        {
            "id": "6ab34b81-625a-43ae-a1c6-aafa790aecb5",
            "amount": 200,
            "description": "Payment with error",
            "status": "REFUNDED",
            "createdAt": "2024-06-14T14:44:07.059Z",
            "updatedAt": "2024-06-14T14:45:53.096Z",
            "callbackUrls": null,
            "bulkPaymentId": null,
            "recipient": null,
            "clientPaymentId": null,
            "customer": null,
            "fees": 1,
            "pixQrCode": null,
            "boleto": null,
            "smartAccount": null,
            "schedule": null
        },
        {
            "id": "1709feb4-3658-4685-97b3-cb3b87343ef8",
            "amount": 100,
            "description": "Payment success",
            "status": "COMPLETED",
            "createdAt": "2024-06-14T14:44:47.294Z",
            "updatedAt": "2024-06-14T14:45:46.932Z",
            "callbackUrls": null,
            "bulkPaymentId": null,
            "recipient": null,
            "clientPaymentId": null,
            "customer": null,
            "fees": 1,
            "pixQrCode": null,
            "boleto": null,
            "smartAccount": null,
            "schedule": null
        }
    ]
}

In this case, the first payment request will be refunded (amount + fees), in this case by R$202.