---
title: Send an ACH
slug: tutorials/api/ach/send-an-ach
description: Demonstrates originating a push payment, monitoring the status of the payment and handling notifications of change to the outbound payment (rejected, returned, NOC).



docTags: 
createdAt: 2024-08-09T13:17:12.814Z
---

## What you will learn

✅ How to originate a push payment

✅ How to monitor status of the payment

✅ How to handle rejected or returned outbound payment, or a NOC (notification of change

:::hint{type="info"}
If you are new to APIs and how the work we recommend you visit [API basics](docId\:pUTTCwQ5SKLzxYzIn5D1b).
:::

The tutorial uses these API endpoints:

| API                                                    | Description           |
| ------------------------------------------------------ | --------------------- |
| [POST /ach/v1/payments](docId\:ILwmF5qnTMLo30D2H3rCH)  | Originate the payment |

:::hint{type="warning"}
**Important**

Do not poll the APIs for status updates and reconciliation purposes
:::

## Before you begin

Make sure you have:

- [API credentials](docId\:Z-MVwOV-p00-xX082NabK)&#x20;
- Partner ID
- Account Number
- [Registered](docId\:BN5XtgkJogBe-CtwomCbS) the following webhook events:

| Webhook                | Description                                                                                      |
| ---------------------- | ------------------------------------------------------------------------------------------------ |
| `Ach.Payment.Sent`     | Outbound payment has been transmitted to the Federal Reserve                                     |
| `Ach.Return.Received`  | A previously originated payment has been returned by the receiving bank                          |
| `Ach.Noc.Received`     | A notification of change has been sent from the receiving bank regarding a previous origination  |
| `Ach.Payment.Rejected` | The ACH payment was rejected                                                                     |

## Originate the ACH payment

There are two types of ACH payments:

- **Push payment**
  When you transfer money to an account in another bank.
- **Pull payment**
  When you request funds from an account in another bank.

:::hint{type="info"}
Use a [validation](docId:0papBZYBjF0LZPac8-tRW) (prenote) if you want to verify and validate account details. A prenote simply means originating a payment of $0.00. If you don't receive an error response, the details are correct. This step is optional.
:::

This tutorial covers push payments. A push payment can result in:

- The recipient receives the payment
- Cross River or ACH rejects the payment
- The recipient FI returns the payment
- The recipient receives the payment but ACH sends a Notification of Change.

Let's send $100 to Bob Smith who has an account at another bank. Since we are transferring the money to Bob's account the `transactionType` attribute must be **Push**.

### To originate an ACH payment

:::::WorkflowBlock
::::WorkflowBlockItem
Call `POST /ach/v1/payments`.

The details of the push payment are defined by the [call attributes](docId\:ILwmF5qnTMLo30D2H3rCH).

:::hint{type="warning"}
**IMPORTANT**
We strongly recommend that you include an idempotency key in your request header to provide duplicate protection should the payment fail. Read more about [idempotency keys](docId\:xQC2lRsG0xVv_9NMkqxKk).
:::

:::hint{type="info"}
Money amounts in API calls and responses are written without a decimal point between the dollars and the cents.
:::

```curl
POST /ach/v1/payments
{
  "accountNumber": "2714035231",
  "receiver": {
    "routingNumber": "021000021",
    "accountNumber": "456789000",
    "accountType": "Checking",
    "name": "Bob Smith",
    "identification": "XYZ123",
  },
  "secCode": "WEB",
  "description": "Payment",
  "transactionType": "Push",
  "amount": 10000,
  "serviceType": "SameDay",
  "clientIdentifier": "21fe77da-e2f8-4475-9397-81a293d63b8x"
}
```
::::

:::WorkflowBlockItem
A successful API call returns a JSON response with the details of your originated payment.

```json
{
    "id": "b96b935a-4713-4aae-973b-aeee00f1a749",
    "accountNumber": "2714035231",
    "referenceId": "A2236S8S20FH",
    "paymentType": "Origination",
    "direction": "Outbound",
    "status": "Created",
    "source": "Api",
    "postingType": "Individual",
    "postingCode": "OK",
    "posting": "Pending",
    "originator": {
        "routingNumber": "021214891",
        "accountNumber": "2714035231",
        "accountType": "Checking",
        "name": "Cross River Bank",
        "identification": "021214891"
    },
    "receiver": {
        "routingNumber": "021000021",
        "accountNumber": "456789000",
        "accountType": "Checking",
        "name": "Bob Smith",
        "identification": "XYZ123"
    },
    "secCode": "WEB",
    "description": "Payment",
    "transactionType": "Push",
    "amount": 10000,
    "serviceType": "SameDay",
    "effectiveDate": "220811",
    "traceNumber": "021214898943562",
    "wasReturned": false,
    "wasCorrected": false,
    "holdDays": 0,
    "original": {
        "paymentId": "b96b935a-4713-4aae-973b-aeee00f1a749"
    },
    "createdAt": "2022-08-11T10:39:49.9996701-04:00",
    "partnerId": "1e5d3f04-ae24-4af6-9e30-aecf012b99dd",
    "productId": "cc62e17f-5912-483e-9e42-aed30112fbb6",
    "lastModifiedAt": "2022-08-11T10:39:49.9996701-04:00",
    "clientIdentifier": "21fe77da-e2f8-4475-9397-81a293d63b8x"
}
```

The `status`attribute in the response indicates that your payment was created. It does not indicate that your payment was successful.
:::
:::::

### Payment confirmation

After originating the payment, its status changes to **Pending** or **Hold** for up to several hours.

- A **Pending** status lets you know that the payment request is created but has not been batched for release to the Federal Reserve. The batching process occurs several times a day.
- A **Hold** status indicates that the payment request is in review and has not yet been approved for release to the Federal Reserve.

Next, the payment moves to **Batched** status. If the payment is originated close to a weekend or bank holiday it may take a few days for the status to transition to **Batched**.

When the Federal Reserve accepts the payment the status changes to **processing**, which triggers the `Ach.Payment.Sent` event.

The payment ID provided in the response body of the payment origination request (`id`) appears in the `details` object of the `Ach.Payment.Sent` event. In this case: **b96b935a-4713-4aae-973b-aeee00f1a749**.

:::CodeblockTabs
Sample Ach.Payment.Sent event

```json
{
  "id": "7c135bfa-234f-48d2-9d70-adc70135d15f",
  "eventName": "Ach.Payment.Sent",
  "status": "Pending",
  "partnerId": "30dee145-b6a2-4058-8dc3-ac4000dee91f",
  "createdAt": "2021-10-20T14:48:01.12-04:00",
  "resources": [
    "ach/v1/payments/b96b935a-4713-4aae-973b-aeee00f1a749"
  ],
  "details": [
    {
      "paymentId": "b96b935a-4713-4aae-973b-aeee00f1a749",
      "coreTransactionId": null,
      "memoPostId": "85b509f9-61f0-4af3-b64c-b04900de43da",
      "clientBatchId": null,
      "clientBatchSequence": null,
      "accountNumber": "2714035231",
      "postingCode": null,
      "clientIdentifier": null,
      "purpose": "ENTERED BY #60C3C9C8FD17BA0070A7FB4F#"
    }
    ]
}
```
:::

## Payment status webhook events

### Rejected payment

There may be situations where a payment request is rejected. A payment request rejected after initially receiving a `success` response from `POST /ach/v1/payments` could be due to:

- **Technical Rejection**. The transaction was unable to post from the account being used for your request, and is covered in this tutorial.
  **Example**
  - You originate a push payment for an amount greater than the balance of the originator account
  - You originate a payment from an account with an active restriction
- **Manual Rejection**. The payment was rejected by the Cross River Operations or BSA/AML Teams. Contact Cross River directly for information on why the payment was rejected.

To simulate a technical rejection, originate a push payment for an amount that exceeds the originating account balance. Learn more about [simulations](docId\:XiG1oe0IP7L9Q-Ii3U-Mk).

Again, let's send $100 to Bob Smith who has an account at another bank. This time, the amount you are sending exceeds the amount in the originator account.

:::::WorkflowBlock
:::WorkflowBlockItem
Call `POST /ach/v1/payments`.
:::

::::WorkflowBlockItem
Define the call attributes as above in To originate an ACH payment

```curl
{
  "accountNumber": "2674958042",
  "receiver": {
    "routingNumber": "021000021",
    "accountNumber": "456789000",
    "accountType": "Checking",
    "name": "Bob Smith",
    "identification": "XYZ123",
  },
  "secCode": "WEB",
  "description": "Payment",
  "transactionType": "Push",
  "amount": 10000,
  "serviceType": "SameDay",
  "clientIdentifier": "bd3e0315-5f29-4b1c-a004-1fcdd0b8bee1"
}
```

The following JSON response is returned:

```json
{
    "id": "f868a125-22b8-4c7e-a8dd-aeee00f76ce7",
    "accountNumber": "2674958042",
    "referenceId": "A223O84JDV79",
    "paymentType": "Origination",
    "direction": "Outbound",
    "status": "Created",
    "source": "Api",
    "postingType": "Individual",
    "postingCode": "OK",
    "posting": "Pending",
    "originator": {
        "routingNumber": "021214891",
        "accountNumber": "2674958042",
        "accountType": "Checking",
        "name": "Cross River Bank",
        "identification": "021214891"
    },
    "receiver": {
        "routingNumber": "021000021",
        "accountNumber": "456789000",
        "accountType": "Checking",
        "name": "Bob Smith",
        "identification": "XYZ123"
    },
    "secCode": "WEB",
    "description": "Payment",
    "transactionType": "Push",
    "amount": 10000,
    "serviceType": "SameDay",
    "effectiveDate": "220811",
    "traceNumber": "021214896697194",
    "wasReturned": false,
    "wasCorrected": false,
    "holdDays": 0,
    "original": {
        "paymentId": "f868a125-22b8-4c7e-a8dd-aeee00f76ce7"
    },
    "createdAt": "2022-08-11T11:00:50.8991331-04:00",
    "partnerId": "1e5d3f04-ae24-4af6-9e30-aecf012b99dd",
    "productId": "d5f3ce06-8550-413e-a2e1-aed1016d6eea",
    "lastModifiedAt": "2022-08-11T11:00:50.8991331-04:00",
    "clientIdentifier": "bd3e0315-5f29-4b1c-a004-1fcdd0b8bee1"
}
```

The `Ach.Payment.Rejected` event is triggered.

The `details` object in the `Ach.Payment.Rejected` event contains the payment ID from the response body (`id`). In this case: **f868a125-22b8-4c7e-a8dd-aeee00f76ce7**.

In the details object of the event, the `postingCode` tells you the [rejection code](docId\:oDtRP7ARfnpQuFEGy4Sfh), in this case **RES** (Account Restriction). If the payment needs to be reviewed manually, the `rejectionReason` gives you more information about the rejection.

:::CodeblockTabs
Sample Ach.Payment.Rejected event

```json
{
  "id": "496659ff-6034-480a-84af-aeee00f78ade",
  "eventName": "Ach.Payment.Rejected",
  "status": "Pending",
  "partnerId": "1e5d3f04-ae24-4af6-9e30-aecf012b99dd",
  "createdAt": "2022-08-11T11:01:16.483-04:00",
  "resources": [
    "ach/v1/payments/f868a125-22b8-4c7e-a8dd-aeee00f76ce7"
  ],
  "details": [
  {
      "paymentId": "f868a125-22b8-4c7e-a8dd-aeee00f76ce7",
      "coreTransactionId": null,
      "memoPostId": "517f24c5-3cf1-4168-b721-b04900e36f00",
      "clientBatchId": null,
      "clientBatchSequence": null,
      "accountNumber": "2674958042",
      "postingCode": "RES",
      "clientIdentifier": null,
      "purpose": "ENTERED BY #60C3C9C8FD17BA0070A7FB4F#",
      "rejectionReason": "Other"
    }
  ]
}

```
:::
::::
:::::

### Returned payment

Sometimes an ACH payment is returned by the receiving bank. See [return codes](docId\:oDtRP7ARfnpQuFEGy4Sfh) for a complete list of why a payment might be returned.

:::hint{type="info"}
**Example**

The receiving bank can't find the specified receiver account number.
:::

Most returns occur within 2 business days, but may take longer.

A payment return creates a new payment record with the `paymentType` set as **Return**. The new payment record is connected to the original payment record with the `previous.paymentId` field.

:::hint{type="warning"}
**IMPORTANT**
Once payment status transitions to **Complete**, the payment record is no longer updated, even if the payment is returned.
:::

A payment returned from a receiving bank triggers the `ACH.Return.Received` webhook event.

Here's an example of an ACH return webhook event:

:::CodeblockTabs
Sample Ach.Return.Received event

```json
{
  "id": "d3ad6473-6690-44f1-a4a6-b04900d95419",
  "eventName": "Ach.Return.Received",
  "status": "Pending",
  "partnerId": "1e5d3f04-ae24-4af6-9e30-aecf012b99dd",
  "createdAt": "2023-07-24T09:11:16.133-04:00",
  "resources": [
    "ach/v1/payments/fb05013b-eaba-439e-8c6b-b04900d8f805"
  ],
  "details": [
    {
      "paymentId": "fb05013b-eaba-439e-8c6b-b04900d8f805",
      "coreTransactionId": "28633d37-f441-496a-ab07-b04900d93e75",
      "originalPaymentId": "1a1a9919-33b5-4933-9b9f-b034011462df",
      "accountNumber": "2151546989",
      "traceNumber": "021000021754553",
      "reasonCode": "R01",
      "reasonData": ""
    }
  ]
}
```
:::

The event shows reasonCode **R01** (Insufficient Funds). The `originalPaymentId` field shows the ID of the original outbound payment.

### Notification of Change (NOC)

There are times when Cross River receives an ACH notification of change (NOC) related to an outbound payment. When you create an API call, a NOC is referred to as a **Correction** in the `paymentType` attribute. Unlike an ACH return, a NOC indicates that the payment you previously originated:

- Posted to the receiver account
- Contained an error (such as an incorrect routing number)
  See [ACH correction codes](docId\:oDtRP7ARfnpQuFEGy4Sfh) for a complete list

Register for the `Ach.Noc.Received` webhook event to be notified of an inbound NOC.

Here's an example of a NOC webhook event:

:::CodeblockTabs
Sample Ach.Noc.Received event

```json
{
  "id": "43d767a8-6b3a-4b5e-9fe6-b05401215333",
  "eventName": "Ach.Noc.Received",
  "status": "Pending",
  "partnerId": "1e5d3f04-ae24-4af6-9e30-aecf012b99dd",
  "createdAt": "2023-08-04T13:33:24.01-04:00",
  "resources": [
    "ach/v1/payments/197021dd-4b47-47b3-a75e-b0540120f5f2"
  ],
  "details": [
    {
      "paymentId": "197021dd-4b47-47b3-a75e-b0540120f5f2",
      "coreTransactionId": "578f36cd-f8e8-47ba-afa8-b05401213c5f",
      "originalPaymentId": "2cc0a0dd-6d7e-4ad9-9d3e-b0540105ba19",
      "accountNumber": "2696592019",
      "traceNumber": "021200333650075",
      "reasonCode": "C02",
      "reasonData": "026009593"
    }
  ]
}
```
:::

The `reasonCode` attribute in the response is **C02**. This indicates an Incorrect Routing Number. The `reasonData` attribute is the correct receiver routing number.

If you receive a NOC notification, update your internal records with the information you receive in the `reasonData` attribute.
