Skip to main content

Send Bank Account Payouts

This guide sends a payout to a bank account over the ACH network or real-time payment rails.

You need a saved bank account for this guide. Save one with Save Bank Accounts, from your web app or from your servers. Either way you get a bank account id that starts with ba_.

You can also skip saving the bank account and send its details in the payout request. See Create with Bank Account Details.

Before you start​

Credova account
Sign up or sign in to the Credova Portal.
Secret Key
Authenticates requests from your server. Never send it to the browser.

Payout Types​

Payouts made to a bank account travel over the ACH network and support three speeds, set via the payout_type field on Create Payout:

  • standard (default) — A standard ACH transfer. Settles over the standard multi-day ACH timeline.
  • same_day — A same-day ACH transfer. Settles the same business day.
  • instant — Sent over real-time payment rails instead of ACH batch processing, and typically settles within minutes. Requires the payouts:instant account setting to be enabled — see Request Account Setting Access below.

Process the Payout​

We will use a saved bank account to create a new payout. A verified bank account is the more reliable choice if you plan to send an instant payout. See Instant Verification.

For example, given this saved bank account:

{
"id": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "test",
"customer_id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "checking",
"routing_number": "110000000",
"account_number_last4": "1011",
"billing_details": {
"address_line_1": "111 Colorado Ave.",
"address_line_2": "Apt 403",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
},
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z"
}

Request Account Setting Access​

This section only applies if you plan to use instant payouts. Skip it if you're using the default standard or same_day payout types.

To use instant payouts, you will need to request access to the payouts:instant account setting type.

To do this, go to the merchant portal and click on the Request this feature button next to the Instant Payouts setting. Alternatively, you can request access via the API.

Create a Payout​

We need to make a call to Create Payout endpoint. Omitting payout_type defaults to standard:

Create a Payout
curl 'https://api.publicsquare.com/payouts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "USD",
"payment_method": {
"bank_account": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
},
"customer": {
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'

The amount is in cents. 1000 is $10.00.

The IDEMPOTENCY-KEY header can be passed to protect against duplicate payouts being processed.

Create with Bank Account Details​

If you have not saved the bank account yet, you can send its details with the payout. The API saves the bank account and sends the payout in the same request, so you do not need to call Create Bank Account first.

Before you use bank_account_details:

  • Your account must have the payment-methods:bank-accounts:manual-creation account setting. See Request Account Setting Access.
  • A restricted API key must have the payment-method:write permission in addition to payout:write. Secret keys have all permissions.
Create a Payout with Bank Account Details
curl 'https://api.publicsquare.com/payouts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "USD",
"payment_method": {
"bank_account_details": {
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "checking",
"routing_number": "110000000",
"account_number": "000123456789"
}
},
"customer": {
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'
  • bank_account_details accepts the same fields as Create Bank Account.
  • Include account_holder_name and account_holder_type. Some processors require them.
  • You cannot combine bank_account_details with bank_account or card.
  • If you omit the top-level customer or billing_details, the payout uses the customer_id and billing_details inside bank_account_details.
  • Every payout_type works with bank_account_details, with the same requirements as a saved bank account.
  • The response returns the saved bank account in payment_method.bank_account. Use its id as bank_account for later payouts.

Send an IDEMPOTENCY-KEY with each request. If a request fails and you retry it with the same key, the payout uses the bank account that the first request saved. A retry with the same key and different bank account details returns a 400. Use a new key when you change the bank account details.

Retry with different bank account details
{
"title": "Error",
"status": 400,
"detail": "'bank_account_details' differs from the request first sent with this IDEMPOTENCY-KEY."
}

Create a Same-Day or Instant Payout​

To use a faster payout type, set payout_type to same_day or instant:

Create an Instant Payout
curl 'https://api.publicsquare.com/payouts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "USD",
"payout_type": "instant",
"payment_method": {
"bank_account": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
},
"customer": {
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'
If the payouts:instant account setting has not been enabled for your account, an instant payout request will fail. See Request Account Setting Access above. same_day payouts require no additional account setup.

Create with Existing Customer​

If you created a customer, then you can pass its ID as customer.id when processing the payout:

Create a Payout with Customer
curl 'https://api.publicsquare.com/payouts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "USD",
"payment_method": {
"bank_account": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
},
"customer": {
"id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'

Create with Customer's Payment Method​

If you attached the bank account to a customer, then you can omit the customer section when processing the payout:

Create a Payout with Payment Method
curl 'https://api.publicsquare.com/payouts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "USD",
"payment_method": {
"bank_account": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'

Create with Payment Method's Billing Details​

If you supplied the billing_details or updated the bank account, then you can omit the billing_details section when processing the payout:

Create a Payout with Payment Method
curl 'https://api.publicsquare.com/payouts' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: 09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "USD",
"payment_method": {
"bank_account": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ"
}
}'

Each of these request variants works the same way for same_day and instant payouts — just add the corresponding payout_type to the request body.

Payout Response​

Given the bank account payout examples, you should see a payout result similar to:

{
"id": "pyt_24NFPd3jSZFTxiaH9UwjuqNdP",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "test",
"status": "pending",
"payout_type": "instant",
"transaction_id": "trx_6QgmXzQzk3S5K5EsR3DfEiMRj",
"amount": 1000,
"currency": "USD",
"payment_method": {
"bank_account": {
"id": "ba_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"status": "verified",
"account_holder_name": "John Doe",
"account_holder_type": "individual",
"account_type": "individual",
"routing_number": "123456789",
"account_number_last4": "1011"
}
},
"customer": {
"id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com",
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
},
"transaction": {
"id": "trx_6QgmXzQzk3S5K5EsR3DfEiMRj",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "test",
"status": "pending",
"amount": -1000,
"fee_amount": 0,
"net_amount": -1000,
"currency": "USD",
"type_id": "pyt_24NFPd3jSZFTxiaH9UwjuqNdP",
"type": "payout",
"processor": "nuvei",
"processor_id": "7110000000010554769",
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z"
},
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z"
}

The payout's status is pending immediately after creation, and the response's payout_type reflects the speed you requested. For instant payouts, the terminal succeeded or declined status typically arrives via the payout:update webhook much sooner than standard or same_day payouts.

Handling Declines​

If a payout is declined, the response's declined_reason will contain the reason available at the time of the decline. When the receiving bank returns the payout, declined_reason contains the ACH return code and its description, for example R03 - No Account/Unable to Locate Account. The linked bank account's status may also change as a result of the decline. See Bank Accounts.

Conclusion​

Now that we have sent a payout to a bank account, we may need to cancel it or view information about it. Follow these guides to learn more: