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.
Requirements
Before requesting closure, make sure the account meets each of the following:
- Zero balance. The available, pending, and posted balances must all be
0. Sweep or withdraw any remaining funds first, and confirm with Retrieving Account Balances. - No in-flight transfers. All Payment Orders, Returns, and Reversals on the account must be completed or cancelled.
Request a Closure
Send a PATCH request to the Update Internal Account endpoint with status set to pending_closure. Only pending_closure is accepted for status; any other non-blank value is rejected, and status cannot be combined with another updatable attribute.
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"
}'A successful request returns the full Internal Account with a status of pending_closure. The example below is abridged; see the Internal Account object 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. |
An account stays in pending_closure until the closure finishes processing, which can take several business days.
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.
Failure Responses
Rejected closures return a 422 with the reason in errors.message and leave the account in its previous status, either active or suspended; a failed request never leaves the account in pending_closure. Errors prefixed with vendor_rejected are surfaced from downstream checks run against the most up-to-date account state.
A non-zero balance:
{
"errors": {
"code": "parameter_invalid",
"message": "vendor_rejected: Account must have a zero balance to be closed",
"parameter": "base"
},
"error_list": [
{
"code": "parameter_invalid",
"message": "vendor_rejected: Account must have a zero balance to be closed",
"parameter": "base"
}
]
}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"
}
]
}An account in a state that cannot be closed, such as one that is already closed or still pending activation:
{
"errors": {
"code": "parameter_invalid",
"message": "vendor_rejected: Account is not in a state that can be closed",
"parameter": "base"
},
"error_list": [
{
"code": "parameter_invalid",
"message": "vendor_rejected: Account is not in a state that can be closed",
"parameter": "base"
}
]
}Updated about 21 hours ago