ACORD XML Protocol
All Safeco Auto communication uses ACORD XML transmitted over HTTPS. Internally, the XML is represented as JSON (converted by SafecoV3XmlConverterService) so all mapping and manipulation happens in JS objects.
Transaction Types
| Transaction | Type Value | Sub-Transaction | Purpose |
|---|---|---|---|
| RC1 | RateCall1 | — | Plain rate call (establish quote, get UUIDs) |
| RC1 + CC | RateCall1 | com.safeco_ReconcileCC | Prior insurance verification (CLUE) |
| RC1 + ADD | RateCall1 | com.safeco_ReconcileADD | Additional driver discovery |
| RC2 | RateCall2 | com.safeco_ReconcileADD | Final rating with MVR/CLUE ordering and driver reconciliation |
| RC3 | RateCall3 | com.safeco_Bind | Bind policy with payment |
ACORD Envelope Structure
ACORD
├── SignonRq
│ ├── SignonPswd → CustId → CustLoginId (agent login)
│ └── ClientApp → Org, Name, Version
└── InsuranceSvcRq
├── RqUID (unique request ID)
└── PersAutoPolicyQuoteInqRq
├── com__safeco_TransactionType
├── com__safeco_SubTransactionType (optional)
├── TransactionRequestDt
├── InsuredOrPrincipal (named insured)
├── PersPolicy
│ ├── ContractTerm (EffectiveDt, ExpirationDt, DurationPeriod)
│ ├── QuoteInfo (CompanysQuoteNumber, com.safeco_CompanyURL)
│ └── PaymentOption (for RC3 bind)
├── PersAutoLineBusiness
│ ├── LOBCd: "AUTOP"
│ ├── PersDriver[] (drivers with IDs, DOB, license, relation)
│ ├── PersVeh[] (vehicles with VIN, year, make, model, garaging)
│ ├── Coverage[] (coverages with codes and limits)
│ └── Discount[] (discount codes and amounts)
├── Location[] (garaging addresses)
└── CreditScoreInfo (IBS consent)
Entity References
Safeco assigns internal IDs to drivers, vehicles, and locations on the first RC1 call. These IDs must be preserved across all subsequent calls.
carrier_quote_sessions.metadata.entityRefs = {
drivers: { driver_1: "safeco-id-abc", driver_2: "safeco-id-def" },
vehicles: { vehicle_1: "safeco-id-123", vehicle_2: "safeco-id-456" },
locations: { location_1: "safeco-id-loc1" }
}
Entity refs are extracted after each RC1 call via extractQuoteSessionFromResponse() and merged with existing refs. New refs overwrite by key; existing refs are preserved.
Source: libs/apis/carriers/safeco/src/v3/application/utils/safeco-session.extractor.ts
Full Rate Flow (4 Steps)
RC1 + CC (Prior Insurance Verification)
Runs a CLUE report to verify prior insurance history. The sub-transaction com.safeco_ReconcileCC triggers Safeco to order a Comprehensive Claims (CC) report.
Response codes (com__safeco_CLUEOrderResult):
| Code | Meaning |
|---|---|
C | Clean — no prior claims |
H | Hits — prior claims found |
N | No hit — no record found |
E | Error ordering report |
999 | System error |
RC1 + ADD (Additional Driver Discovery)
Discovers undisclosed household drivers. Safeco returns DriverCandidate entries that must be reconciled in RC2.
For RC2, discovered drivers are injected with:
com__safeco_DriverCandidateType: 'N'(not adding)com__safeco_AddAction: 'N'(decline to add)
RC2 (Final Rating)
Before sending RC2, the service validates ~14 required fields:
| Field | Validation |
|---|---|
| TransactionType | Must be RateCall2 |
| EsignYN | Must be present |
| PaperlessBillingYN | Must be present |
| AgentEmailAddress | Must be present |
| NIPRId | Must be present |
| ContractNumber / RqUID | Must be present |
| Insured name + DOB | Must be present |
| Address | Must be present |
| CreditScoreInfo (IBS) | Must be present |
| LOBCd | Must be AUTOP |
| EffectiveDt | Must be present |
| Drivers | Count > 0 |
| Vehicles | Count > 0 |
MVR response codes (com__safeco_MVROrderResult):
| Code | Meaning |
|---|---|
C | Clean record |
H | Hits — violations found |
N | No record found |
E | Error ordering report |
999 | System error |
RC3 (Bind)
RC3 preparation:
- Clone RC2 quote data
- Set
TransactionType = 'RateCall3',SubTransactionType = 'com.safeco_Bind' - Remove
MsgStatus(response-only field) - Add
PaymentOptiontoPersPolicywith Hydra instrument and plan details
Response Parsing
All rate responses are parsed through parseRateResponse():
| Extracted Data | ACORD Path |
|---|---|
| Status | ACORD.Status.StatusCd (0 = success) |
| Message status | PersAutoPolicyQuoteInqRs.MsgStatus.MsgStatusCd |
| Extended errors | MsgStatus.ExtendedStatus[].ExtendedStatusDesc |
| Quote number | PersAutoPolicyQuoteInqRs.RqUID |
| Policy number | PersAutoPolicyQuoteInqRs.PolicyNumber |
| FullTermAmt | Sum of PersVeh[].FullTermAmt.Amt |
| Policy term | PersPolicy.ContractTerm.DurationPeriod.NumUnits |
| Coverages | PersAutoLineBusiness.Coverage[] |
| Discounts | PersAutoLineBusiness.Discount[] |
| Payment plans | PersPolicy.PaymentOption[] |
| Safeco URL | com.safeco_CompanyURL |
API Client
Implementation: libs/apis/carriers/safeco/src/v3/infrastructure/api/safeco-v3-api.client.ts
| Config | Env Variable |
|---|---|
| RC1/RC2 endpoint | SAFECO_RC1_RC2_URL |
| RC3 (bind) endpoint | SAFECO_RC3_URL |
| Attribution ID | SAFECO_RC1_RC2_ATTRIBUTION_ID |
| Timeout | SAFECO_API_TIMEOUT (default 30s) |
Auth: Bearer token from SafecoV3AuthService → Switchboard OAuth (SwitchboardTokenManagerService).
Headers: Authorization, Content-Type: application/xml, Accept: application/xml, x-partner-attribution-id.
Retry: On 401, clears cached token and retries once.
Logging: Request/response XML and JSON logged to logs/api/ with timestamps.
Field Mapper
SafecoV3FieldMapperService converts GHCMS session data into the ACORD XML structure:
| Session Data | ACORD Target |
|---|---|
| Applicant name, DOB, SSN | InsuredOrPrincipal |
| Drivers (license, relation) | PersDriver[] |
| Vehicles (VIN, year, make, model) | PersVeh[] |
| Garaging addresses | Location[] |
| Prior policy info | PriorPolicy on PersAutoLineBusiness |
| Coverages (BI, PD, UM, PIP) | Coverage[] |
| Policy info (effective date, term) | PersPolicy.ContractTerm |
| Agent NPN | NIPRId |
| E-sign acceptance | com__safeco_EsignYN |
| Excluded drivers | com__safeco_ExcludedDriverInputs |
Source: libs/apis/carriers/safeco/src/v3/infrastructure/mapping/safeco-v3-field-mapper.service.ts