Skip to Content
API OverviewAccountsAccounts API

Accounts API

The Accounts API allows Third Party Providers (TPPs) to access account information on behalf of authorized users. This API requires the PSP_AI (Account Information) scope.

Capabilities

List Accounts

Retrieve a list of all accounts accessible to the authenticated user.

GET /accounts

Each account includes:

FieldRequiredDescription
idYesUnique account identifier used in other API calls
nameYesHuman-readable account name
currencyYesAccount currency (ISO 4217 alpha-3, e.g., DKK, SEK, NOK)
bbanYesNational Basic Bank Account Number
ibanNoInternational Bank Account Number
swiftNoSWIFT/BIC code
balanceAmountYesCurrent account balance
balanceReservedAmountYesAmount reserved for pending transactions
balanceAvailableAmountYesAvailable spending amount (balance + credit limit - reserved)
creditLimitAmountNoAuthorized credit limit (if applicable)
typeYesAccount type (only CHECKING accounts are available via PSD2)
supportsPaymentsYesWhether payments can be initiated from this account
supportsTransfersYesWhether credit transfers can be initiated from this account
ownerNameNoFull name of the account owner
usageNoWhether the account is owned by a private individual or an organisation. One of PRIVATE, ORGANISATION. Omitted if the owner type cannot be determined.

Only checking accounts are exposed through the Open Banking API. Savings accounts and other account types are not accessible.

List Transactions

Retrieve transaction history for a specific account.

GET /accounts/{accountId}/transactions

A newer Transactions v2 endpoint returns transactions split into separate pending and posted lists (nextgen style) with opaque cursor pagination. Attachments a user added to a transaction can be downloaded via the Attachments endpoints.

Query Parameters

ParameterTypeDescription
limitnumberMaximum transactions to return (max 500, default 100)
offsetnumberPagination offset for retrieving additional pages
fromdatetimeInclude only transactions after this ISO-8601 timestamp
todatetimeInclude only transactions before this ISO-8601 timestamp

If you send a date without a time component (e.g., 2025-01-01), it defaults to 2025-01-01T12:00:00.000.

Response Structure

The response is a TransactionsResponse wrapper object:

FieldTypeDescription
offsetnumberThe offset used in pagination
limitnumberThe limit requested
fromdatetimeThe from date requested (if any)
todatetimeThe to date requested (if any)
transactionsTransaction[]Array of transaction objects

The offset is the amount of transactions “skipped”, if you have 10 transactions, and limit is 10 and you have offset 1 you get the last 9 transactions.

Transaction Properties

Each transaction includes:

FieldDescription
idUnique transaction identifier
transactionTimeISO-8601 timestamp when the transaction was initiated (e.g., the moment a card was swiped or a transfer was created). Present on all transactions including pending ones
postingTimeISO-8601 timestamp when the transaction was settled and funds were moved on the account. null for pending/authorized transactions that have not yet settled
billingAmountAmount object ({ amount, currency }) — the actual billed amount in the account’s currency
transactionAmountAmount object ({ amount, currency }) — the original transaction amount (may differ for foreign currency). Can be null in cases where the payment was never reserved on the account
currencyExchangeCurrencyExchange object with currency (string), targetCurrency (string), and exchangeRate (number)
titleTransaction description
typeTransaction type: dkPaymentSlip, domesticCreditTransfer, card, direct-debit, or unknown
domesticCreditTransferInfoObject with recipientBBAN (string, BBAN of the recipient, 11-14 chars) and message (string, optional). Present for domestic credit transfer transactions
cardTransactionInfoObject describing the card used and the merchant — merchantName, merchantCategoryCode, cardEntryMode, walletProvider, isAtm, and merchantLocation. Present for card transactions. See Card transaction info.
statusStatus: future, financial, authorization, interim, failed_authorization, declined, initiated, or unknown
accountIdParent account identifier
attachmentIdsstring[] — IDs of the attachments a user has added to this transaction. Populated on the transaction list endpoints and the get-by-id endpoint; omitted when the transaction has no attachments. See Attachments for downloading them.
messageOptional free-text payment message associated with the transaction — for example, the sender note on a transfer, the message on a direct debit, or the description on a Swedish giro payment. Present when available; omitted otherwise.
debtorTransactionParty object ({ name, address, account?: { scheme, identification }, bic? }) — the party funds are debited from. Populated for transfer-like transactions.
creditorTransactionParty object ({ name, address, account?: { scheme, identification }, bic? }) — the party funds are credited to. Populated for transfer-like transactions.
accountBalanceAfterTransactionAmount object — the booked account balance after this transaction settled. Populated for settled transactions; omitted otherwise.
additionalInformationobject (string map) — free-form identifiers that don’t fit other fields. See below for currently emitted keys.

Transactions are returned with negative amounts for debits and positive amounts for credits.

Eventual consistency

Transaction data is served from a view that is updated over time as payments move through our transaction pipeline — not as a single atomic snapshot at creation.

  • Transactions can appear in the API as soon as they are known, while optional fields are added or updated asynchronously as the payment progresses.
  • A common lifecycle is authorization or initiated (reserved or in flight) → financial when posted on the ledger. postingTime is empty until the transaction is posted, then set (this corresponds to bookingDate in NextGenPSD2).
  • Same id, different payloads on repeat fetches is normal. For example, a first response may have status authorization and no postingTime or accountBalanceAfterTransaction; a later response for the same transaction may include postingTime, accountBalanceAfterTransaction, and status financial. That reflects posting and enrichment — not duplicate transactions.
  • This applies to same-day activity, not only historical data. Enrichment can lag by seconds or minutes depending on product and posting path.
  • Treat enrichment fields (message, debtor, creditor, accountBalanceAfterTransaction, additionalInformation, and others) as optional until present. Absence on the first fetch does not mean the field will never appear.
  • For reconciliation and balance reconstruction, prefer transactions with postingTime and status financial. Re-fetch or poll recent activity when required fields are missing; do not assume one list call is complete for “today.”
  • Use stable id for deduplication when merging polls; merge updates into stored records rather than treating missing optional fields as removed.

This behaviour is expected platform behaviour, not an error in your integration.

Title and payment message

title and message serve different purposes:

  • title — the primary short transaction description (for example merchant name or counterparty name). It is what we show as the main label in the Lunar app. It is not the payment reference.
  • message — optional payment or remittance text when available (sender note on a transfer, direct-debit message, international receiver message, and similar). Use this for unstructured reference or note text.
  • Structured Swedish payment references (OCR, bankgiro/plusgiro numbers, Swish ID) belong in additionalInformation, not in title.
  • For domestic credit transfers, domesticCreditTransferInfo.message may still be present for backward compatibility. When both are available, prefer the top-level message — it can contain the full multi-line text.
Billing amount vs. transaction amount

A transaction carries two amount fields:

  • transactionAmount — the amount in the original currency of the payment (e.g., EUR 20 for a purchase at a European shop). Can be null in some special cases for example when the payment was never reserved on the account, such as certain direct settlements.
  • billingAmount — the amount that was actually posted to the account, in the currency of the posting. For foreign-currency transactions this is the converted amount after exchange.

When both currencies are the same, the two values will match. When they differ, the currencyExchange object provides the conversion details.

Always prefer billingAmount — it is the authoritative figure for balance calculations and represents what actually entered or left the account.

Example: A card payment made for 20 EUR:

{ "billingAmount": { "amount": -149.0, "currency": "DKK" }, "transactionAmount": { "amount": -20.0, "currency": "EUR" }, "currencyExchange": { "currency": "EUR", "targetCurrency": "DKK", "exchangeRate": 7.45 } }
Mapping properties for transaction fields

Here is a mapping of our statuses, to codes of the ISO 20022 data table:

Lunar StatusClosest ISO 20022Rationale
initiatedRCVD / PDNGTransaction received/pending
authorizationACTC / PDNGAwaiting authorization
interimACSPIn process, not yet settled
financialACSC / ACCCSettled/completed
futurePDNGScheduled for a future date
failed_authorizationRJCTAuthorization failed
declinedRJCTRejected
unknownA fault that isn’t described above, contact Lunar

Mapping to NextGenPSD2 (Berlin Group) fields:

Lunar uses transactionTime and postingTime as full ISO-8601 timestamps. The NextGenPSD2 spec uses bookingDate, valueDate, and transactionDate as date-only (ISODate) fields. The mapping between them depends on the transaction status:

bookingDate“The date when an entry is posted to an account on the ASPSP’s books.”

  • Maps to postingTime. Both represent when the transaction was recorded on the account.
  • null for pending transactions, just as bookingDate is absent for pending entries in NextGen.

valueDate“The date at which assets become available to the account owner in case of a credit, or cease to be available in case of a debit. If entry status is pending, refers to an expected/requested value date.”

  • For settled transactions (financial status): maps to postingTime. Lunar does not distinguish between the booking date and the value date — settlement, booking, and funds availability happen at the same time.
  • For future/scheduled transactions (future status): maps to transactionTime, which holds the scheduled execution date — equivalent to the “expected/requested value date” in NextGen.
  • For other pending transactions (authorization, initiated): Lunar does not expose an expected value date. There is no direct equivalent.

transactionDate (NextGen card transactions only)“Date of the actual card transaction.”

  • Maps to transactionTime. Both represent when the transaction was initiated (e.g., the moment a card was swiped or a transfer was created).

    Reconciliation guidance:

  • Use postingTime for matching against bank statements and cash-flow reconciliation — this is when the account balance actually changed. It corresponds to bookingDate in NextGenPSD2.

  • Use transactionTime to determine when the transaction was initiated, e.g., for dispute timelines or user-facing activity logs.

  • For pending transactions (authorization, initiated), only transactionTime is available. postingTime is populated once the transaction reaches financial status. See Eventual consistency for why fields can appear or change between fetches.

  • For future/scheduled transactions, transactionTime represents the expected execution date and can be used as an anticipated settlement date.

Debtor and creditor parties

Transfer-like transactions (domestic credit transfers, international payments, direct debits, bank giro, plus giro, Swish, e-faktura) carry structured debtor and creditor objects. The direction follows the sign of billingAmount:

  • Incoming (positive billingAmount) — the counterparty is the debtor (the sender); the account holder is the creditor.
  • Outgoing (negative billingAmount) — the account holder is the debtor; the counterparty is the creditor.

All fields on the party object are optional. Consumers must not rely on any particular field being present.

FieldRequiredDescription
nameNoName of the party.
addressNoAddress of the party (see below).
accountNoStructured account identifier (see below).
bicNoSWIFT/BIC of the counterparty bank.

address is a single free-text string, not a structured street/city/postcode model. When multiple lines are available they may be joined with newline characters. Format varies depending on source (bank-supplied data, payer-entered text, and similar) — do not parse into structured address fields without your own heuristics. The field is often omitted when only a counterparty name is known.

When account is present, both scheme and identification are guaranteed:

account.schemeDescription
IBANInternational Bank Account Number (ISO 13616).
BBANNational Basic Bank Account Number, used for domestic transfers in DK, NO, and SE.
ACCOUNT_NUMBERFallback for account identifiers that are neither an IBAN nor a BBAN. Treat as opaque.

Additional schemes may be introduced in the future; consumers should treat unknown values defensively.

When the counterparty’s account identifier is not a bank account (e.g. bank giro, plusgiro, Swish), the account field is omitted and the relevant identifier is surfaced via additionalInformation instead.

Example: An incoming domestic credit transfer of DKK 500:

{ "billingAmount": { "amount": 500.0, "currency": "DKK" }, "debtor": { "name": "Jane Doe", "account": { "scheme": "BBAN", "identification": "12345678901" } }, "creditor": { "name": "John Smith", "account": { "scheme": "BBAN", "identification": "98765432109" } } }

Example: An outgoing international payment to a Danish IBAN:

{ "billingAmount": { "amount": -1000.0, "currency": "DKK" }, "creditor": { "name": "Foreign Recipient", "account": { "scheme": "IBAN", "identification": "DK1212345678901234" }, "bic": "BANKDKKKXXX" } }
Transaction identifiers (id)

The id field is an opaque, stable identifier. Use it only for lookup and deduplication (for example GET /accounts/{accountId}/transactions/{transactionId} and merging results across polls).

Do not use id for business logic. Do not infer transaction type, direction, payment reference, or product from substrings in the identifier. IDs reflect historical naming conventions across many internal flows; a substring such as payout is not a reliable signal of incoming vs outgoing or of a specific product. Use structured fields instead (type, status, billingAmount, message, additionalInformation, debtor / creditor, and others).

Account balance after transaction

accountBalanceAfterTransaction carries the booked account balance immediately after a transaction settled, as an Amount object ({ amount, currency }). It is populated when that booked balance is available and omitted otherwise — including for same-day transactions that have not yet been enriched.

This field aligns with Berlin Group’s balanceAfterTransaction and is useful for reconstructing a running balance from a transaction list without a separate balance call.

See Eventual consistency for why the same transaction may lack this field on an earlier request and gain it after posting.

Card transaction info

Card transactions (type card) carry a cardTransactionInfo object describing the card used and the merchant. All fields are optional and each is omitted when the source data is unavailable — there are no empty placeholders.

FieldTypeDescription
merchantNamestringMerchant name.
merchantCategoryCodenumberMerchant Category Code (MCC).
cardEntryModestringHow the card credentials were captured. One of chip, contactless, magneticStripe, manual, merchantInitiated. Omitted when not specified.
walletProviderstringDigital wallet used when the card was tokenized for the payment. One of applePay, googlePay. Omitted when the payment was not made via a wallet.
isAtmbooleantrue when the card transaction took place at an ATM. Omitted when the source data does not indicate an ATM transaction.
merchantLocationobjectStructured merchant address (see below). Populated alongside merchantName/merchantCategoryCode when available.

merchantLocation — structured merchant address. Every sub-field is optional.

FieldTypeDescription
citystringCity of the merchant.
countrystringISO 3166-1 alpha-2 country code of the merchant.

These are enrichment fields: they may be absent on an early fetch and appear on a later one as the transaction is enriched. See Eventual consistency and treat them as optional until present.

Example: A contactless Apple Pay card payment at a merchant:

{ "type": "card", "billingAmount": { "amount": -149.0, "currency": "DKK" }, "cardTransactionInfo": { "merchantName": "Coffee Shop", "merchantCategoryCode": 5814, "cardEntryMode": "contactless", "walletProvider": "applePay", "isAtm": false, "merchantLocation": { "city": "Copenhagen", "country": "DK" } } }
Additional information map

additionalInformation is a free-form string-to-string map for identifiers that don’t fit other structured fields. It is omitted when empty. Consumers should treat unrecognized keys as opaque — new keys may be added without a version bump.

Structured OCR references (Swedish bankgiro, plusgiro, e-faktura) are exposed under the ocr key when available. The map or key is omitted when there is no OCR. OCR is not guaranteed on all transaction types (for example ordinary card payments or domestic transfers may have no ocr entry). Do not use title or message as the structured OCR channel — use additionalInformation.ocr when present. Reference-like text may still appear in message as free text.

Currently emitted keys:

KeyDescription
bgNumberSwedish bank giro recipient number
pgNumberSwedish plusgiro recipient number
giroNumberGeneric giro identifier from e-faktura SE (may be a BG or PG number; not distinguishable at source)
bgIssuerBank giro issuer identifier (BGS number) from e-faktura SE
ocrOCR reference for SE bank giro / plusgiro / e-faktura
swishIdSwish payment identifier

Get Transaction by ID

Retrieve a single transaction by its identifier.

GET /accounts/{accountId}/transactions/{transactionId}

Path Parameters

ParameterTypeDescription
accountIdstringThe account identifier
transactionIdstringThe transaction identifier

Headers

HeaderRequiredDescription
X-LanguageNoLanguage preference

Response Structure

Returns a single TransactionDetail object. This is a full Transaction — every field described above, including attachmentIds — plus one extra field that is only returned by this endpoint (the list endpoints keep returning the plain Transaction):

FieldTypeDescription
deletedbooleanAlways present. true when the transaction has been deleted and no longer appears in the transaction lists; false otherwise. See Detecting deleted transactions.

attachmentIds is populated on this endpoint as well (with the same rules as the list endpoints — omitted when the transaction has no attachments). See Attachments for downloading the files.

Detecting deleted transactions

A transaction can appear while it is still pending (status authorization) and later fail — for example a declined or reversed authorization. When that happens it simply stops appearing in the transaction lists (neither the flat list nor the Transactions v2 pending/posted lists) without ever settling.

Because the list endpoints only tell you a transaction is absent, they cannot distinguish “failed and removed” from “not yet fetched”. The get-by-id endpoint resolves this: it keeps returning the transaction by its stable id and sets deleted: true once it has been removed. Use it to confirm the outcome of a pending transaction you previously stored instead of waiting for it to (possibly never) reappear. See Eventual consistency for the wider lifecycle behaviour.

Example: a previously pending transaction that later failed:

{ "id": "txn-a1", "status": "authorization", "transactionTime": "2025-01-31T18:22:00.000Z", "billingAmount": { "amount": -149.0, "currency": "DKK" }, "title": "Coffee Shop", "type": "card", "accountId": "account-uuid", "deleted": true }

Funds Confirmation

Check whether a specific amount is available in an account. This is useful before initiating a payment to ensure it won’t fail due to insufficient funds.

GET /funds-confirmation

Request Body

{ "accountId": "account-uuid", "amount": 100.0, "currency": "DKK" }

Response

{ "fundsAvailable": true }

Funds confirmation requires the PSP_PI (Payment Initiation) scope, not PSP_AI.

Required Scopes

EndpointRequired Scope
GET /accountsPSP_AI
GET /accounts/{accountId}/transactionsPSP_AI
GET /accounts/{accountId}/transactions/{transactionId}PSP_AI
GET /funds-confirmationPSP_PI

Error Handling

Each endpoint defines its own set of error responses:

Endpoint400404500
GET /accounts
GET /accounts/{accountId}/transactions
GET /accounts/{accountId}/transactions/{transactionId}
GET /funds-confirmation
StatusDescription
400Invalid request parameters
404Resource not found
500Internal server error

Error responses include an errorCode and message for debugging.

Last updated on