Skip to main content

Payments

Unit allows you to originate and receive ACH payments from/to all deposit accounts. For general information on the ACH network, we recommend the following series from Gusto: How ACH Works: a Developer's Perspective.

ACH Origination overview#

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.

ACH returns are handled by Unit:

  • When you're on the originating side of an ACH payment, the counterparty's institution may issue a return. This can happen in the case of ACH Debit (example reasons: unauthorized debit, insufficient funds in the counterparty's account) or ACH Credit (example reason: incorrect account number). When such returns happen, the payment.returned webhook event will be fired. In addition, a Returned ACH Transaction will be created within the relevant deposit account, to offset the original transaction associated with the ACH payment.
  • When you're on receiving side of an ACH payment, Unit may issue a return. This can happen in the case of ACH Debit (example reason: an attempt to debit a deposit account with insufficient funds) or ACH Credit (example reason: an attempt to credit an non-existent account number).

Originating an ACH payment supports Idempotency, to ensure that multiple identical requests will have the same effect as a single request.

note

ACH payment originations (both Debit and Credit) are subject to daily amount limits determined by the account's deposit product. 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.

note

Originating a credit ACH payment to a counterparty whose account belongs to your organization will result in a Book Transaction.

ACH payment to inline Counterparty#

Originates an ACH payment to a counterparty which is specified inline (vs to a linked Counterparty Resource).

VerbPOST
Urlhttps://api.s.unit.sh/payments
Required Scopepayments-write or payments-write-ach-debit
Data TypeachPayment
note

You can use scope payments-write-ach-debit only with ACH Debit payments.

Attributes#

NameTypeDescription
amountintegerThe amount (in cents).
directionstringThe direction in which the funds flow.
counterpartyCounterpartyThe party on the other side of the ACH payment.
descriptionstringPayment description (maximum of 10 characters), also known as Company Entry Description, this will show up on statement of the counterparty.
addendastringOptional, additional payment description (maximum of 80 characters), not all institutions present that.
idempotencyKeystringSee Idempotency.
tagsobjectSee Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance).

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe Deposit Account originating the payment.
Example Request:
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": "812345678",        "accountNumber": "12345569",        "accountType": "Checking",        "name": "Jane Doe"      },      "description": "Funding"    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "555"        }      }    }  }}'

Response#

Response is a JSON:API document.

Example Response:
{  "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"        }      }    }  }}

ACH payment to linked Counterparty#

Originates an ACH payment to a Counterparty. The counterparty should be created separately through Create Counterparty.

VerbPOST
Urlhttps://api.s.unit.sh/payments
Required Scopepayments-write-counterparty or payments-write
Data TypeachPayment

Attributes#

NameTypeDescription
amountintegerThe amount (in cents).
directionstringThe direction in which the funds flow.
descriptionstringPayment description (maximum of 10 characters), also known as Company Entry Description, this will show up on statement of the counterparty.
addendastringOptional, additional payment description (maximum of 80 characters), not all institutions present that.
idempotencyKeystringSee Idempotency.
tagsobjectSee Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance).
verifyCounterpartyBalancebooleanOptional, default is false. Verify the counterparty balance, if balance verification fails the payment will be rejected with reason set to CounterpartyInsufficientFunds.

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe Deposit Account originating the payment.
counterpartyJSON:API RelationshipThe Counterparty the payment to be made to.
Example Request:
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": "depositAccount",          "id": "555"        }      },      "counterparty": {        "data": {          "type": "counterparty",          "id": "4567"        }      }    }  }}'

Response#

Response is a JSON:API document.

Example Response:
{  "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"        }      }    }  }}

ACH payment with Plaid token#

Originates an ACH payment to a counterparty which is verified by Plaid.

VerbPOST
Urlhttps://api.s.unit.sh/payments
Required Scopepayments-write or payments-write-ach-debit
Data TypeachPayment

Attributes#

NameTypeDescription
amountintegerThe amount (in cents)
directionstringThe direction in which the funds flow
descriptionstringPayment description (maximum of 10 characters), also known as Company Entry Description, this will show up on statement of the counterparty.
idempotencyKeystringSee idempotency
counterpartyNamestringName of the person or company that owns the counterparty bank account.
plaidProcessorTokenstringSee Create Plaid processor token API
verifyCounterpartyBalancebooleanOptional, default is false. Verify the counterparty balance, if balance verification fails the payment will be rejected with reason set to CounterpartyInsufficientFunds.

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe Deposit Account originating the payment
Example Request:
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": "depositAccount",          "id": "555"        }      }    }  }}'

Response#

Response is a JSON:API document.

Example Response:
{  "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"        }      }    }  }}

Receiving an ACH payment#

You can receive ACH payments (both Debit and Credit) into any deposit account. To do so, you may provide the routing number and account number to trusted third parties. These numbers are both attributes of any deposit account.

Received ACH payments are processed automatically. You can get notified on them by listening to the transaction.created}) webhook and inspecting the payload for a received ACH transaction.

Examples:

  • Receiving an ACH Credit in the amount of $20 when the balance is $0 will automatically result in a balance increase. Two transactions will be created: one received ACH transaction and one associated fee transaction (if the fee is non-zero).
  • Receiving an ACH Debit in the amount of $20 when the balance is $10 will automatically result in an ACH return to the originating side of the payment. No transactions will be created.

ACH Status#

The ACH network operates in batches. When you originate an ACH payment, it will be created with a Pending status. You may track its progress using the status attribute or listening to relevant webhooks, such as payment.sent}) or payment.returned.

The possible status values are:

StatusDescription
PendingThe 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.
PendingReviewThe payment is pending review by Unit.
RejectedThe 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.
SentThe payment was processed by the ACH network. This is the final state for successful payments.
CanceledThe payment was canceled.
ReturnedThe payment was processed but the network or the receiving bank returned the payment (see return reasons for more details)

Create a Book payment#

Book payments are free and instant fund transfers between two accounts under your organization. Common uses for book payments include:

  • Moving funds between two accounts that belong to the same end-customer.
  • Moving funds between two accounts that belong to different end-customers.
  • Moving funds from clearing accounts to end-customer accounts.
  • Moving funds from your organization's revenue account to an end-customer account.

Once you create a book payment, Unit will process it instantly and free of charge. The result will be one Book Transaction in each account.

note

The direction of book payment is always Credit, moving funds from account to counterpartyAccount.

VerbPOST
Urlhttps://api.s.unit.sh/payments
Required Scopepayments-write
Data TypebookPayment

Attributes#

NameTypeDescription
amountintegerThe amount (in cents).
descriptionstringPayment description (maximum of 50 characters), this will show up on statement of the counterparty.
idempotencyKeystringSee Idempotency.
tagsobjectSee Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance).

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe Deposit Account originating the payment.
counterpartyAccountJSON:API RelationshipThe Counterparty account the payment to be made to.
Example Request:
curl -X POST 'https://api.s.unit.sh/payments'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "bookPayment",    "attributes": {      "amount": 10000,      "description": "Funding"    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "555"        }      },      "counterpartyAccount": {        "data": {          "type": "depositAccount",          "id": "99821"        }      }    }  }}'

Response#

Response is a JSON:API document.

Example Response:
{  "data": {    "type": "bookPayment",    "id": "1232",    "attributes": {      "createdAt": "2021-02-21T13:03:19.025Z",      "amount": 1500,      "direction": "Credit",      "description": "Funding",      "status": "Sent"    },    "relationships": {      "account": {        "data": {          "type": "account",          "id": "555"        }      },      "customer": {        "data": {          "type": "customer",          "id": "10000"        }      },      "counterpartyAccount": {        "data": {          "type": "account",          "id": "99821"        }      },      "counterpartyCustomer": {        "data": {          "type": "customer",          "id": "10000"        }      },      "transaction": {        "data": {          "type": "transaction",          "id": "1413"        }      }    }  }}

Create a Wire payment#

Wire payments are fund transfers done electronically across a network of banks or transfer agencies. Wires can only be used to move funds from the Unit account to a third party account (unlike ACH).

Once you create a wire payment, Unit will process it immediately, and a Wire Transaction will be created.

note

The direction of wire payment is always Credit, moving funds from account to counterparty.

note

Wire payments API is not enabled by default for all customers. Please contact Unit if you need to enable this functionality.

VerbPOST
Urlhttps://api.s.unit.sh/payments
Required Scopepayments-write
Data TypewirePayment

Attributes#

NameTypeDescription
amountintegerThe amount (in cents).
descriptionstringPayment description (maximum of 50 characters), this will show up on statement of the counterparty.
counterpartyWire CounterpartyThe party on the other side of the Wire payment.
idempotencyKeystringSee Idempotency.
tagsobjectSee Tags. Tags that will be copied to any transaction that this payment creates (see Tag Inheritance).

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe Deposit Account originating the payment.
Example Request:
curl -X POST 'https://api.s.unit.sh/payments'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "wirePayment",    "attributes": {      "amount": 200,      "direction": "Credit",      "description": "Wire payment",      "counterparty": {        "name": "April Oniel",        "routingNumber": "812345678",        "accountNumber": "1000000001",        "address": {          "street": "20 Ingram St",          "city": "Forest Hills",          "state": "CA",          "postalCode": "11375",          "country": "US"        }      }    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "10000"        }      }    }  }}'

Response#

Response is a JSON:API document.

Example Response:
{  "data": {    "type": "wirePayment",    "id": "1135",    "attributes": {      "createdAt": "2021-08-30T12:19:18.639Z",      "amount": 200,      "direction": "Credit",      "description": "Wire payment",      "counterparty": {        "name": "April Oniel",        "routingNumber": "812345678",        "accountNumber": "1000000001",        "address": {          "street": "20 Ingram St",          "city": "Forest Hills",          "state": "CA",          "postalCode": "11375",          "country": "US"        }      },      "status": "Pending"    },    "relationships": {      "account": {        "data": {          "type": "account",          "id": "10000"        }      },      "customer": {        "data": {          "type": "customer",          "id": "10000"        }      },      "customers": {        "data": [          {            "type": "customer",            "id": "10000"          }        ]      },      "transaction": {        "data": {          "type": "transaction",          "id": "4"        }      }    }  }}

Update ACH Payment#

Update an ACH Payment.

VerbPATCH
Urlhttps://api.s.unit.sh/payments/:paymentId
Required Scopepayments-write

Attributes#

NameTypeDescription
tagsobjectSee Updating Tags.
Update an ACH payment:
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"      }    }  }}'

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataAchPaymentThe updated ACH payment resource.

Update Book Payment#

Update a Book Payment.

VerbPATCH
Urlhttps://api.s.unit.sh/payments/:paymentId
Required Scopepayments-write

Attributes#

NameTypeDescription
tagsobjectSee Updating Tags.

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataBookPaymentThe updated Book payment resource.
Update book payment:
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": "bookPayment",    "attributes": {      "tags": {        "by": null,        "uuid": "83033b64-38f8-4dbc-91a1-313ff0156d02"      }    }  }}'

Receiving a wire payment#

You can receive wire (Fedwire) payments into any deposit account. To do so, you may provide the routing number and account number to trusted third parties. These numbers are both attributes of any Deposit Account.

Received wire payments are processed automatically. You can get notified on them by listening to the transaction.created webhook and inspecting the payload for a Wire Transaction.

As an example, receiving a wire payment in the amount of $4,000 when the balance is $0 will automatically result in a balance increase. Two transactions will be created: one Wire Transaction and one associated Fee Transaction (if the fee is non-zero).

Get by Id#

Get a payment by id.

VerbGET
Urlhttps://api.s.unit.sh/payments/{id}
Required Scopepayments

Query Parameters#

NameTypeDefaultDescription
includestring(empty)Optional. A comma-separated list of related resources to include in the response. Related resources include: customer, account, transaction. See Getting Related Resources

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataACH PaymentPayment resource.
includedArray of DepositAccount or Customer or TransactionArray of resources requested by the include query parameter.
curl -X GET 'https://api.s.unit.sh/payments/100' \-H "Authorization: Bearer ${TOKEN}"

List#

List payments resources. Filtering, paging and sorting can be applied.

VerbGET
Urlhttps://api.s.unit.sh/payments
Required Scopepayments

Query Parameters#

NameTypeDefaultDescription
page[limit]integer100Maximum number of resources that will be returned. Maximum is 1000 resources. See Pagination.
page[offset]integer0Number of resources to skip. See Pagination.
filter[accountId]string(empty)Optional. Filters the results by the specified account id.
filter[customerId]string(empty)Optional. Filters the results by the specified customer id.
filter[tags]Tags (JSON)(empty)Optional. Filter Payments by Tags.
filter[status]ACH Status (JSON)(empty)Optional. Filter Payments by ACH Status.
filter[since]RFC3339 Date string(empty)Optional. Filters the Payments that occurred after the specified date. e.g. 2020-01-13T16:01:19.346Z
filter[until]RFC3339 Date string(empty)Optional. Filters the Payments that occurred before the specified date. e.g. 2020-01-02T20:06:23.486Z
sortstringsort=-createdAtOptional. Leave empty or provide sort=createdAt for ascending order. Provide sort=-createdAt (leading minus sign) for descending order.
includestring(empty)Optional. A comma-separated list of related resources to include in the response. Related resources include: customer, account, transaction. See Getting Related Resources
curl -X GET 'https://api.s.unit.sh/payments?page[limit]=20&page[offset]=10&filter[status][]=Pending&filter[status][]=Clearing' \-H "Authorization: Bearer ${TOKEN}"

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataArray of ACH PaymentArray of payment resources.
includedArray of DepositAccount or Customer or TransactionArray of resources requested by the include query parameter.
Example Response:
{  "data": [    {      "type": "achPayment",      "id": "50",      "attributes": {        "createdAt": "2020-01-13T16:01:19.346Z",        "status": "Pending",        "counterparty": {          "routingNumber": "812345678",          "accountNumber": "12345569",          "accountType": "Checking",          "name": "Jane Doe"        },        "description": "Funding",        "direction": "Credit",        "amount": 10000      },      "relationships": {        "account": {          "data": {            "type": "depositAccount",            "id": "555"          }        },        "customer": {          "data": {            "type": "individualCustomer",            "id": "99823"          }        },        "counterparty": {          "data": {            "type": "counterparty",            "id": "4567"          }        },        "transaction": {          "data": {            "type": "transaction",            "id": "4003"          }        }      }    }  ]}

Possible ACH rejection reasons#

When creating an ACH payment, it may be rejected immediately due to the following reasons:

ReasonDescription
InsufficientFundsA credit payment to a counterparty was rejected due to account not having sufficient funds to cover the transaction.
DailyACHCreditLimitExceededThe credit payment amount exceeds the total daily ACH limit set by Unit.
DailyACHDebitLimitExceededThe debit payment amount exceeds the total daily ACH limit set by Unit.
MonthlyACHCreditLimitExceededThe credit payment amount exceeds the total monthly ACH limit set by Unit.
MonthlyACHDebitLimitExceededThe debit payment amount exceeds the total monthly ACH limit set by Unit.
CounterpartyInsufficientFundsA 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.
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.

Possible ACH return reasons#

When receiving an ACH return, it may be due the following reasons:

ReasonACH CodeShort Description
InsufficientFundsR01Insufficient Funds
AccountClosedR02Account Closed
NoAccountR03No Account / Unable to Locate Account
InvalidAccountNumberStructureR04Invalid Account Number Structure
UnauthorizedDebitToConsumerR05Unauthorized Debit to Consumer Account Using Corporate SEC Code
ReturnedPerOdfiRequestR06Returned per ODFI's Request
AuthorizationRevokedByCustomerR07Authorization Revoked by Customer
PaymentStoppedR08Payment Stopped
UncollectedFundsR09Uncollected Funds
CustomerAdvisesNotAuthorizedR10Customer Advises Unauthorized, Improper, Ineligible, or Part of an Incomplete Transaction
CheckTruncationEntryReturnedR11Check Truncation Early Return
BranchSoldToAnotherDfiR12Branch Sold to Another DFI
RdfiNotQualifiedToParticipateR13RDFI Not Qualified to Participate
RepresentativePayeeDeceasedOrUnableToContinueR14Representative Payee Deceased or Unable to Continue in that Capacity
BeneficiaryOrBankAccountHolderDeceasedR15Beneficiary or Account Holder (Other Than a Representative Payee) Deceased
AccountFrozenR16Account Frozen/Entry Returned per OFAC Instruction
FileRecordEditCriteriaR17File Record Edit Criteria
ImproperEffectiveEntryDateR18Improper Effective Entry Date
AmountFieldErrorR19Amount Field Error
NonTransactionAccountR20Non-Transaction Account
InvalidCompanyIdentificationR21Invalid Company Identification
InvalidIndividualIdNumberR22Invalid Individual ID Number
CreditEntryRefusedByReceiverR23Credit Entry Refused by Receiver
DuplicateEntryR24Duplicate Entry
AddendaErrorR25Addenda Error
MandatoryFieldErrorR26Mandatory Field Error
TraceNumberErrorR27Trace Number Error
RoutingNumberCheckDigitErrorR28Routing Number Check Digit Error
CorporateCustomerAdvisesNotAuthorizedR29Corporate Customer Advises Not Authorized
RdfiNotParticipantInCheckTruncationProgramR30RDFI Not Participant in Check Truncation Program
PermissibleReturnEntryR31Permissible Return Entry (CCD and CTX Only)
RdfiNonSettlementR32RDFI Non-Settlement
ReturnOfXckEntryR33Return of XCK Entry
LimitedParticipationDfiR34Limited Participation DFI
ReturnOfImproperDebitEntryR35Return of Improper Debit Entry
ReturnOfImproperCreditEntryR36Return of Improper Credit Entry
SourceDocumentPresentedForPaymentR37Source Document Presented for Payment
StopPaymentOnSourceDocumentR38Stop Payment on Source Document
ImproperSourceDocumentR39Improper Source Document/Source Document Presented for Payment