---
title: Recurring ACH authorization lifecycle
summary: Establishes a variable recurring ACH payment authorization at US Bank, amends its amount and due date, or cancels it.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.EPay.USBank
reference_type: package
operation_id: OP-EPAY-03
trigger: Caller invokes EstablishRecurringAuthorization, UpdateRecurringAuthorizationAmountAndDate, or StopRecurringPayment/CancelPayment
---

# Recurring ACH authorization lifecycle

This operation covers the three related calls that manage a single recurring ACH authorization at US Bank across its lifetime: establishing it (`EstablishRecurringAuthorization`, a "VARP" — variable recurring payment — request), amending its amount and due date (`UpdateRecurringAuthorizationAmountAndDate`), and cancelling it (`StopRecurringPayment`, which delegates to the shared `CancelPayment`). They are grouped here because all three operate on the same recurring-payment concept and share the biller-credential and web-service-client plumbing, even though each calls a distinct US Bank SOAP method.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-EPAY-03 |
| **Trigger** | Caller invokes `USBankAPIs.EstablishRecurringAuthorization`, `USBankAPIs.UpdateRecurringAuthorizationAmountAndDate`, or `USBankAPIs.StopRecurringPayment`/`CancelPayment` |
| **Inputs** | Establish: US Bank user, policy number/name, bank account, voluntary flag. Update: US Bank user or sequence number, amount, payment date, voluntary flag. Cancel: payment/recurring confirmation ID, voluntary flag |
| **Outputs** | Establish: payment confirmation ID (string). Update: none (void; throws on failure). Cancel: boolean success |
| **Primary components** | `USBankAPIs.EstablishRecurringAuthorization`, `USBankAPIs.GetFilledVarpRecurringPaymentRequest`, `USBankAPIs.GetFilledRecurringACHPayMethod`, `USBankAPIs.UpdateRecurringAuthorizationAmountAndDate`, `USBankAPIs.CancelPayment`, `USBankAPIs.StopRecurringPayment` |
| **Entry point** | `Business\SAIF.Business.EPay.USBank\USBankAPIs.vb` |

## Steps

1. **Establish — classify and normalize the bank account.** `GetFilledRecurringACHPayMethod` sets the account category (business/consumer) and account type (checking/savings) from the bank account's flags, decrypts and strips spaces from the account number and routing number, and shortens the normalized nickname to 20 characters ([BR-012](../business-rules.md#br-012-bank-account-payloads-require-category-and-type)).
   - If neither category flag or neither type flag is set: throw `ApplicationException` (`"Bank account must be business or consumer"` / `"...checking or savings"`).
2. **Establish — build the VARP request.** `GetFilledVarpRecurringPaymentRequest` sets the biller credential, uses the US Bank user's sequence number as the doubling-posting token, sets an unbounded duration (`continueUntilCancelled`), an on-the-due-date frequency, a zero-day lead time, and a web payment channel, attaches the normalized ACH pay method from step 1, resolves the recurring-payments product code, and adds `PolicyNumber` and `PolicyName` (normalized and shortened to 40 characters) as product parameters.
3. **Establish — call the SOAP client.** `VarpRecurringPayment` is invoked with the built request.
   - On a transport failure: wrap and re-throw as an `ApplicationException`.
   - On a non-zero response code: throw an `ApplicationException` including the response message, US Bank user sequence number, and policy number.
   - On success: return `RPResponse.paymentConfirmationId` to the caller.
4. **Update — build the payment-info request.** `GetFilledUpdatePaymentInfoRequest` sets the amount due, due date, biller credential, recurring-payments product code, and the target user ID from either the `IUSBankUser` overload or the raw sequence-number overload.
5. **Update — call the SOAP client.** `UpdatePaymentInfo` is invoked with the built request.
   - On a transport failure: wrap and re-throw as an `ApplicationException`.
   - On a non-zero response code: throw an `ApplicationException` including the response message, US Bank user sequence number, amount, and payment date.
6. **Cancel — build the cancel request.** The private `CancelPayment` overload sets the biller credential and the confirmation ID to cancel (used for both one-time payment cancellation and recurring-authorization stop, since `StopRecurringPayment` is a thin wrapper over the same call).
7. **Cancel — call the SOAP client.** `CancelPayment` is invoked on the client.
   - On a transport failure: wrap and re-throw as an `ApplicationException`.
   - On a non-zero response code: throw an `ApplicationException` with the response message.
   - On success: return `True`.

## Process flow

The following diagram visualizes the three related flows sharing this operation.

```mermaid
flowchart TD
	Start{Which recurring<br>action?}
	Start -->|Establish| EClass[Classify and normalize<br>bank account]
	EClass --> EBuild[Build VarpRecurringPaymentRequest]
	EBuild --> ECall[Call VarpRecurringPayment]
	ECall --> ECode{Response code = 0?}
	ECode -->|No| EFail([Throw ApplicationException])
	ECode -->|Yes| EOk([Return payment confirmation ID])
	Start -->|Update amount/date| UBuild[Build UpdatePaymentInfoRequest]
	UBuild --> UCall[Call UpdatePaymentInfo]
	UCall --> UCode{Response code = 0?}
	UCode -->|No| UFail([Throw ApplicationException])
	UCode -->|Yes| UOk([Return: update applied])
	Start -->|Cancel/Stop| CBuild[Build CancelPaymentRequest<br>with confirmation ID]
	CBuild --> CCall[Call CancelPayment]
	CCall --> CCode{Response code = 0?}
	CCode -->|No| CFail([Throw ApplicationException])
	CCode -->|Yes| COk([Return True])
```

## Failure and edge-case behavior

- Missing or ambiguous bank-account category/type on the establish path throws before any SOAP call is made ([BR-012](../business-rules.md#br-012-bank-account-payloads-require-category-and-type)).
- All three sub-flows throw on transport failure and on any non-zero response code; none of them return a handled "duplicate" or "not found" outcome the way `AddBankAccount` does for duplicate accounts.*
- `StopRecurringPayment` and one-time `CancelPayment` share the exact same private implementation, so a caller providing the wrong kind of confirmation ID (payment vs. recurring reference) would still reach the same US Bank cancel call; the library performs no local check to distinguish them.*
- The establish request's `PolicyName` product parameter is truncated to 40 characters after normalization, so very long policy names lose trailing text in what US Bank displays for the recurring authorization.*

> **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)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources

- `Business\SAIF.Business.EPay.USBank\USBankAPIs.vb`
