Overview
Unit allows you to originate next day and same day ACH payments.
For more information on originating ACH payments, please refer to Unit's ACH Guide
In Unit, an ACH payment originates from a Deposit Account. The entity on the other side of the payment is called a Counterparty. A counterparty is a combination of routing number, account number, account type, and name.
Each ACH payment has a direction - either Debit
or Credit
. In the context of ACH payment origination, the directions work as follows:
- Debit - the payment "pulls" funds from the counterparty account. The amount is credited to the originating deposit account on Unit. It may take several banking (business) days for the credit to be settled, depending on the settings for your organization.
- Credit - the payment "pushes" funds to the counterparty account. The amount is debited from the originating deposit account immediately.
Originating an ACH payment supports Idempotency, to ensure that multiple identical requests will have the same effect as a single request.
ACH payment originations (both Debit and Credit) are subject to soft and hard daily amount limits determined by the account's deposit product. Once the Soft limit is exceeded, payments will automatically be submitted for manual review. Debit ACHs can only be manually approved if a balance check for the counterparty is successful.
Once you exceed the account's total daily limit, payments will be created under the Rejected
status code, and the relevant API responses will contain the exact reason.
You may contact Unit to change the limits for an account or a group of accounts. See the Limits section for more information.
Some ACH payments will automatically be converted into Book Payments upon creation. These will be logged and appear as ACH on the account but function as book payments (e.g. status flows, limits, clearing times etc.), except for when both counterparties are customers of your organisation, in which case the payment will also be logged as a book payment.
ACH Statuses
The ACH network operates in batches. When you originate an ACH payment, it will mostly be created with a Pending
status. See note above for examples of when the status won't be Pending
initially. You may track a payment's progress using the status
attribute or listening to relevant webhooks, such as payment.sent or payment.returned.
The possible status
values are listed below and you should be prepared to receive all statuses:
Status | Description |
---|---|
Pending | The payment was created on the Unit ledger but was not yet delivered to the ACH network. Payments with Pending status may be canceled by the originator. |
PendingReview | The payment is pending review by Unit. |
Rejected | The payment was rejected due to insufficient funds or exceeding daily ACH limits (see rejection reasons for more details) |
Clearing | (Debit only) The payment was sent but the deposit account was not credited yet. |
Sent | The payment was processed by the ACH network. This is the final state for successful payments. |
Canceled | The payment was canceled. |
Returned | The payment was processed but the network or the receiving bank returned the payment (see return reasons for more details) |
Same-day ACH
Same-day ACH enables your clients to send and receive funds using ACH the same day the payment is created. You can read more about same-day ACH in the relevant section of the Unit ACH guide.
The same day ACH functionality is disabled by default and is only available for specific use cases. If you would like to use same day ACH, please contact Unit.
Use a Custom Standard Entry Class (SEC) Code
A Standard Entry Class (SEC) code is a mandatory three-letter code used in all ACH payments (originated and received) in order identify certain types of ACH payments.
The SEC Code generally indicates:
- The nature of the transaction as consumer or corporate in nature. It indicates whether the funds transfer affects a consumer account or a corporate account at the RDFI (receiving depository financial institutions).
- Whether the transaction is single-entry or recurring.
- The specific computer record format that will be used to carry the payment and payment-related information relevant to the application.
The use of Custom Standard Entry Class (SEC) Code is currently limited to specific codes as described below:
Direction | Customer Type | Supported SEC codes (ACH Origination) |
---|---|---|
Credit | Individual Business | WEB (*default), PPD CCD (default), PPD |
Debit | Individual Business | Not Supported WEB (default), CCD |
The custom SEC code functionality is disabled by default. If you would like to enable it, please contact Unit.
*Individuals who are Sole Proprietors will have their default SEC code set to CCD
.
Dynamic Clearing Period (ACH Debit)
Dynamic Clearing Period enables you to set the amount of days it will take an Originated ACH debit
to clear and funds to become available in a deposit account. When this feature is enabled, the value that is passed as clearingDaysOverride
, will replace the default amount of clearing days as it is defined in the deposit product.
In order to enable the Dynamic Clearing Period feature, new definitions of maximum clearing days and minimum clearing days will need to be added to the deposit product so the clearingDaysOverride
attribute will support values between the minimum clearing days and the maximum clearing days .
If a clearing days override is not specified when the ACH debit is created, the clearing period will be set to the default clearing period set in the deposit product.
The clearing period can be changed after the ACH debit resource has been created, as long as it is still in Pending
or PendingReview
status.
The dynamic clearing period functionality is disabled by default. If you would like to enable it, please contact Unit.
Create ACH payment to inline Counterparty
Originates an ACH payment to a counterparty which is specified inline (vs to a linked Counterparty Resource).
Verb | POST |
Url | https://api.s.unit.sh/payments |
Required Scope | payments-write or ach-payments-write |
Data Type | achPayment |
Timeout (Seconds) | 60 |
Originating ACH debits requires capturing the authorization of the account owner and therefore originating ACH debits to inline counterparties is not allowed by default. If your use case requires this capability, please contact Unit.
Attributes
Name | Type | Description |
---|---|---|
amount | integer | The amount (in cents). |
direction | string | The direction in which the funds flow. |
counterparty | Counterparty | The party on the other side of the ACH payment. |
description | string | Payment description (maximum of 10 characters), also known as Company Entry Description, this will show up on statement of the counterparty. |
addenda | string | Optional, additional payment description (maximum of 80 characters), not all institutions present that. |
idempotencyKey | string | Optional. See Idempotency. |
tags | object | Optional. See Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance). |
sameDay | boolean | Optional, default is false . See Same Day ACH. |
secCode | string | Optional. See Use a custom SEC Code. |
clearingDaysOverride | integer | Optional. See Dynamic Clearing Period |
Relationships
Name | Type | Description |
---|---|---|
account | JSON:API Relationship | The Deposit Account originating the payment. |
curl -X POST 'https://api.s.unit.sh/payments'
-H 'Content-Type: application/vnd.api+json'
-H 'Authorization: Bearer ${TOKEN}'
--data-raw '{
"data": {
"type": "achPayment",
"attributes": {
"amount": 10000,
"direction": "Credit",
"counterparty": {
"routingNumber": "812345673",
"accountNumber": "12345569",
"accountType": "Checking",
"name": "Jane Doe"
},
"description": "Funding"
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": "555"
}
}
}
}
}'
Response
Response is a JSON:API document.
{
"data": {
"type": "achPayment",
"id": "50",
"attributes": {
"createdAt": "2020-01-13T16:01:19.346Z",
"status": "Pending",
"reason": null,
"counterparty": {
"routingNumber": "812345673",
"accountNumber": "12345569",
"accountType": "Checking",
"name": "Jane Doe"
},
"description": "Funding",
"direction": "Credit",
"amount": 10000,
"tags": {
"purpose": "internal"
}
},
"relationships": {
"account": {
"data": {
"type": "depositAccount",
"id": "555"
}
},
"customer": {
"data": {
"type": "individualCustomer",
"id": "99823"
}
}
}
}
}
Create ACH payment to linked Counterparty
Originates an ACH payment to a Counterparty. The counterparty should be created separately through Create Counterparty.
Verb | POST |
Url | https://api.s.unit.sh/payments |
Required Scope | payments-write-counterparty or payments-write or ach-payments-write |
Data Type | achPayment |
Timeout (Seconds) | 60 |
Attributes
Name | Type | Description |
---|---|---|
amount | integer | The amount (in cents). |
direction | string | The direction in which the funds flow. |
description | string | Payment description (maximum of 10 characters), also known as Company Entry Description, this will show up on statement of the counterparty. |
addenda | string | Optional, additional payment description (maximum of 80 characters), not all institutions present that. |
idempotencyKey | string | Optional. See Idempotency. |
tags | object | Optional. See Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance). |
verifyCounterpartyBalance | boolean | Optional, default is false . Verify the counterparty balance, if balance verification fails the payment will be rejected with reason set to CounterpartyInsufficientFunds . |
sameDay | boolean | Optional, default is false . See Same Day ACH. |
secCode | string | Optional. See Use a custom SEC Code. |
clearingDaysOverride | integer | Optional. See Dynamic Clearing Period |
Relationships
Name | Type | Description |
---|---|---|
account | JSON:API Relationship | The Deposit Account originating the payment. |
counterparty | JSON:API Relationship | The Counterparty the payment to be made to. |
curl -X POST 'https://api.s.unit.sh/payments'
-H 'Content-Type: application/vnd.api+json'
-H 'Authorization: Bearer ${TOKEN}'
--data-raw '{
"data": {
"type": "achPayment",
"attributes": {
"amount": 10000,
"direction": "Credit",
"description": "Funding"
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": "555"
}
},
"counterparty": {
"data": {
"type": "counterparty",
"id": "4567"
}
}
}
}
}'
Response
Response is a JSON:API document.
{
"data": {
"type": "achPayment",
"id": "50",
"attributes": {
"createdAt": "2020-01-13T16:01:19.346Z",
"status": "Pending",
"reason": null,
"counterparty": {
"routingNumber": "812345678",
"accountNumber": "12345569",
"accountType": "Checking",
"name": "Jane Doe"
},
"description": "Funding",
"direction": "Credit",
"amount": 10000,
"tags": {
"purpose": "internal"
}
},
"relationships": {
"account": {
"data": {
"type": "depositAccount",
"id": "555"
}
},
"customer": {
"data": {
"type": "individualCustomer",
"id": "99823"
}
},
"counterparty": {
"data": {
"type": "counterparty",
"id": "4567"
}
}
}
}
}
Create ACH payment with Plaid token
Originates an ACH payment to a counterparty which is verified by Plaid.
For more information on using Plaid, please read Unit's Plaid partnership guide
Verb | POST |
Url | https://api.s.unit.sh/payments |
Required Scope | payments-write or payments-write-ach-debit or ach-payments-write |
Data Type | achPayment |
Timeout (Seconds) | 60 |
You can use scope payments-write-ach-debit
only with ACH Debit payments.
Attributes
Name | Type | Description |
---|---|---|
amount | integer | The amount (in cents) |
direction | string | The direction in which the funds flow |
description | string | Payment description (maximum of 10 characters), also known as Company Entry Description, this will show up on statement of the counterparty. |
addenda | string | Optional, additional payment description (maximum of 80 characters), not all institutions present that. |
idempotencyKey | string | Optional. See idempotency |
counterpartyName | string | Optional. Name of the person or company that owns the counterparty bank account. |
plaidProcessorToken | string | See Create Plaid processor token API |
tags | object | Optional. See Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance). |
verifyCounterpartyBalance | boolean | Optional, default is false . Verify the counterparty balance, if balance verification fails the payment will be rejected with reason set to CounterpartyInsufficientFunds . |
sameDay | boolean | Optional, default is false . See Same Day ACH. |
secCode | string | Optional. See Use a custom SEC Code. |
clearingDaysOverride | integer | Optional. See Dynamic Clearing Period |
Relationships
Name | Type | Description |
---|---|---|
account | JSON:API Relationship | The Deposit Account originating the payment |
curl -X POST 'https://api.s.unit.sh/payments'
-H 'Content-Type: application/vnd.api+json'
-H 'Authorization: Bearer ${TOKEN}'
--data-raw '{
"data": {
"type": "achPayment",
"attributes": {
"amount": 10000,
"direction": "Debit",
"plaidProcessorToken": "processor-5a62q307-ww0a-6737-f6db-pole26004556",
"description": "Funding"
},
"relationships": {
"account": {
"data": {
"type": "account",
"id": "555"
}
}
}
}
}'
Response
Response is a JSON:API document.
201 Created
Field | Type | Description |
---|---|---|
data | Payment | The target resource after the operation was completed. |
408 Request Timeout
The request to Plaid has timed-out, probably because of a technical issue with the counterparty bank. You might want to retry the request without the verifyCounterpartyBalance
flag.
{
"data": {
"type": "achPayment",
"id": "50",
"attributes": {
"createdAt": "2020-01-13T16:01:19.346Z",
"status": "Pending",
"reason": null,
"counterparty": {
"routingNumber": "812345673",
"accountNumber": "12345569",
"accountType": "Checking",
"name": "Jane Doe"
},
"description": "Funding",
"direction": "Credit",
"amount": 10000,
"tags": {
"purpose": "internal"
}
},
"relationships": {
"account": {
"data": {
"type": "depositAccount",
"id": "555"
}
},
"customer": {
"data": {
"type": "individualCustomer",
"id": "99823"
}
}
}
}
}
Update ACH Payment
Update an ACH Payment.
Verb | PATCH |
Url | https://api.s.unit.sh/payments/:paymentId |
Required Scope | payments-write |
Timeout (Seconds) | 5 |
Attributes
Name | Type | Description |
---|---|---|
tags | object | See Updating Tags. |
clearingDaysOverride | integer | Only supports ACH Payments with direction Debit in status PendingReview or Pending . See Dynamic Clearing Period |
curl -X PATCH 'https://api.s.unit.sh/payments/:paymentId'
-H 'Content-Type: application/vnd.api+json'
-H 'Authorization: Bearer ${TOKEN}'
--data-raw '{
"data": {
"type": "achPayment",
"attributes": {
"tags": {
"by": null,
"uuid": "83033b64-38f8-4dbc-91a1-313ff0156d02"
},
"clearingDaysOverride": 3
}
}
}'
Response
Response is a JSON:API document.
200 OK
Field | Type | Description |
---|---|---|
data | AchPayment | The updated ACH payment resource. |
Cancel ACH Payment
Cancels a previously processed ACH payment. Only payments with status Pending
or PendingReview
can be canceled.
Verb | POST |
Url | https://api.s.unit.sh/payments/{paymentId}/cancel |
Required Scope | payments-write |
Timeout (Seconds) | 5 |
Response
Response is a JSON:API document.
200 OK
Field | Type | Description |
---|---|---|
data | ACH Payment | The canceled payment. |
curl -X POST 'https://api.s.unit.sh/payments/61212/cancel' \
-H "Authorization: Bearer ${TOKEN}"
Possible ACH rejection Reasons
When creating an ACH payment, it may be rejected immediately due to the following reasons:
Reason | Description |
---|---|
InsufficientFunds | A credit payment to a counterparty was rejected due to account not having sufficient funds to cover the transaction. |
DailyACHCreditLimitExceeded | The credit payment amount exceeds the total daily ACH limit set by Unit. |
DailyACHDebitLimitExceeded | The debit payment amount exceeds the total daily ACH limit set by Unit. |
MonthlyACHCreditLimitExceeded | The credit payment amount exceeds the total monthly ACH limit set by Unit. |
MonthlyACHDebitLimitExceeded | The debit payment amount exceeds the total monthly ACH limit set by Unit. |
CounterpartyInsufficientFunds | A debit payment was rejected due to insufficient funds of the counterparty. |
PlaidBalanceUnavailable | (Plaid only) Unable to determine the balance of the counterparty. |
PlaidLoginRequired | (Plaid only) The Plaid Link authentication has become invalid and requires re-login. See this guide on re-initializing Plaid Link. |
PlaidInvalidProduct or PlaidUnsupportedBank | (Plaid only) The Plaid integration is not available. Please contact Unit. |
PlaidInternalError | (Plaid only) An error occurred while establishing a connection with Plaid. Please contact Unit. |
SuspectedFraud | Unit or the client suspects the payment may be fraudulent |
ClientRequest | Client requested Unit to cancel/reject the payment |
NameMismatch | The counterparty name on the payment does not match the counterpaty name in the Plaid data |
PlaidTokenError | There is an error retrieving Plaid data. |
PlaidTokenExpired | The plaid token expired. A new token will need to be linked |
PlaidNotSupported | The counterparty bank does not support Plaid |