HomeGuidesRecipesAPI ExplorerForumSupport
Partner Portal
Partner Portal

Make ACH payments

Overview

US-based entities can use the Automated Clearing House (ACH) network to pay their payables, either individually or in bulk. This guide is for Monite partners who want to implement the ACH payment functionality for their entities.

📘

All API calls mentioned in this guide require a partner access token.

Implementing ACH payments

Implementing ACH payments includes the following steps:

  1. Enable the ACH payment method for an entity and onboard this entity.
  2. The entity needs to verify the ownership of its US bank account.
  3. After successful onboarding and verification, the entity can make ACH payments.

Requirements

This guide assumes that:

Requirements for counterparts:

  • The address specified by default_billing_address_id must have all fields filled in, including optional fields. Optional fields with no value should be stored as empty strings instead of null.
  • If default_billing_address_id is not specified, the counterpart's default address is instead used as the billing address. This default address must have all fields filled in.

Additionally, each counterpart's bank account that will be specified in batch payment request must have these fields filled in:

  • account_holder_name
  • account_number
  • routing_number

1. Subscribe to the webhooks

To get notified about the status updates of payments made by entities, you need to subscribe to these webhooks:

  • batch_payment.status_updated - notifies about status transitions of a batch payment as a whole;
  • payment_intent.status_updated - notifies about status transitions of individual payment intents within the batch payment.

2. Create an ACH payment

To create an ACH payment on behalf of an entity, call POST /batch_payments and provide information about the payables that the entity wants to pay and the entity's bank account to withdraw funds from. A single request can include one or more payables.

📘

The specified payables must be in the waiting_to_be_paid status.

curl -X POST 'https://api.sandbox.monite.com/v1/batch_payments' \
     -H 'X-Monite-Version: 2024-01-31' \
     -H 'X-Monite-Entity-Id: ENTITY_ID' \
     -H 'Authorization: Bearer YOUR_PARTNER_TOKEN' \
     -H 'Content-Type: application/json' \
     -d '{
           "payment_method": "us_ach",
           "payer_bank_account_id": "<<ID of the entitys bank account>>",
           "payment_intents": [
             {
               "object": {
                 "type": "payable",
                 "id": "<<ID of the payable>>"
               },
               "recipient": {
                 "type": "counterpart",
                 "id": "<<ID of the counterpart>>"
                 "bank_account_id": "<<ID of the counterparts bank account>>"
               }
             },
                
             // other payments
             ...
           ]
         }'
Explanation of the request fields

The request fields are:

  • payment_method - must be "us_ach".
  • payer_bank_account_id - the ID of the entity's US bank account to withdraw the funds from. This bank account must be verified.
  • payment_intents - an array containing information about the payables that the entity wants to pay. Each payable's currency must be USD.
    • object.type - must be "payable".
    • object.id - the ID of a payable to pay.
    • recipient - this object needs to be provided only if the specified payable does not contain information about the counterpart. Otherwise, recipient can be omitted. The counterpart must be US-based.
      • recipient.type - must be "counterpart".
      • recipient.id - counterpart ID.
      • recipient.bank_account_id - the ID of the counterpart's bank account to which the payment is to be made.

The POST /batch_payments endpoint creates one payment intent per each payable specified in the request's payment_intents list. A list of the created intents is returned in the payment_intents field of the created batch payment. Each payment intent specifies the amount to be paid (taken from the payable object's data), and the total amount of all payments are returned in the total_amount field.

{
  "id": "560c8683-2c77-4dbe-b36c-ce27e28ca4bc",
  "created_at": "2023-10-02T08:30:00.837Z",
  "status": "pending",
  "payment_method": "us_ach",
  "payer_bank_account_id": "<<ID of the entitys bank account>>",

  "total_amount": 1000,
  "fee_amount": 20,

  "error": null,
  "payment_intents": [
    {
      "id": "254fbb5f-6c82-42ee-a0f0-dc83138aacca",
      "created_at": "2023-10-02T08:30:00.837Z",
      "amount": 1000,
      "currency": "USD",
      "status": "created",
      "error": null,
      "object": {
        "type": "payable",
        "id": "<<ID of the payable>>"
      },
      "recipient": {
        "type": "counterpart",
        "id": "<<ID of the counterpart>>",
        "bank_account_id": "<<ID of the counterparts bank account>>"
      }
    },

    // other payments intents
    ...
  ]
}

3. Track the payment status

Batch payment statuses

A batch payment goes through several statuses, some of which also reflect the statuses of the individual payment intents within this batch payment.

Overview of batch payment lifecycle.

The lifecycle of a batch payment.

StatusDescription
createdThe initial status of a batch payment after it has been created and before the payment processing has started. All of the individual payment intents also have the created status at this point.
processingPayment processing has started. Individual payment intents still have the created status.
succeededAll payments have been processed, and all of the payment intents have the succeeded or settled status.
partially_successfulAll payments have been processed. At least one payment intent has the failed status, and at least one payment intent has the succeeded or settled status.
failedThis status occurs in the following cases:

* Unable to withdraw funds from the entity's bank account. In this case, individual payment intents still have the created status.

* All payment intents have been processed and all of them have the failed status.

Check the batch payment status

Assuming you have subscribed to the payment webhooks, you will receive the batch_payment.status_updated and payment_intent.status_updated webhooks whenever the payment status is updated.

In the case of the batch_payment.status_updated webhook, the event payload contains the batch payment ID (object_id) and the ID of the entity that made this payment (entity_id):

{
  "id": "dc84fcee-3788-436e-9e7a-31d9e335925a",
  "created_at": "2024-03-04T20:06:48.593225+00:00",
  "action": "batch_payment.status_updated",
  "api_version": "2024-01-31",
  "entity_id": "bebe3e93-3984-4a07-b2cc-897766c6f8d2",
  "description": "batch_payment_status_updatedd",
  "object": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "object_type": "batch_payment",
  "webhook_subscription_id": "c7f37127-44e5-494a-833a-21e60585f187"
}

Use these IDs to query the new status of the batch payment by calling GET /batch_payment/{id}:

curl 'https://api.sandbox.monite.com/v1/batch_payments/3fa85...fa6' \
  -H 'X-Monite-Version: 2024-01-31' \
  -H 'X-Monite-Entity-Id: ENTITY_ID' \
  -H 'Authorization: Bearer YOUR_PARTNER_TOKEN'

The returned batch payment object contains the statuses of the batch payment itself and its individual payment intents, among other details. If the batch payment status is partially_successful or failed, the error fields contain any errors that occurred while processing the batch payment as a whole and individual payment intent.

{
  "id": "6a0611dc-73a9-4bf2-9d90-0a78d1b0770a",
  "created_at": "2023-10-03T13:17:17.400Z",
  "payment_method": "us_ach",
  "payer_bank_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",

  "payment_intents": [
    {
      "id": "3900fc5b-2ff1-41a4-a958-e2139f779c81",
      "created_at": "2023-10-03T13:17:17.400Z",
      ...
      "status": "failed",
      "error": {
        "message": "Error message goes here"
      }
    },
    ... // Other payment intents
  ],
  ...

  "status": "partially_successful",
  "error": null
}