---
title: Register or update a US Bank user
summary: Looks up or creates the local US Bank user record for a policy/business-online-user pair, calls the matching US Bank profile SOAP operation, and saves any local name changes.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.EPay.USBank
reference_type: package
operation_id: OP-EPAY-01
trigger: Caller invokes USBankAPIs.RegisterUser(inDPI, inUserInfo, inPolicyInfo)
---

# Register or update a US Bank user

Register-or-update is the single entry point callers use to make sure a SAIF policy/business-online-user pair has a matching US Bank profile. It first checks for an existing local record; if none exists, it creates one locally and adds the user at US Bank, otherwise it optionally refreshes the profile at US Bank. Either way it finishes by writing any first-name/last-name changes to the local `US_BANK_USER` row.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-EPAY-01 |
| **Trigger** | Caller invokes `USBankAPIs.RegisterUser(inDPI, inUserInfo, inPolicyInfo)` |
| **Inputs** | `IDataPortalInfo`; `IUserInfoProvider` (business-online user ID, name, email, phone); `IPolicyInfoProvider` (policy number, policy name, address, voluntary/assigned-risk flag) |
| **Outputs** | A `clsUSBankUser` reflecting the current (possibly newly created) local record, with a US Bank profile that has been added or refreshed |
| **Primary components** | `USBankAPIs.RegisterUser`, `USBankAPIs.AddUserToUSBank`, `USBankAPIs.UpdateUserToUSBank`, `clsUSBankUser.GetUSBankUser`, `clsUSBankUser.NewUSBankUser`, `clsUSBankUser.Save` |
| **Entry point** | `Business\SAIF.Business.EPay.USBank\USBankAPIs.vb` |

## Steps

1. **Look up the local user record.** `RegisterUser` calls `clsUSBankUser.GetUSBankUser(inDPI, policyNumber, businessOnlineUserId)`, which retrieves by policy number and a case-insensitive comparison on the business-online user ID ([SQL-008](../sql/SQL-008-retrieve-us-bank-user-by-policy-and-business-online-user.md), [US_BANK_USER](../database-tables.md#us_bank_user)) ([BR-009](../business-rules.md#br-009-user-lookup-is-case-insensitive)).
2. **Branch on whether a record was found.** `USBankUser.IsValid` reflects whether the retrieve found a row.
   - If invalid (no local record): go to step 3 (create path).
   - If valid (local record exists): go to step 6 (refresh path).
3. **Create path — allocate a new local user.** `clsUSBankUser.NewUSBankUser` builds a criteria with the policy number and business-online user ID and calls the BOF `Create()`, which allocates a new sequence value ([SQL-002](../sql/SQL-002-select-us-bank-user-sequence.md), [DUAL](../database-tables.md#dual)) and seeds the policy number and business-online user ID in memory ([BR-001](../business-rules.md#br-001-business-online-user-id-is-required), [BR-002](../business-rules.md#br-002-policy-number-is-required)).
4. **Create path — add the profile at US Bank.** `AddUserToUSBank` builds an `AddUserProfileRequest` from the policy address, policy name, user's email/first/last name, the new user's sequence number as the US Bank user ID, and the policy ZIP code as the shared-secret answer ([BR-016](../business-rules.md#br-016-shared-secret-answers-use-the-policy-zip-code)), then calls `AddUserProfile` on the SOAP client.
   - On a SOAP call failure (exception): wrap and re-throw as an `ApplicationException`.
   - On a non-zero response code: throw an `ApplicationException` including the concatenated response messages and a labeled dump of the request data.
5. Continue to step 8 (shared save step) after the create-and-add path completes.
6. **Refresh path — check whether update is enabled.** If `USBankCodes.IsUpdateUSBankUserProfileAvailable` (config flag `USE_US_BANK_UPDATE_USER_PROFILE_API`) is false, skip the US Bank call entirely and go directly to step 8; only the local save (if any) will run.
7. **Refresh path — update the profile at US Bank.** `UpdateUserToUSBank` builds an `UpdateUserProfileRequest` (address, policy name, email, first/last name, the same shared-secret ZIP answer) and calls `UpdateUserProfile`.
   - On the first call throwing: sleep 1500ms and retry the call once.
     - If the retry also throws: send a failure email to `USBankCodes.ErrorEmailAddress` describing the exception and request data, and continue without raising an exception ([BR-019](../business-rules.md#br-019-update-user-profile-failures-are-retried-once-then-reported-by-email-instead-of-failing-the-call)).
   - If a response was obtained (retry not needed, or succeeded) and its response code is non-zero: throw an `ApplicationException` with the concatenated response messages and request data.
8. **Apply local name changes.** Regardless of path, `RegisterUser` sets `USBankUser.FirstName` and `USBankUser.LastName` from `inUserInfo`, which marks the object dirty only if the values actually changed.
9. **Save the local record if dirty.** If `USBankUser.IsDirty`:
   - If `USBankUser.IsValid`: call `Save()`.
     - New object → BOF insert path ([SQL-004](../sql/SQL-004-insert-us-bank-user.md), [US_BANK_USER](../database-tables.md#us_bank_user)) enforcing [BR-003](../business-rules.md#br-003-user-inserts-must-affect-exactly-one-row); this is the persistence logic documented in full in [Persist and retrieve SAIF-side integration records](saif-side-user-and-notice-persistence.md).
     - Existing object → BOF update path ([SQL-011](../sql/SQL-011-update-us-bank-user.md), [US_BANK_USER](../database-tables.md#us_bank_user)) enforcing [BR-004](../business-rules.md#br-004-user-updates-must-affect-exactly-one-row).
     - If `Save()` returns false: throw `ApplicationException("clsUSBankUser.Save failed.")`.
   - If not valid: throw `ApplicationException("Unable to save clsUSBankUser - not valid.")` ([BR-001](../business-rules.md#br-001-business-online-user-id-is-required), [BR-002](../business-rules.md#br-002-policy-number-is-required)).
10. **Return the user object.** `RegisterUser` returns the (possibly newly persisted) `clsUSBankUser` to the caller.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([RegisterUser dpi, userInfo, policyInfo]) --> Lookup[Retrieve local user by<br>policy and business-online user]
	Lookup --> Found{Local record found?}
	Found -->|No| Create[Create local user;<br>allocate sequence]
	Create --> AddBank[Call AddUserProfile at US Bank]
	AddBank --> ApplyNames[Apply FirstName/LastName]
	Found -->|Yes| UpdEnabled{Update API enabled?}
	UpdEnabled -->|No| ApplyNames
	UpdEnabled -->|Yes| UpdateBank[Call UpdateUserProfile]
	UpdateBank --> UpdFail{Call failed?}
	UpdFail -->|Yes, retry also fails| Email([Send failure email;<br>continue without exception])
	UpdFail -->|No, or retry succeeded| ApplyNames
	Email --> ApplyNames
	ApplyNames --> Dirty{Object dirty?}
	Dirty -->|No| Done([Return user object])
	Dirty -->|Yes| Valid{Object valid?}
	Valid -->|No| Err([Throw: not valid])
	Valid -->|Yes| Save[Save: insert or update]
	Save --> SaveOk{Save succeeded?}
	SaveOk -->|No| Err2([Throw: Save failed])
	SaveOk -->|Yes| Done
```

## Failure and edge-case behavior

- A missing business-online user ID or a zero policy number leaves the object invalid, so the create path is skipped and the final save throws rather than silently doing nothing ([BR-001](../business-rules.md#br-001-business-online-user-id-is-required), [BR-002](../business-rules.md#br-002-policy-number-is-required)).
- The retry-then-email behavior on `UpdateUserProfile` means a caller cannot distinguish "profile refreshed" from "refresh silently failed and was emailed" from the return value alone ([BR-019](../business-rules.md#br-019-update-user-profile-failures-are-retried-once-then-reported-by-email-instead-of-failing-the-call)).
- When the update API is disabled by configuration, an existing local user's US Bank profile is never refreshed by this operation, even if the caller's name or address data has changed.*
- `AddUserProfile` failures (transport or non-zero response code) always throw, unlike `UpdateUserProfile`, so create-path failures are never silently swallowed.
- The password sent to US Bank (`clsUSBankUser.Password`) is a hardcoded literal value rather than a caller-supplied or generated secret.*

> **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`
- `Business\SAIF.Business.EPay.USBank\clsUSBankUser.vb`
- `Business\SAIF.Business.EPay.USBank\USBankCodes.vb`
