MngDeleteClientsByFilter¶
Deletes every client matching the supplied filter. A single flag decides what
happens to the trading accounts linked to those records:
delete_accounts: false detaches them, delete_accounts: true deletes them.
The confirm flag decides whether anything is written. With confirm: false the
command runs every check and returns the counters describing what would happen,
without touching a record.
The command is available through the manager command API only; there is no REST
path for it. The kind is fixed by the command name, so customer_kind is not
accepted on input. See
Clients and Leads Commands.
It replaces the deprecated MngDeleteCustomersByFilter.
Nothing here can be undone
Deleted records, accounts, and trades are removed from storage, not archived. Recovery is possible only from a backup. Treat the dry run as a mandatory step, not a convenience.
Access Control¶
Allowed sessions:
SESSION_MANAGERSESSION_ADMINSESSION_DEALERSESSION_CRM_MANAGERSESSION_CRM_ADMIN
The caller must have CRM access and del_clients.
delete_accounts: true additionally requires access_backoffice and
del_accounts, and every account's group must fall inside the caller's groups
mask, the same rule as MngDeleteAccount. A caller
who asks for it without those rights is refused with 403 before any record is
selected.
Every call is written to the journal, successful ones included.
Request¶
Dry run, delete records together with their accounts:
{
"command": "MngDeleteClientsByFilter",
"extID": "1",
"data": {
"delete_accounts": true,
"confirm": false,
"filter": {
"deskFilter": "*",
"limit": 100,
"offset": 0,
"where": [
["lifecycle_flags", "has_all", 32]
]
}
}
}
Request Data¶
Top level:
| Field | Type | Required | Description |
|---|---|---|---|
delete_accounts |
bool | Yes | true deletes the linked accounts and their trade history. false keeps them and clears customer_id |
confirm |
bool | Yes | false reports what would happen without writing. true performs the deletion |
filter |
object | Yes | Record selection |
filter object:
| Field | Type | Required | Description |
|---|---|---|---|
deskFilter |
string | Yes | Desk wildcard mask, for example *, DESK_*, DESK_EU*,!DESK_EU_TEST. Must not be empty |
limit |
int | Yes | From 1 to 50000. Validated, but it does not limit how much is processed |
offset |
int | Yes | Minimum 0. Validated, but it does not limit how much is processed |
where |
array | No | [[field, operator, value], ...], all conditions must match |
orWhere |
array | No | OR comparison group; at least one condition must match |
whereNot |
array | No | [[field, value], ...] |
whereIn |
array | No | [[field, [values...]], ...] |
whereNotIn |
array | No | [[field, [values...]], ...] |
whereBetween |
array | No | [[field, [from, to]], ...] |
whereNotBetween |
array | No | [[field, [from, to]], ...] |
orderBy |
array | No | Example: [["created_time", "desc"]] |
Filter fields and operators are the same as for the customer table, including the
lifecycle_flags operators has_all, has_any, and has_none. Common filter
semantics are described in Table filter syntax; desk masks in
Desks TCP API.
Behavior¶
Each record is all-or-nothing: if any check fails, it is reported in failures
and none of its accounts are touched. Accounts are processed first and the
record last, so an interrupted run leaves a consistent, retryable state.
An open market position blocks deletion and fails the record with
ACCOUNT_HAS_TRADES, listing the offending logins. Pending orders do not block
and are deleted together with the account. A non-zero balance does not block
either: it is reported through accounts_with_balance, not enforced.
Response Data¶
{
"confirm": true,
"delete_accounts": true,
"matched": 10,
"deleted": 9,
"failed": 1,
"accounts_matched": 44,
"accounts_deleted": 41,
"accounts_unlinked": 0,
"accounts_with_balance": 12,
"failures": [
{
"customer_id": 1207,
"error": "ACCOUNT_HAS_TRADES",
"message": "Accounts have open market positions",
"logins": [500780]
}
]
}
| Field | Type | Description |
|---|---|---|
confirm |
bool | Echo of the request flag |
delete_accounts |
bool | Echo of the request flag |
matched |
int | Records selected by the filter, kind, brand scope, and desk mask |
deleted |
int | Records actually deleted. Always 0 when confirm is false |
failed |
int | Records that did not pass. One entry in failures each |
accounts_matched |
int | Accounts belonging to records that passed every check |
accounts_deleted |
int | Accounts actually deleted. Always 0 in a dry run and in the detach branch |
accounts_unlinked |
int | Accounts actually detached. Always 0 in a dry run and in the delete branch |
accounts_with_balance |
int | How many of accounts_matched hold a non-zero balance. A count, never a sum |
failures |
array | One entry per failure, with an optional logins array naming the accounts at fault |
After an applied run matched = deleted + failed.
Response Statuses¶
| Status | Condition |
|---|---|
200 |
Dry run, or an applied run with no failures |
207 |
Applied, at least one record deleted, some failed |
403 |
delete_accounts: true without the account rights, or the caller context could not be resolved |
409 |
Applied, nothing was deleted |
A 409 has two readings: matched: 0 means the filter selected nobody, while a
non-zero failed equal to matched means every selected record was blocked.
Errors¶
| HTTP | Error | Description |
|---|---|---|
400 |
INVALID_DATA |
Request validation failed |
403 |
RET_NOT_ENOUGH_RIGHTS |
Missing permission, missing scope, or the record is outside the caller's visibility |
404 |
RET_NOT_FOUND |
No customer with that identifier exists |
Every error carries a message field with free-form text. Its contents are not
part of the contract; branch on error.