How to create a mass payout via API

General API integration rules

Before starting an integration please check our General API integration rules page for more info.

Get balance information via API

Before creating payouts you will probably want to check whether you have enough funds on your wallets or not. To do this please check our Get balance information via API page for more info.

Mass payout API integration

Mass Payout is a method of paying multiple recipients simultaneously. Since mass payouts are submitted online, they are processed instantly which helps organizations to save time, money and resources.

To send many payments with fixed amount in cryptocurrency you can use mass payout functionality. To make payments you just need to know receiver addresses and specify amount and currency of payments.

Mass payouts are profitable if you are going to send more than 5 payments. Otherwise, use single payouts, it will be cheaper.

Currently, there is a limit for quantity of transactions in one mass payout:

1000 transactions for ETH and tokens ERC-20;
100 transactions for other currencies.

Payment sent by mass payout must be sent from one address in one currency but can has any amount of receiver addresses.

You can find more information about other features of Public API integration in our documentation: Mass payout

Create mass payout

To create a new mass payout use the following endpoint: New Mass Payout (POST <<baseUrl2>>/api/v1/payout/mass/create).

You can find the detailed description of all the parameters in the documentation:

New Mass Payout

Here we consider the most important ones.

  • currency - the crypto currency of payment. Calypso supports the following currencies:
    • Bitcoin blockchain: BTC
    • Ethereum blockchain: ETH, USDT, FRAX, BUSD_ETH, USDC, DAI
    • Tron blockchain: TRX, USDT_TRX
    • Binance Smart Chain blockchain: BNB, BUSD
    • Polygon blockchain: MATIC, USDT_MATIC
    • Doge blockchain: XDG
  • name - the name of payment.
  • comment - some information about payment.
  • idempotencyKey - a specific UUID for the payout which guarantees uniqueness of the request. It’s possible to check the status of the payout by this parameter after creation.
  • massAddresses - object with data for each payment.
    • depositAddress - address of the receiver of payment. Pay attention to specify address in the correct blockchain network.
    • amount - amount of the payment.

So to create mass payout without additional options you just have to send request:

curl --location --request POST '<<baseUrl2>>/api/v1/pub/payout/mass/create' \
--header 'key: <your_api_key>' \
--header 'sign: <your_sign>' \
--header 'Content-Type: application/json' \
--data-raw '{
  "timestamp": 13292792792,
  "account": "0xc195df92dd9db2a8f28e597981f113d6e7582f8b",
  "payload": {
    "currency": "USDT",
    "name": "salary for employees",
    "comment": "October",
    "massAddresses": [
      {
        "depositAddress": "0x3b2d03a4e60c9e0fa45f45a544d137bda2014f0f",
        "amount": 10
      },
      {
        "depositAddress": "0x40b70f0eee9a1605ef28ac6914f34d3bc80e15ca",
        "amount": 10
      }
    ],
    "idempotencyKey": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }
}'

Some additional options:

  • You can set time of the payout processing by transmitting executionDate field in request body. The payout will be sent on specified date and time.
  • You can set a specific custom ID for each payment by transmitting externalId field in the object massAddresses. It’s possible to get the information about payments with the same externalId via api or webhooks.

If the creation was successful you receive the response:

  • Response example
    {
        "id": "b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a",
        "idempotencyKey": "e8aed201-ed80-4a14-90a6-dd6ba328391b",
        "companyId": "811b0401-c9f9-4b40-be68-3b01eb1d61f6",
        "state": "CREATION_IN_PROGRESS",
        "comment": "October",
        "name": "salary for employees",
        "currency": "USDT",
        "totalCalypsoFee": 1,
        "totalCalypsoFeePercentage": 10
    }
    

After that you can track state changes until payout will be completed.

Tracking mass payout state

After creating mass payout you can receive information about it from the system. There are three options to track changes in mass payout state:

  1. Get data about payout state via request by ID.
  2. Get data about all or specific payments via request by payout ID or externalId.
  3. Set webhooks for payouts.

Get data about payout state

To receive information about earlier created payout you can use Get Specific Mass Payout endpoint (POST <<baseUrl2>>/api/v1/payout/mass).

You can request payout by id or idempotencyKey.

More info on Get Specific Mass Payout endpoint: Get specific Mass Payout

Example of the request by id:

curl --silent --location --request POST "<<baseUrl2>>/api/v1/payout/mass" \
--header 'Key: <your_api_key>' \
--header 'Sign: <your_sign>' \
--header "Content-Type: application/json" \
--data-raw "{
  "timestamp": 13292792792,
  "account": "0xc195df92dd9db2a8f28e597981f113d6e7582f8b",
  "payload": {
    "id": "b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a"
  }
}"

In response you will receive payout data:

  • Response example
    {
        "id": "b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a",
        "idempotencyKey": "e8aed201-ed80-4a14-90a6-dd6ba328391b",
        "companyId": "811b0401-c9f9-4b40-be68-3b01eb1d61f6",
        "state": "CREATION_IN_PROGRESS",
        "comment": "October",
        "name": "salary for employees",
        "currency": "USDT",
        "totalCalypsoFee": 1,
        "totalCalypsoFeePercentage": 10
    }
    

The most important fields you need to pay attention to:

  • state - represents status of the payout. More info about possible states in documentation: Mass payout
  • totalCalypsoFee - service fee you paid for payout.

Using this approach you can track only general state of all payments. So, the general state of mass payout is set by the following rules:

  1. If there is no payment (withdrawal) in state IN_PROGRESS and at least one payment (withdrawal) in state COMPLETED, the state of payout will be COMPLETED.
  2. If there is no payment (withdrawal) in state IN_PROGRESS, COMPLETED and at least one payment (withdrawal) is in state FAILED, the state of payout will be FAILED.
  3. If there is no payment (withdrawal) in state IN_PROGRESS, COMPLETED, FAILED and at least one payment (withdrawal) is in state CANCELED, the state of payout will be CANCELED.

If you want tracking state of the particular payment (withdrawal) use the next approach.

Get data about payments

Pay attention that payments for payout are being created asynchronously, thus, before all payments will be created it may take some time after payout creation.

To receive information about payments (withdrawals) you can use Get Transactions From a Specific Mass Payout endpoint (POST <<baseUrl2>>/api/v1/payout/withdrawal/all).

You can request payments by dealId (payout ID) or idempotencyKey. Then you will get all payments for this payout. Or you can request payments by externalId. Then you will get all payments with this externalId. If you specify dealId (or idempotencyKey) and externalId together only payments for the specified payout will be selected, otherwise, all payments with tis externalId.

Also you must specify states of payments you want to get. To get all payments specify the field stateNames by value: [ "DRAFT", "IN_PROGRESS", "COMPLETED", "REPLACED", "FAILED" ].

More info on Get Transactions From a Specific Mass Payout endpoint: Get Transactions from a specific Mass Payout

Example of the request by dealid:

curl --location --request POST '<<baseUrl2>>/api/v1/payout/withdrawal/find' \
--header 'key: <your_api_key>' \
--header 'sign: <your_sign>' \
--header 'Content-Type: application/json' \
--data-raw '{
  "timestamp": 13292792792,
  "account": "0xc195df92dd9db2a8f28e597981f113d6e7582f8b",
  "payload": {
    "dealId": "b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a",
    "stateNames": [
      "DRAFT", "IN_PROGRESS", "COMPLETED", "FAILED", "CANCELED"
    ]
  }
}'

In response you will receive payments data:

  • Response example
    {
        "result": [
            {
                "id": "75867d4d-764c-4dd2-94a5-3e07a41c22ea",
                "account": "0xc195df92dd9db2a8f28e597981f113d6e7582f8b",
                "companyName": "My Company",
                "amount": 10,
                "currency": "USDT",
                "state": "IN_PROGRESS",
                "calypsoFee": 1,
                "transactionHash": "0x36cc4892b491f09a88bc4f073c9d1ba05491feba21cbca820e15cb27408fd1f6",
                "depositAddress": "0x3b2d03a4e60c9e0fa45f45a544d137bda2014f0f",
                "createdDate": "2022-10-13T07:42:52.670568",
                "withdrawalErrors": []
            },
            {
                "id": "0328f0a2-e26d-4168-b803-375c06dc723b",
                "account": "0xc195df92dd9db2a8f28e597981f113d6e7582f8b",
                "companyName": "My Company",
                "amount": 10,
                "currency": "USDT",
                "state": "IN_PROGRESS",
                "calypsoFee": 1,
                "transactionHash": "0x36cc4892b491f09a88bc4f073c9d1ba05491feba21cbca820e15cb27408fd1f6",
                "depositAddress": "0x40b70f0eee9a1605ef28ac6914f34d3bc80e15ca",
                "createdDate": "2022-10-13T07:42:52.670568",
                "withdrawalErrors": []
            }
        ],
        "page": 1,
        "size": 10,
        "total": 1,
        "totalElements": 0
    }
    

The most important fields you need to pay attention to:

  • state - represents status of the payment. Possible statuses: [ "DRAFT", "IN_PROGRESS", "COMPLETED", "REPLACED", "FAILED" ]. "COMPLETED", "REPLACED", "FAILED" are terminal statuses.
  • calypsoFee - service fee you paid for each transaction.
  • withdrawalErrors - if this field is filled, then the error occurred during payment processing. Here you can find details about the error.

Receive information about mass payout state via Webhooks

To track state of your created mass Payout you can use Calypso Payment functionality which is called Webhooks.

Webhook is a way for an app to provide other applications with real-time information.
The Webhooks API allows you to subscribe to events happening with your created objects (Invoices or Payouts) in Calypso. Rather than making an API call to check status of invoice or payout during processing, Calypso can send an HTTP request to an endpoint you configure.

More detailed information about Calypso Webhooks functionality: Webhooks

  1. First of all, to receive information about mass Payout state change you need to create a subscription for system events which you want to track.

There are several types of events which you need to track in order to understand what is happening to your Invoices.

The main events are:

Event typeDescription
PAYOUT_CHANGE_STATUSPayout has changed state to In Progress, Canceled, Failed or Completed
PAYOUT_VALIDATION_ERRORValidation error has been occurred during payout processing

More info on Calypso Webhooks event types: Types of events

We’ll look at more scenarios of using Webhooks in following scenarios.

To create a subscription for those events you can use the Create Webhook Public API endpoint: POST <<baseUrl2>>/api/v1/subscription/webhook/create

curl --location --request POST '<<baseUrl2>>/api/v1/pub/subscription/webhook/create' \
--header 'Key: <your_api_key>' \
--header 'Sign: <your_sign>' \
--header 'Content-Type: application/json' \
--data-raw '{
  "timestamp": 13292792792,
  "account": "0xc195df92dd9db2a8f28e597981f113d6e7582f8b",
  "payload": {
    "notificationEventTypes": [
      "PAYOUT_CHANGE_STATUS",
			"PAYOUT_VALIDATION_ERROR"
    ],
    "requestId": "bf9348b7-2c14-46d7-868c-b597852da319",
    "url": "Your App URL"
  }
}'

You can subscribe to all types of events if you specify value “PAYOUT” in the notificationServiceTypes field instead of enumeration all types of events in notificationEventTypes.

In the response you will get:

{
    "requestId": "bf9348b7-2c14-46d7-868c-b597852da319",
    "notificationEventTypes": [
      "PAYOUT_CHANGE_STATUS",
			"PAYOUT_VALIDATION_ERROR"
    ],
    "url": "Your App URL",
    "createdDate": "2022-08-22T08:24:00.307535"
}

More info on Webhooks management in Calypso Pay system: Webhook API

  1. After successful creation of subscription for payout state changes you should wait while the payout is processing.

Successful Mass Payout scenario

If mass payout was processed you will receive webhook with type PAYOUT_CHANGE_STATUS where the field payoutStatus will be COMPLETED.

  • The example of webhook payload:
    {
      "requestId": "bf9348b7-2c14-46d7-868c-b597852da319",
    	"id":74146,
    	"createdDate":"2022-10-10T11:54:52.191723",
    	"level":"SUCCESS",
    	"service":"PAYOUT",
    	"data": {
    			"hash":null,
    			"type":"PAYOUT_CHANGE_STATUS",
    			"currency":"USDT",
    			"createdDate":"2022-10-06T15:54:23.925926",
    			"payoutStatus":"COMPLETED",
    			"idempotencyKey":"e318f10d-d470-4605-898f-680be65a5380",
    			"parentExternalId":"b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a"
    	}
    }
    

The mass payout is processed successfully if all its payments have state COMPLETED.

To check state of payments you can use Get Transactions From a Specific Mass Payout endpoint (POST <<baseUrl2>>/api/v1/payout/withdrawal/all) using idempotencyKey or dealId (id in request).

The value of the field state of all payments in result must be COMPLETED.

Negative Mass Payout scenario

If payout was finished due to the error you will receive webhook one of the following type:

  1. PAYOUT_VALIDATION_ERROR - payout remains in state IN_PROGRESS, validation error occurred.
  2. PAYOUT_CHANGE_STATUS where the field payoutStatus will be FAILED - all payments were failed.
  3. PAYOUT_CHANGE_STATUS where the field payoutStatus will be COMPLETED - part of payments were failed, others were completed.
  • The example of webhook payload with type PAYOUT_VALIDATION_ERROR
    {
      "requestId": "fef8b8b9-cfee-4ccf-b0f1-c824f6eabb94",
      "id": 78418,
      "createdDate": "2022-10-13T10:24:42.187272",
      "level": "WARNING",
      "service": "PAYOUT",
      "eventType": "PAYOUT_VALIDATION_ERROR",
      "data": {
        "type": "PAYOUT_VALIDATION_ERROR",
        "message": "Not enough funds for processing payout by wallet. \nExpected network fee: 0.00018113 BTC.\nPayout amount: 0.01001 BTC.\nAvailable wallet balance by wallet: 0.00025000 BTC.\nYou need more: 0.00994113 BTC.\nPlease top up your BTC wallet: tb1qde9x2fvr7hv8a85yxfu0enrp5p598ljvj6vtrt.",
        "currency": "BTC",
        "externalId": null,
        "createdDate": "2022-10-13T10:24:36.409095",
        "idempotencyKey": "81a86936-ca95-4991-b824-ef1ee12f65f3",
        "dealWithdrawalId": "75867d4d-764c-4dd2-94a5-3e07a41c22ea",
        "parentExternalId": "b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a",
        "validationStatus": "NOT_ENOUGH_FUNDS"
      }
    }
    
  • The example of webhook payload with type PAYOUT_CHANGE_STATUS (payoutStatus = FAILED)
    {
      "requestId": "bf9348b7-2c14-46d7-868c-b597852da319",
    	"id":74146,
    	"createdDate":"2022-10-10T11:54:52.191723",
    	"level":"WARNING",
    	"service":"PAYOUT",
    	"data": {
    			"hash":null,
    			"type":"PAYOUT_CHANGE_STATUS",
    			"currency":"ETH",
    			"createdDate":"2022-10-06T15:54:23.925926",
    			"payoutStatus":"FAILED",
    			"idempotencyKey":"e318f10d-d470-4605-898f-680be65a5380",
    			"parentExternalId":"b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a"
    	}
    }
    
  • The example of webhook payload with type PAYOUT_CHANGE_STATUS (payoutStatus = COMPLETED)
    {
      "requestId": "bf9348b7-2c14-46d7-868c-b597852da319",
    	"id":74146,
    	"createdDate":"2022-10-10T11:54:52.191723",
    	"level":"SUCCESS",
    	"service":"PAYOUT",
    	"data": {
    			"hash":null,
    			"type":"PAYOUT_CHANGE_STATUS",
    			"currency":"USDT",
    			"createdDate":"2022-10-06T15:54:23.925926",
    			"payoutStatus":"COMPLETED",
    			"idempotencyKey":"e318f10d-d470-4605-898f-680be65a5380",
    			"parentExternalId":"b5d7778c-6cf2-43fa-86eb-c5efbb89cb0a"
    	}
    }
    

The mass payout can have state COMPLETED but some payments could finish with errors. So, you need to check state of all payments to know where an error occurred.

To check state of payments you can use Get Transactions From a Specific Mass Payout endpoint (POST <<baseUrl2>>/api/v1/payout/withdrawal/all) using idempotencyKey or dealId (id in request).

If payment state is FAILED that means that the error occurred on the side of Calypso system. You should resend this payment or ask our technical support about the problem.

If the payment is not in terminal status but you catch PAYOUT_VALIDATION_ERROR then you should check withdrawalErrors field.

This object includes the following parameters:

id - the ID of the error. It’s needed for error searching by technical support.

status - the reason of the error. Can be: [ EXCEEDING_LIMIT, NOT_ENOUGH_FUNDS, NOT_ENOUGH_FUNDS _FOR_COMMISSION ]

errorResolved - if false, then this validation error was not resolved. If true, this validation error was resolved and not relevant anymore.

errorMessage - detailed information about error.

  • Example of withdrawalErrors field
"withdrawalErrors": [
                {
                    "id": "75867d4d-764c-4dd2-94a5-3e07a41c22ea",
                    "status": "NOT_ENOUGH_FUNDS",
                    "errorResolved": false,
                    "errorMessage": "Not enough funds for processing payout by wallet. \nPayout amount: 4010.00 USDT.\nAvailable wallet balance by wallet: 52.57 USDT.\nYou need more: 3957.43USDT.\nPlease top up your USDT wallet: 0xa04dfcfb734f8c3c94497fa269c47331f14a70c9."
                }
            ]