Migration guide
Restructured fees object (from 2025-01-01)
In 2025-01-01 and earlier, Fees carried flat fields whose meaning depended on the feesCollected boolean: true meant the figures were personalized to the customer (with their actual discounts), false meant generic / list-price fallback figures. 2026-04-01 splits these two modes into separate, mutually-exclusive sub-objects and removes the flag.
fees.personalized(PersonalizedFees) — values personalized to the holder, including the holder's actual discounts. Present when the source exposes per-holder fee data.fees.generic(GenericFees) — generic / list-price mapping, not personalized to the holder and likely missing discounts. Present when per-holder fee data is unavailable.- Exactly one of
fees.personalized/fees.genericis present per response; its presence is the personalized-vs-generic signal. previousYear(last year's actual total fees paid) exists only onpersonalized; it is not meaningful for the generic / list-price side.- The
feesobject is absent entirely when no fee data — neither personalized nor generic — is available for the product. variableremains a decimal ratio in[0, 1](e.g.0.0065= 0.65%) — same representation as the oldfeeVariable, no unit change.
// personalized — per-holder figures with actual discounts
{
"fees": {
"personalized": {
"fixed": { "amount": 100, "currency": "SEK" },
"variable": 0.0065,
"previousYear": { "amount": 513, "currency": "SEK" }
}
}
}
// generic — list-price mapping, no previousYear
{
"fees": {
"generic": {
"fixed": { "amount": 100, "currency": "SEK" },
"variable": 0.0065
}
}
}Field mapping
| 2025-01-01 | 2026-04-01 |
|---|---|
fees.feesCollected: true | values move under fees.personalized (object present) |
fees.feesCollected: false | values move under fees.generic (object present) |
fees.feeFixed | fees.personalized.fixed or fees.generic.fixed |
fees.feeVariable | fees.personalized.variable or fees.generic.variable (units unchanged) |
fees.feesPreviousYear | fees.personalized.previousYear only (dropped on the generic branch) |
fees.feesCollected (the flag) | removed — replaced by which sub-object is present |
Steps
- Replace the
feesCollectedbranch with a presence check. Instead of readingfees.feesCollectedand thenfees.feeFixed/fees.feeVariable, check which sub-object exists:fees.personalizedpresent → use personalized figures;fees.genericpresent → use generic figures;feesabsent → no fee data for this product. - Rename the leaf fields:
feeFixed→fixed,feeVariable→variable(now nested under the chosen sub-object).variablesemantics and units are unchanged. feesPreviousYear→personalized.previousYear. It is only available on the personalized branch. The previousfeesCollected: false+feesPreviousYearcombination no longer exists — generic responses carry no previous-year total.- Handle the absent
feesobject. Earlier versions effectively always returned afeesobject;2026-04-01omits it when there is no fee data, so guard forfeesbeing undefined.
// 2025-01-01
const fees = product.fees;
const personalized = fees.feesCollected === true;
const fixed = fees.feeFixed;
const variable = fees.feeVariable;
// 2026-04-01
const fees = product.fees; // may be undefined
const personalized = !!fees?.personalized;
const figures = fees?.personalized ?? fees?.generic; // undefined if no fee data
const fixed = figures?.fixed;
const variable = figures?.variable;
const previousYear = fees?.personalized?.previousYear; // personalized onlyCollections are now a top-level resource (from 2025-01-01)
In 2025-01-01 a wealth collection lived under the product namespace: it was created at POST /wealth/collection and read under /wealth/collection/{collectionId}/... (insurance collections lived under /insurance/collection/...). In 2026-04-01 collections become a single shared, top-level resource. A collection is created at POST /collections regardless of product, and the wealth data is read from a product sub-path — /collections/{collectionId}/wealth/data, mirroring the Insurance API's /collections/{collectionId}/insurance/data.
Endpoint mapping
2025-01-01 (wealth) | 2026-04-01 |
|---|---|
POST /wealth/collection | POST /collections (shared across products) |
GET /wealth/collection/{collectionId}/status | GET /collections/{collectionId}/status |
GET /wealth/collection/{collectionId}/data | GET /collections/{collectionId}/wealth/data |
POST /wealth/collection/{collectionId}/supplement-info | POST /collections/{collectionId}/supplement-info |
Typed request parameters
POST /collections replaces the untyped 2025-01-01 request body — a loginMethod plus an input map keyed by uppercase strings, with separate top-level consents and filter arrays — with a single typed parameters array. Each entry carries a type discriminator and its own named, lower-camelCase fields.
- Credentials become typed parameters (
SWEDISH_BANKID,EMAIL) instead of keys ininput. - Consents are explicit, typed parameters. PSD2 Account Information Service consent is new in this version — supply it as a Psd2AisConsentParameter (
type: PSD2_AIS_CONSENT), or reference a previously-authorized consent with a StoredConsentParameter. This replaces the untypedconsentsarray. - SST / session identifiers (
SESSION_ID,ADVISOR_HANDLE,EXTERNAL_REFERENCE) move from inlineinputkeys into aSESSION_METADATAparameter'sattributesmap.
// 2025-01-01
{
"company": "se-avanza",
"loginMethod": "SWEDISH_MOBILE_BANKID_OTHER_DEVICE",
"input": { "SWEDISH_PERSONAL_NUMBER": "199001011234" }
}
// 2026-04-01
{
"company": "se-avanza",
"loginMethod": "SWEDISH_MOBILE_BANKID_OTHER_DEVICE",
"parameters": [
{ "type": "SWEDISH_BANKID", "personalNumber": "199001011234" }
]
}Login methods (Sweden)
The loginMethod enum values are unchanged; only the shape of the credential payload changes. Each method now carries its credential in a typed parameter rather than in the input map:
| Login method | 2025-01-01 input | 2026-04-01 parameter |
|---|---|---|
SWEDISH_MOBILE_BANKID_SAME_DEVICE / …_OTHER_DEVICE / …_ANY_DEVICE / …_SAME_DEVICE_CLIENT_SIDE_AUTHENTICATION / SWEDISH_SECURITY_TOKEN | { "SWEDISH_PERSONAL_NUMBER": "…" } | { "type": "SWEDISH_BANKID", "personalNumber": "…" } |
EMAIL | { "USERNAME": "…" } | { "type": "EMAIL", "email": "…" } |
All Swedish BankID variants — including the _TEST (BankID sandbox) and _MOCK (deterministic, short-circuited) flows — reuse the same SwedishBankIdParameter (type: SWEDISH_BANKID); switch environments by changing only the loginMethod.
Steps
- Repoint the base path. Replace
/wealth/collectionwith/collections, and read data from/collections/{collectionId}/wealth/datainstead of/wealth/collection/{collectionId}/data. Status and supplement-info keep the same suffixes under the new prefix. - Convert the request body. Move each
inputkey into a typed entry in theparametersarray (e.g.SWEDISH_PERSONAL_NUMBER→{ "type": "SWEDISH_BANKID", "personalNumber": … }). - Move consents and session data into parameters. Replace the
consentsarray with the relevant typed consent parameter, and moveSESSION_ID/ADVISOR_HANDLE/EXTERNAL_REFERENCEinto aSESSION_METADATAparameter'sattributes.