Closing Accounts
When a customer no longer needs an account, request its closure through the API. Closure is an asynchronous process: Modern Treasury validates the request, moves the Internal Account to pending_closure, and returns closed once the account is terminally closed.
For BYOA accounts, Modern Treasury sends the closure request to the bank. Completion therefore depends on the bank: some banks close accounts synchronously and the response may already return closed, while others leave the account in pending_closure until the bank confirms closure.
Requirements
Before requesting closure, make sure the account meets each of the following:
- No in-flight transfers. The account must not have cancellable Payment Orders, pending originating Returns, or pending Reversals. Customer closure requests do not automatically cancel these instructions. The corresponding errors are
The internal account has in-flight PaymentOrders.,The internal account has in-flight Returns., andThe internal account has in-flight Reversals.. - All child accounts are closed. An account cannot be closed while any of its child accounts has a status other than
closed. The error ishas child accounts that are not closed. - The bank supports API closure. The bank must support closing accounts through the API, and the connection must have an API endpoint configured. The errors are
Vendor does not support this Internal Account request.andConnection endpoint not configured. - The account is in a closable state. Accounts in
active,suspended, orpending_activationstatus can begin closure. The error for an account that cannot be closed iscannot be closed.
Closure requests are supported for the following banks:
| Bank | Accounts that can be closed via API |
|---|---|
| BNY Mellon | Child accounts only; parent accounts cannot be closed via the API. |
| Cross River | Child accounts only; parent accounts cannot be closed via the API. |
| Standard Chartered | Child accounts only; parent accounts cannot be closed via the API. |
Requesting closure on an account at any other bank is rejected with Vendor does not support this Internal Account request.. When a bank rejects a parent-account closure, Modern Treasury returns a vendor_rejected:-prefixed error.
Modern Treasury does not validate the account balance as part of the BYOA closure request. Your bank may still reject a closure for reasons such as remaining funds; those downstream errors are surfaced with a vendor_rejected: prefix.
Request a Closure
Send a PATCH request to the Update Internal Account endpoint with status set to pending_closure.
curl --request PATCH \
-u ORGANIZATION_ID:API_KEY \
--url https://app.moderntreasury.com/api/internal_accounts/<internal_account_id> \
-H 'content-type: application/json' \
-d '{
"status": "pending_closure"
}'Only pending_closure is accepted for status. Any other non-blank value is rejected with Must be 'pending_closure'., and status cannot be combined with another updatable attribute. When combined with another updatable attribute, the request is rejected with Cannot be updated while requesting closure..
A successful request returns the full Internal Account. Depending on the bank, the response status may be pending_closure or closed. The example below is abridged; see the Internal Account reference for every field.
{
"id": "bf5f1df9-de01-40c2-9040-7ec10170a14c",
"object": "internal_account",
"name": "Customer Payment Account",
"status": "pending_closure",
"currency": "USD",
"legal_entity_id": "8f4e2b1c-7d93-4a56-b8e1-2c9f0a3d5e67",
"parent_account_id": null,
"counterparty_id": null,
"live_mode": true,
"metadata": {},
"created_at": "2026-01-01T16:30:00Z",
"updated_at": "2026-02-14T09:15:00Z"
}Closure States
| Status | Description |
|---|---|
pending_closure | The closure request has been accepted and is being processed. The account can no longer originate payments. |
closed | The account is terminally closed. It can no longer be used. |
Subscribe to internal_account webhooks to be notified when the closure completes. You will receive an internal_account.closed webhook once the account reaches closed. There is no webhook for entering pending_closure or for a failed closure; closure failures are returned inline as 422 responses.
Failure Responses
Rejected closures return a 422 with the reason in errors.message and error_list[].message. For customer requests, the account reverts to its previous status, such as active or suspended; a failed request never leaves the account in pending_closure.
In-flight transfers on the account:
{
"errors": {
"code": "parameter_invalid",
"message": "The internal account has in-flight PaymentOrders.",
"parameter": "internal_account"
},
"error_list": [
{
"code": "parameter_invalid",
"message": "The internal account has in-flight PaymentOrders.",
"parameter": "internal_account"
}
]
}Child accounts that are not closed:
{
"errors": {
"code": "parameter_invalid",
"message": "has child accounts that are not closed",
"parameter": "internal_account"
},
"error_list": [
{
"code": "parameter_invalid",
"message": "has child accounts that are not closed",
"parameter": "internal_account"
}
]
}An unsupported bank:
{
"errors": {
"code": "parameter_invalid",
"message": "Vendor does not support this Internal Account request.",
"parameter": "internal_account"
},
"error_list": [
{
"code": "parameter_invalid",
"message": "Vendor does not support this Internal Account request.",
"parameter": "internal_account"
}
]
}A downstream bank rejection:
{
"errors": {
"code": "parameter_invalid",
"message": "vendor_rejected: Account cannot be closed while funds remain",
"parameter": "base"
},
"error_list": [
{
"code": "parameter_invalid",
"message": "vendor_rejected: Account cannot be closed while funds remain",
"parameter": "base"
}
]
}Updated about 20 hours ago