Account Discovery
Account Discovery
After a user authenticates, myProp calls the AgentOS API to discover which portal accounts are linked to that user's email address. A single user can hold multiple roles simultaneously — for example, the same person could be both a landlord and a buyer at the same agency.
How It Works
Account discovery makes a single API call to the AgentOS unified accounts endpoint:
GET /{clientName}/accounts?emailAddress={email}
The response is normalised into a list of PortalAccount objects, each carrying a type, accountId, displayName, email, isActive flag, branchId, and a metadata bag containing additional fields from the original record.
This matches the original Lambda BFF outbound call pattern exactly.
Supported Account Types
AgentOS returns accounts with a string AccountType field. The portal maps these to normalised roles:
AgentOS AccountType | Portal role |
|---|---|
LettingsLandlord | landlord |
LettingsTenant | tenant |
LettingsProspect | tenant |
SalesApplicantBuyer | buyer |
SalesVendor | vendor |
MaintenanceContractor | contractor |
LettingsProspect is mapped to tenant because prospect tenants participate in the same tenant workflow within the portal. Any AccountType value not in the table above is silently filtered out.
Response Formats
The /accounts endpoint may return one of two shapes. Both are handled transparently:
Flat array:
[
{ "AccountType": "LettingsLandlord", "OID": "abc-123", ... },
{ "AccountType": "SalesApplicantBuyer", "OID": "def-456", ... }
]
Paged wrapper:
{
"Data": [
{ "AccountType": "LettingsLandlord", "OID": "abc-123", ... }
],
"Count": 1
}
Account Metadata
Each discovered PortalAccount includes a metadata object that preserves the following fields from the original AgentOS record (in addition to any other fields returned):
| Metadata key | AgentOS field |
|---|---|
oid | OID |
globalReference | GlobalReference |
accountType | AccountType |
accountReference | AccountReference |
branch | Branch |
companyShortName | CompanyShortName |
companyMarketingName | CompanyMarketingName |
companyLogo | CompanyLogo |
Display Name Resolution
The portal resolves a human-readable display name from the account record using the following priority order:
NameDisplayNameForename+Surname(concatenated)Title"Unknown"(fallback)
Error Handling
If the API call itself fails, discoverAccounts() returns an empty accounts array and a single entry in the errors array describing the failure. The error is also forwarded to the platform's error capture system with domain: "account-discovery" metadata.
If discovery succeeds but a specific record has an unrecognised AccountType, that record is silently dropped — it does not produce an error.
Public API
import {
discoverAccounts,
discoverAccountsByType,
isAccountDiscoveryAvailable,
type PortalAccount,
type AccountDiscoveryResult,
} from "@/lib/letmc/accounts";
// Discover all accounts for an email address
const result: AccountDiscoveryResult = await discoverAccounts(
"user@example.com",
"my-agency"
);
// result.accounts => [{ type: "landlord", accountId: "abc-123", ... }, ...]
// result.errors => [] (empty on success)
// Discover accounts of a specific type
const landlords = await discoverAccountsByType(
"landlord",
"user@example.com",
"my-agency"
);
The BFF compatibility endpoint /api/bff/accounts calls discoverAccounts() internally and is unaffected by this change.