---
title: ATM participation and status
summary: Checks ATM-network participation, retrieves and translates an account status, or translates a bare ATM status code via the ATM vendor service.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: BankValidator
reference_type: package
operation_id: OP-BV-04
trigger: Caller invokes IsATMParticipant, GetATMAccountStatus, or TranslateStatusCode
---

# ATM participation and status

This operation covers the three façade methods that interact with the ATM vendor service: `IsATMParticipant` checks whether a routing number participates in the ATM network, `GetATMAccountStatus` retrieves and translates an account status (checking participation first), and `TranslateStatusCode` translates a status code the caller already has in hand. This is the only operation group in the library with two distinct fault/edge behaviors captured as business rules.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-BV-04 |
| **Trigger** | Caller calls `IsATMParticipant(inRoutingNum)`, `GetATMAccountStatus(inRoutingNum, inAccountNum, inAmount, outStatusDescription)`, or `TranslateStatusCode(inStatus)` on a constructed `clsValidateBank` |
| **Inputs** | Routing number; for `GetATMAccountStatus`, also account number and amount; for `TranslateStatusCode`, a status code |
| **Outputs** | `Boolean` participation flag (`IsATMParticipant`); `Integer` status code plus an `outStatusDescription` byref string (`GetATMAccountStatus`); or a translated description string (`TranslateStatusCode`) |
| **Primary components** | `clsValidateBank.IsATMParticipant`, `clsValidateBank.GetATMAccountStatus`, `clsValidateBank.TranslateStatusCode`, `clsValidateBank.LogonATM`, `clsValidateBank.LogoffATM` |
| **Entry point** | `Legacy\BankValidator\clsValidateBank.vb` |

## Steps

1. **Log on to the ATM service.** `LogonATM()` increments `m_LogonAttempts`, lazily constructs `ATMService.ATMService` if needed, sets its `Url` from `URLATM`, and calls `ATM.Logon(CompanyId, UserId, Password)` to obtain a `LogonToken` ([BR-002](../business-rules.md#br-002-vendor-logon-retry-handling)).
   - On failure: recursively retries `LogonATM()` while `m_LogonAttempts < m_LogonAttemptsMax`, then throws `ApplicationException("Unable to logon to ATM web service.", ex)` once exhausted.
2. **`IsATMParticipant` — check participation.** Wrapped in `Try/Catch`, call `ATM.IsParticipant(LogonToken, inRoutingNum)` and assign the result to `isValid`.
   - On `SoapException`: assign `isValid = False`, treating the fault as non-participation ([BR-005](../business-rules.md#br-005-atm-participation-faults-resolve-to-non-participant)).
   - On any other exception: throw `ApplicationException("Error while trying to check the ATM participant", ex)`.
   - `LogoffATM()` runs in `Finally` regardless of outcome.
3. **`GetATMAccountStatus` — initialize defaults.** `statusCode` is set to `-1` and `outStatusDescription` is set to `"Unknown"` before any vendor call, establishing the fallback outcome up front.
4. **`GetATMAccountStatus` — check participation.** Call `ATM.IsParticipant(LogonToken, inRoutingNum)` (not wrapped in `Try/Catch` at this call site).
   - If the bank participates: call `ATM.GetStatusCode(LogonToken, inRoutingNum, inAccountNum, inAmount.ToString("0000000.00"))` to get `statusCode`, then call `ATM.TranslateStatusCode(LogonToken, statusCode)` to resolve `outStatusDescription`.
   - If the bank does not participate: leave `statusCode = -1` and `outStatusDescription = "Unknown"` ([BR-004](../business-rules.md#br-004-non-participating-banks-return-unknown-atm-status)).
   - Because this method has no `Try/Catch`, any exception from `ATM.IsParticipant`, `ATM.GetStatusCode`, or `ATM.TranslateStatusCode` propagates directly to the caller and `LogoffATM()` is skipped.*
5. **`TranslateStatusCode` — translate a code.** Call `ATM.TranslateStatusCode(LogonToken, inStatus)` and assign the result to `result` (default `"Unknown"`).
   - Not wrapped in `Try/Catch`; an exception propagates directly to the caller and skips `LogoffATM()`.*
6. **Log off the ATM service.** `LogoffATM()` calls `ATM.Logoff(LogonToken)`, disposes the `ATM` proxy, and sets it to `Nothing` (guaranteed via `Finally` only for `IsATMParticipant`; called unconditionally at the end of `GetATMAccountStatus` and `TranslateStatusCode` when no exception is thrown).
   - On failure: the exception is silently swallowed (the `Throw` line is commented out).
7. **Return the result.** `IsATMParticipant` returns the participation Boolean; `GetATMAccountStatus` returns `statusCode` and sets `outStatusDescription` by reference; `TranslateStatusCode` returns the description string.

## Process flow

The following diagram visualizes the three method flows, highlighting the participation-check branch used by `GetATMAccountStatus` and the fault handling unique to `IsATMParticipant`.

```mermaid
flowchart TD
	Start([Caller calls IsATMParticipant,<br>GetATMAccountStatus, or TranslateStatusCode]) --> Logon[LogonATM:<br>logon with retry up to m_LogonAttemptsMax]
	Logon --> LogonOk{Logon succeeded?}
	LogonOk -->|No, retries exhausted| Ex([ApplicationException thrown])
	LogonOk -->|Yes| Which{Which method?}
	Which -->|IsATMParticipant| Part[ATM.IsParticipant]
	Part --> PartFault{SoapException?}
	PartFault -->|Yes| NonPart[isValid = False]
	PartFault -->|No, other| PartEx([ApplicationException thrown])
	PartFault -->|No| PartOk[isValid = vendor result]
	Which -->|GetATMAccountStatus| Defaults[statusCode = -1<br>outStatusDescription = Unknown]
	Defaults --> Part2[ATM.IsParticipant]
	Part2 --> IsPart{Participant?}
	IsPart -->|No| KeepDefaults([Return -1 / Unknown])
	IsPart -->|Yes| GetStatus[ATM.GetStatusCode]
	GetStatus --> Translate[ATM.TranslateStatusCode]
	Translate --> StatusResult([Return status code<br>and description])
	Which -->|TranslateStatusCode| Trans[ATM.TranslateStatusCode]
	Trans --> TransResult([Return description string])
	NonPart --> Logoff[LogoffATM:<br>release token, dispose proxy]
	PartOk --> Logoff
	Logoff --> Done([Return result])
	StatusResult --> Logoff2[LogoffATM]
	TransResult --> Logoff3[LogoffATM]
```

## Failure and edge-case behavior
- If the ATM logon fails repeatedly, the caller receives an `ApplicationException` after `m_LogonAttemptsMax` retries ([BR-002](../business-rules.md#br-002-vendor-logon-retry-handling)); no ATM check is attempted for any of the three methods.
- `IsATMParticipant` is the only one of the three methods that wraps the vendor call in `Try/Catch`: a `SoapException` resolves to `False` ([BR-005](../business-rules.md#br-005-atm-participation-faults-resolve-to-non-participant)) and `LogoffATM()` is guaranteed via `Finally`.
- `GetATMAccountStatus` has no exception handling around `ATM.IsParticipant`, `ATM.GetStatusCode`, or `ATM.TranslateStatusCode`; a vendor fault propagates unhandled and `LogoffATM()` is skipped, unlike `IsATMParticipant`.*
- `GetATMAccountStatus` returns `-1` and `"Unknown"` specifically when the routing number is not an ATM participant ([BR-004](../business-rules.md#br-004-non-participating-banks-return-unknown-atm-status)) — a different code path from the `SoapException` handling in `IsATMParticipant` ([BR-005](../business-rules.md#br-005-atm-participation-faults-resolve-to-non-participant)); the two rules must not be conflated.
- `TranslateStatusCode` has no participation check and no exception handling; it assumes the caller already has a valid status code from a prior `GetATMAccountStatus` call.*
- `LogoffATM` failures are intentionally swallowed and never surface to the caller.*
- Historical source comments note the ATM web service was discontinued by the vendor as of 11/30/2006 and re-enabled as of 01/08/2007; the current code paths reflect the re-enabled, fully functional service.

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `Legacy\BankValidator\clsValidateBank.vb`
