swedbank-json
v1.0.1
Published
Node.js Swedbank API client (unofficial) based on walle89/swedbank-json
Maintainers
Readme
swedbank-json
A modern TypeScript port of walle89/SwedbankJson that interacts with Swedbank's mobile APIs. It supports Mobile BankID QR login, session caching, cookie management, account overview, transaction previews, and complete transaction history with pagination.
This project is not affiliated with Swedbank or Sparbanken. Use for personal/educational purposes only.
Table of Contents
- Features
- Installation
- Authentication: Mobile BankID QR Login
- Fetch Accounts
- Fetch Transactions
- Directory Structure
- Environment Variables
- Error Handling
- Debug Logging
- Full API Reference
- Contributing
- License
Features
- Mobile BankID QR and same-device login
- Session caching & cookie persistence (persist the returned session to skip QR on the next run)
- Built-in Mobile app headers (User-Agent, X-Client, Authorization) with AppData cache
- Accounts overview, reminders, savings portfolios
- Transaction preview (
accountTransactions) and full history pagination (getFullTransactionHistory) - Transfers, quick balance subscriptions, and transaction detail lookups
- Written in modern TypeScript with rich TSDoc for IDEs
Installation
npm install swedbank-jsonTypeScript/ESM import:
import { loginWithBankID, SwedbankClient } from "swedbank-json";CommonJS require:
const { loginWithBankID, SwedbankClient } = require("swedbank-json");Authentication: Mobile BankID QR Login
import { loginWithBankID, SwedbankClient } from "swedbank-json";
async function main() {
const { auth, session } = await loginWithBankID({
personnummer: "YYYYMMDDXXXX", // optional for QR, required for same-device
bankApp: "sparbanken",
cachePath: "./cache/session.json", // where you persist the session/AppData cache
sameDevice: false, // set true to deep-link to the BankID app instead of QR
});
// Render QR by polling in your own loop (pseudo):
const status = await auth.pollStatus();
console.log(status.imageChallengeData); // base64 for animated QR frames
await auth.verify(); // waits for COMPLETE
const client = new SwedbankClient(auth);
const accounts = await client.accountList();
console.log(accounts.transactionAccounts.map((a: any) => a.name));
}Valid bankApp values: swedbank, sparbanken, savingsbank, swedbank_foretag, sparbanken_foretag.
Session caching behavior
loginWithBankIDreturns{ auth, session }. Persistsessionto disk (e.g.,fs.writeFileSync("./cache/session.json", JSON.stringify(session))).- On the next run, load the JSON and pass it to
new SwedbankClient(loadedSession)to reuse cookies/user agent without scanning a new QR (until Swedbank expires the session). - App metadata (User-Agent/AppID) is also cached to the
cachePathso repeat runs avoid remote lookups.
Cookie handling
- All Set-Cookie headers are merged into the in-memory session and reused on subsequent requests.
- When you persist
session, those cookies are preserved and replayed when you reconstructSwedbankClientwith the saved session.
Fetch Accounts
const client = new SwedbankClient(auth);
const overview = await client.accountList();
// Transaction accounts
for (const account of overview.transactionAccounts) {
console.log(`${account.name} (${account.id}) -> balance: ${account.balance.amount} ${account.balance.currency}`);
}
// Savings/investments
if (overview.savingsAccounts) {
console.log(`You have ${overview.savingsAccounts.length} savings accounts`);
}Account categories commonly present in engagement/overview:
transactionAccounts: Current/checking accountssavingsAccounts: Savings & investment accountscardAccounts: Credit card accountsloans: Loan products (mortgage, consumer loans)
Fetch Transactions
Basic preview (single page):
const accountId = overview.transactionAccounts[0].id;
const page = await client.accountTransactions(accountId, 40, 1);
console.log(page.transactions.length); // Up to ~40, depending on the API defaultFull history with pagination (recommended):
const allTransactions = await client.getFullTransactionHistory(accountId);
console.log(`Fetched ${allTransactions.length} transactions`);
// Example: find the latest card charge
const latestCard = allTransactions.find((t) => t.type === "CARD");
console.log(latestCard);getFullTransactionHistory follows Swedbank's links.next.uri pagination until moreTransactionsAvailable is false, so you get the complete list the API exposes.
Directory Structure
├─ src/ # TypeScript sources with rich TSDoc
│ ├─ auth/ # Mobile BankID, security token, and unauth flows
│ ├─ swedbank/ # SwedbankClient and high-level banking helpers
│ ├─ http/ # HTTP wrapper with headers/cookies
│ ├─ appdata/ # AppData cache (User-Agent/AppID)
│ └─ index.ts # Public entrypoint (loginWithBankID, exports)
├─ dist/ # Compiled JavaScript + type declarations (npm publishes this)
├─ cache/ # (suggested) store session JSON and AppData cache here
├─ test/ # Vitest tests
├─ package.json
├─ tsconfig.json
└─ README.mdEnvironment Variables
.env example (with dotenv):
SWEDBANK_PERSONNUMMER=YYYYMMDDXXXX
SWEDBANK_BANKAPP=sparbanken
SWEDBANK_CACHE_PATH=./cache/session.json
SWEDBANK_SAME_DEVICE=false
SWEDBANK_DEBUG=1Usage:
import "dotenv/config";
import { loginWithBankID } from "swedbank-json";
const { auth } = await loginWithBankID({
personnummer: process.env.SWEDBANK_PERSONNUMMER,
bankApp: process.env.SWEDBANK_BANKAPP || "swedbank",
cachePath: process.env.SWEDBANK_CACHE_PATH || "./cache/session.json",
sameDevice: process.env.SWEDBANK_SAME_DEVICE === "true",
});Error Handling
Common errors thrown by the client:
Unable to use Mobile BankID. Check if the user has enabled Mobile BankID.– initiation failedMobile BankID verification timed out. User did not complete authentication in time.– QR not scanned within timeoutThe user is not a customer in Swedbank...or...Sparbanken– profile selection mismatches the chosenbankAppNot a valid AccountID/Not a valid DetailsTransactionID– invalid identifiers passed to account/transaction endpointsThere are no registered transactions to confirm.– attempting to confirm transfers when none existPROFILE_SELECTION_NEEDED/MULTIPLE_PROFILES– some users must select a profile; useselectProfileIfNeededor setprofileID
Catch errors around your calls to provide better user messaging or retries.
Debug Logging
Set SWEDBANK_DEBUG=1 to log request URLs, headers, cookies, and short response excerpts. By default, the client is quiet aside from thrown errors.
SWEDBANK_DEBUG=1 node your-script.jsFull API Reference
loginWithBankID(options: LoginWithBankIDOptions)
Starts Mobile BankID authentication and returns { auth, session }. Persist session to disk to skip QR next time; use auth.pollStatus() for QR frames and auth.verify() to block until done.
Classes
SwedbankClient
constructor(authOrSession)– pass aMobileBankIDAuthinstance or a persistedSessionobjectprofileList()– list available profiles for the authenticated useraccountList(profileID?)– fetch engagement overview (transactionAccounts, savingsAccounts, cardAccounts, loans)accountTransactions(accountID?, transactionsPerPage?, page?)– single-page transaction preview (legacy)accountDetails(accountID?, transactionsPerPage?, page?)– alias ofaccountTransactionsgetFullTransactionHistory(accountID?)– traverse pagination and return all transactionstransactionDetails(detailsTransactionID)– fetch additional info for a transactionportfolioList(profileID?)– list savings/investment holdingsreminders()– fetch message reminderstransferBaseInfo()– base info for payments (limits, defaults)transferRegisterPayment(amount, fromAccountId, recipientAccountId, fromAccountNote?, recipientAccountMessage?, transferDate?, periodicity?)transferListRegistered()/transferListConfirmed()– list pending/confirmed paymentstransferConfirmPayments()– confirm all registered transferstransferDeletePayment(transferId)– delete a paymentquickBalanceAccounts(profileID?)– list accounts eligible for quick balancequickBalanceSubscription(accountQuickBalanceSubID)/quickBalance(subscriptionId)/quickBalanceUnsubscription(subscriptionId, profileID?)selectProfileIfNeeded(accountsResp)– helper to auto-select a profile when the API requests itterminate()– end the authentication session
MobileBankIDAuth
initAuth()– start Mobile BankID (QR or same-device)pollStatus()– non-blocking status + animated QR payloadverify()/verifyLoop()– block until authentication is completegetAutoStartToken()– deep-link token for same-device flowsgetImageChallengeData()– latest QR frame payloadsetSameDevice(sameDevice)– toggle between QR and same-device modesterminate()– logout
SecurityTokenAuth
Hardware token/OTP flow (legacy): getChallenge(), login(responseCode), isUseOneTimePassword().
UnAuth
Device registration without full login: login() registers the device; useful for unauthenticated endpoints.
Utilities
AppData/AppDataCache– fetch and cache mobile app metadataHttpClient– Swedbank-aware fetch wrapper with cookie + header management- Types:
Session,SwedbankTransaction,LoginWithBankIDOptions,MobileBankIDAuthOptions,SecurityTokenAuthOptions,UnAuthOptions
Contributing
PRs are welcome! Please:
- Run
npm testto execute Vitest suites. - Include updates to TSDoc/README when changing public APIs.
- Keep logs behind
SWEDBANK_DEBUGto avoid noisy defaults.
License
MIT
