PSD2
🌍 Overview
Sparebanken Norge and Bulder Bank offers PSD2 services by use of our PSD2 APIs based on the Berlin Group NextGenPSD2 standard, as a dedicated PSD2 interface for all TPPs. The interfaces (APIs) are continuously being developed. We strive to provide interfaces that suit the use cases of all our TPPs, enabling good customer experiences for our common customers.
Note: Sparebanken Norge is operating on three separate PSD2 interfaces until the technical merger of Sparebanken Vest, Sparebanken Sør and Oslofjord Sparebank is completed:
- Sparebanken Norge (former Sparebanken Vest) and Bulder Bank — own PSD2 APIs at https://developer.spvapi.no/documentation/psd2/ (continuing interface)
- Sparebanken Norge (Sør) [former Sparebanken Sør] — Tietoevry Open Banking Portal at https://openbanking.sor.no/developer/ (until Q4 2026)
- Sparebanken Norge (Oslofjord) [former Oslofjord Sparebank] — Tietoevry Open Banking Portal at https://psd2.oslofjordsparebank.no/developer/ (until Q1 2027)
Sparebanken Norge (former Sparebanken Vest) PSD2 APIs is the surviving / continuing interface. We will inform all TPPs 3 months ahead of each technical merger, as we will be phasing out an interface.
🔐 TPP Requirements for PSD2 APIs
In order to authenticate towards Sparebanken Norge and Bulder Bank’s PSD2 APIs in production, the TPP must:
- Be in possession of one or more valid, qualified QWAC eIDAS certificates in accordance with ETSI TS 119 495
- Use a QWAC certificate to establish mutually authenticated TLS connections (mTLS)
- Support at least TLS 1.2, and strong cipher suites (subject to continuous change)
📢 Subscribe to Updates
Information about ongoing incidents, planned maintenance and change announcements will be published on our status page. We recommend that you subscribe to these updates to stay informed.
🏦 Account Information Services (AIS)
With these services you will be able to retrieve balances and transactions from your end users’ account. Read about our account information services here.
The difference between the two endpoints is mainly the SCA solution — each endpoint uses each bank’s respective SCA solution.
| Bank | Endpoint |
|---|---|
| Sparebanken Norge | https://psd2.spvapi.no |
| Bulder Bank | https://psd2-bulder.spvapi.no |
Request Limits
The header PSU-IP-Address must be present when a PSU is requesting information. PSU-IP-Address shall be the IP address of the device used by the PSU to access the TPP service. If the TPP wants to make a request without a PSU present, the PSU-IP-Address header shall not be set.
There are cases where a TPP can make requests without the PSU-IP-Address that does not generally require SCA. However, some restrictions apply:
| Endpoint | Rate Limit | Additional Constraint |
|---|---|---|
GET /v1/accounts |
4 calls per 24h | Accounts for which the PSU has given consent |
GET /v1/accounts/{accountId}/balances |
4 calls per 24h | Accounts for which the PSU has given consent |
GET /v1/accounts/{accountId}/transactions |
4 calls per 24h | Transactions no more than 90 days old |
💸 Payment Initiation Services (PIS)
These services allow end users to initiate payments from their accounts at Sparebanken Norge. The service will ask for a strong customer authentication as long as no exemption is applied. Read about our payment initiation services here.
The difference between the two endpoints is mainly the SCA solution — each endpoint uses each bank’s respective SCA solution.
| Bank | Endpoint |
|---|---|
| Sparebanken Norge | https://psd2.spvapi.no |
| Bulder Bank | https://psd2-bulder.spvapi.no |
Status Codes
Non-final payment status codes are updated asynchronously, which is why you need to poll for status updates after payment user approval. Different payment products have different statuses, and SCA exemptions may result in instantly completed payments. See XS2A Framework Implementation Guidelines, Sections 14.12 and 14.13 for details on the payment statuses.
Status Code Reference
| Code | Name | ISO 20022 Definition | Instruction |
|---|---|---|---|
ACSC |
AcceptedSettlementCompleted | Settlement on the debtor’s account has been completed. | No further polling |
ACCC |
AcceptedCreditSettlementCompleted | Settlement on the creditor’s account has been completed. | No further polling |
ACCP |
AcceptedCustomerProfile | Preceding technical validation and customer profile checks were successful. | Not in use |
ACSP |
AcceptedSettlementInProcess | All preceding checks were successful; payment accepted for execution. | Consider polling |
ACTC |
AcceptedTechnicalValidation | Authentication and syntactical/semantical validations were successful. | No further polling |
ACWC |
AcceptedWithChange | Instruction accepted but a change will be made (e.g. date or remittance not sent). | No further polling |
ACWP |
AcceptedWithoutPosting | Payment accepted without being posted to the creditor’s account. | No further polling |
ACFC |
AcceptedFundsChecked | Technical validation, customer profile and automatic funds check were positive. | Not in use |
RCVD |
Received | Payment initiation has been received by the bank. | Continue polling |
PART |
PartiallyAccepted | Some transactions accepted, but some have not yet achieved “accepted” status. Bulk payments only. | Continue polling |
PATC |
PartiallyAcceptedTechnicalCorrect | Multiple authentications needed; some but not all have been performed. | Continue polling |
PDNG |
Pending | Payment initiation or individual transaction is pending. Further checks will be performed. | Continue polling |
RJCT |
Rejected | Payment initiation or individual transaction has been rejected. | No further polling |
CANC |
Cancelled | Payment initiation has been cancelled before execution. | No further polling |
Payment Status Transitions
These are the status transitions you will most commonly see. Note that RJCT is not part of these flows as it can happen at any time before ACSC and should be handled generally as an error.
Normal Payment
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | RCVD |
Start authorisation | Yes | Authorize if startAuthorisation link is present |
| 2 | ACSP / PDNG |
Poll until next status | Yes / No | PDNG if due date is current date |
| 3 | ACSC |
— | No | Payment completed |
Instant Completion
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | RCVD |
Start authorisation | Yes | Authorize if startAuthorisation link is present |
| 2 | ACSC |
— | No | Payment completed |
SCA Exemption
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | ACSP / PDNG |
Poll until next status | Yes / No | PDNG if due date is current date |
| 2 | ACSC |
— | No | Payment completed |
Without Posting to Creditor’s Account
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | RCVD |
Start authorisation | Yes | Authorize if startAuthorisation link is present |
| 2 | ACWP |
— | No | Payment completed |
Multiple Signatures Required
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | RCVD |
Start authorisation | Yes | Authorize if startAuthorisation link is present |
| 2 | PATC |
Start authorisation again for next PSU | Yes | |
| 3 | ACSP |
Poll until next status | Yes | |
| 4 | ACSC |
— | No | Payment completed |
Periodic Payment
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | RCVD |
Start authorisation | Yes | Authorize if startAuthorisation link is present |
| 2 | ACSP |
— | Yes | Periodic payment registered |
Cancel Payment Before Authorisation
| Step | Code | Next Action | Updatable | Comment |
|---|---|---|---|---|
| 1 | RCVD |
Delete | Yes | |
| 2 | CANC |
— | No | Payment cancelled |
⚠️ Error Codes and Responses
The XS2A Framework Implementation Guidelines describes the error codes and responses used in the Berlin Group NextGenPSD2 standard. The error codes are described in detail in the Berlin Group NextGenPSD2 documentation. The code field in the API response corresponds to the “Message Code” below.
Service Unspecific Error Codes
| Message Code | HTTP Code | Description |
|---|---|---|
CERTIFICATE_INVALID |
401 | The contents of the signature/corporate seal certificate are not matching PSD2 general or attribute requirements. |
ROLE_INVALID |
401 | The TPP does not have the correct PSD2 role to access this service. |
CERTIFICATE_EXPIRED |
401 | Signature/corporate seal certificate is expired. |
CERTIFICATE_BLOCKED |
401 | Signature/corporate seal certificate has been blocked by the ASPSP or the related NCA. |
CERTIFICATE_REVOKED |
401 | Signature/corporate seal certificate has been revoked by QSTP. |
CERTIFICATE_MISSING |
401 | Signature/corporate seal certificate was not available in the request but is mandated for the corresponding field. |
SIGNATURE_INVALID |
401 | Application layer eIDAS Signature for TPP authentication is not correct. |
SIGNATURE_MISSING |
401 | Application layer eIDAS Signature for TPP authentication is mandated by the ASPSP but is missing. |
FORMAT_ERROR |
400 | Format of certain request fields are not matching the XS2A requirements. Applies to headers and body entries, including references to erroneous or non-existing data instances (e.g. a malformed IBAN). |
PARAMETER_NOT_CONSISTENT |
400 | Parameters submitted by TPP are not consistent. Applies only for query parameters. |
PARAMETER_NOT_SUPPORTED |
400 | The parameter is not supported by the API provider. Only for parameters described as “optional if supported by API provider.” |
PSU_CREDENTIALS_INVALID |
401 | The PSU-ID cannot be matched by the addressed ASPSP or is blocked, or a password/OTP was not correct. |
SERVICE_INVALID |
400 / 405 | The addressed service is not valid for the addressed resources or submitted data. |
SERVICE_BLOCKED |
403 | This service is not reachable for the addressed PSU due to a channel independent blocking by the ASPSP. |
CORPORATE_ID_INVALID |
401 | The PSU-Corporate-ID cannot be matched by the addressed ASPSP. |
CONSENT_UNKNOWN |
403 / 400 | The Consent-ID cannot be matched by the ASPSP relative to the TPP. |
CONSENT_INVALID |
401 | The consent was created by this TPP, but is not valid for the addressed service/resource. |
CONSENT_EXPIRED |
401 | The consent was created by this TPP, but has expired and needs to be renewed. |
RESOURCE_UNKNOWN |
404 / 403 / 400 | The addressed resource is unknown relative to the TPP. |
RESOURCE_EXPIRED |
403 / 400 | The addressed resource is associated with the TPP but has expired. |
RESOURCE_BLOCKED |
400 | The addressed resource is not addressable by this request since it is blocked (e.g. by a signing basket grouping). |
TIMESTAMP_INVALID |
400 | Timestamp not in accepted time period. |
PERIOD_INVALID |
400 | Requested time period out of bound. |
SCA_METHOD_UNKNOWN |
400 | Addressed SCA method in the Authentication Method Select Request is unknown or cannot be matched with the PSU. |
STATUS_INVALID |
409 | The addressed resource does not allow additional authorisation. |
Payment Initiation Service Error Codes
| Message Code | HTTP Code | Description |
|---|---|---|
PRODUCT_INVALID |
403 | The addressed payment product is not available for the PSU. |
PRODUCT_UNKNOWN |
404 | The addressed payment product is not supported by the ASPSP. |
PAYMENT_FAILED |
400 | The payment initiation POST request failed during the initial process. |
KID_MISSING |
400 | Payment initiation failed due to a missing KID (Norwegian market specific). |
KID_INVALID |
400 | Payment initiation failed due to an invalid KID (Norwegian market specific). |
EXECUTION_DATE_INVALID |
400 | The requested execution date is not a valid execution date for the ASPSP. |
CANCELLATION_INVALID |
405 | The addressed payment is not cancellable (e.g. cut off time passed or legal constraints). |
Account Information Service Error Codes
| Message Code | HTTP Code | Description |
|---|---|---|
SESSIONS_NOT_SUPPORTED |
400 | The combined service flag may not be used with this ASPSP. |
ACCESS_EXCEEDED |
429 | The access on the account has exceeded the consented frequency without PSU involvement per day. |
REQUESTED_FORMATS_INVALID |
406 | The requested formats in the Accept header entry do not match the offered formats. |
Signing Basket Error Codes
| Message Code | HTTP Code | Description |
|---|---|---|
REFERENCE_MIX_INVALID |
400 | The used combination of referenced objects is not supported in the ASPSP’s signing basket function. |
REFERENCE_STATUS_INVALID |
409 | At least one of the references is already fully authorised. |
🧪 Sandbox Environment
A sandbox environment for the dedicated PSD2 interface is available. The sandbox environment has the same TPP requirements as production. No sign-up or registration is needed. The sandbox covers both Sparebanken Norge and Bulder Bank’s API experience with a single sandbox SCA solution.
Note: At the moment we do not trust test QWACs.
| Environment | Endpoint |
|---|---|
| Sandbox | https://psd2-sandbox.spvapi.no |
For more information, see the PSD2 Sandbox Documentation on GitHub.
🔄 Contingency / Fallback Solution
Authentication for PSD2 Access via Ordinary Interfaces
Third Party Providers (TPPs) must authenticate themselves before accessing the Payment Service User’s (PSU’s) online banking data. There is no “natural” approach to this in traditional user-centric online banking websites, so a more untraditional authentication approach is required.
This access will also serve as our fallback solution until we are exempted from having a fallback.
Requirements for TPPs Using the Fallback Mechanism
For every HTTP request made to Sparebanken Norge, the following two request headers must be included:
1. SPV-PSD2-Fallback-TPP-Cert
Base64-encoded JWK containing the QSeal certificate
The TPP’s QSeal certificate (including intermediates) must be presented in the JSON Web Key (JWK) format, using the x5c (X.509 Certificate Chain) parameter — see RFC 7517, Section 4.7. The JWK should be UTF-8 encoded and then Base64-encoded for inclusion in the HTTP header.
2. SPV-PSD2-Fallback-TPP-Qseal
TPP-issued JWT proving possession of the QSeal private key
The JWT must be signed with the QSeal private key using one of the following algorithms (see RFC 7518, Section 3.1):
- RS256 — RSASSA-PKCS1-v1_5 using SHA-256
- ES256 — ECDSA using P-256 and SHA-256
JWT Header (kid/x5t are example values only):
{
"alg": "RS256",
"kid": "E7B3AE9190916FDB58091EEE5FA7A55B56A736B3",
"x5t": "57OukZCRb9tYCR7uX6elW1anNrM",
"typ": "JWT"
}JWT Claims:
| Claim | Description |
|---|---|
iss |
The full name of the TPP, as registered in the QSeal certificate. |
aud |
spv fallback prod for production use. |
exp |
Expiry — no longer than 1 hour from the time the token was issued. |
nbf |
Not before — set to the time of issuance. |
iat |
Issued at — set to the time of issuance. |
jti |
JWT ID — a 128-bit randomly generated identifier. |
Inclusion of both headers enables us to verify that the TPP has a valid QSeal certificate and controls its private key.