WERO Notification API

WERO Notification API

API Reference

The WERO payment APIs described in this chapter need to be implemented on the Acceptor side, if the Acceptor decides to use them. The Open Banking Service will post notifications to these endpoints. For the WERO product, the post status notification is part of the product.

POST Status

Endpoint: POST /status

This API will notify the Acceptor about the status of the payment.

  • The purple fields are applicable to WERO.
  • The orange fields are mandatory for a WERO payment.

More details about the fields can be found in the API reference.

Data model

Below is a representation of the API request and response structure.

Request (click to enlarge)

Response (click to enlarge)

 

Post status request
Payment Notification Response

 

Enable "on this page" menu on doc section
On

WERO Payment Initiation API

WERO Payment Initiation API

API Reference

The WERO payment api uses a subset of the available open banking API's. In this chapter only the api's needed for WERO payment initiation are described, furthermore the fields applicable to a WERO payment are marked purple (optional) and orange (mandatory) in the data models.

Payment Status

The following statuses are used to describe the actual state of processing: 

  • Open
  • Authorised
  • SettlementInProcess
  • SettlementCompleted
  • Cancelled
  • Expired
  • Error

In the following picture the possible WERO status are shown in an activity diagram:

WERO Payment Status

Status mapping to Wero

The following table describes the mapping from the Wero payment status(es) to the unified payment status used in the Open Banking Platform. A Wero Single immediate payment consists of a consent, authorization and capture resource, each have an individual status. The combination of those statuses is mapped to a single Payment status in the Open banking solution.

Worldline Wero ConsentWero AuthorizationWero Individual Capture
OpenRequested or Granted  
AuthorisedGrantedGranted 
SettlementInProcessGrantedGrantedAccepted
SettlementCompletedGrantedGrantedSettled
CancelledDenied  
CancelledGrantedRejected 
CancelledGrantedCancelled 
ExpiredTimeOut  
ErrorGrantedFailed 

POST Payments

Endpoint: POST /payments

Base URL:  /xs2a/routingservice/services/ob/pis/v3

This endpoint is used by the Acceptor to initiate a WERO transaction.

  • The purple fields are applicable to WERO.
  • The orange fields are mandatory for a WERO payment.

More details about the fields can be found in the yaml specification.

Data model

Below is a representation of the API request and response structure.

Request 

Legend

  • Purple fields: are applicable to a WERO payment.
  • Orange fields: are mandatory for a WERO payment.
Request (click to enlarge)Response (click to enlarge)
Post payments v3 WeroPayment Response

Example: WERO Single Immediate payment

Request:

Address: https://localhost:8443/xs2a/routingservice/services/ob/pis/v3/payments
    
    HttpMethod: POST
    Headers: {X-Request-ID=27965d49-b27b-38a9-6f7a-2211cb5c0c78, Authorization=Bearer 69eb307c55eb91b4a4144ec8a2d8562d, MessageCreateDateTime=2022-03-22T14:02:13.184Z, Digest=SHA-256=DZ0QKHaRy/MdbWEI62wuE7xJMrfJJBTUWF8irHIHTGw=, Signature=keyId="8D0F688AD3E6C2D4D5FB99FE129F2A2E3B496AF7",algorithm="SHA256withRSA",headers="x-request-id (request-target) digest messagecreatedatetime",signature="DK7sQCW56EMXHOw/rdW3RlrtM2U/QL2Hy5g5Fsq+oZ0qspiDerzYL0FRu47EdGWT9qy7n7R3ay6iJHVCUrgFvVXS806E3Clgh5u7+J8/xgUeEPRglA6jeNaLYErKC+xIklJrmpKODDkD407IgA6Y9LhixFisSfawR1pDs2vwOsB1wnujrwBcKFzYf66/pxhW06NZu98VM0pkLm5OFp82G0x4vHfOPAoo46xcSXd/IbQV0DYZewosQIaI5qAclPvmusO9uXDx90uqgDL4E8fLW4yHEaraW7yDlCx54bcraU4ubo+wqDE8NJMKxEVreI/Se9YY73mvAMnOkon1jZHsAQ=="}, Accept=*/*, Content-Type=application/json
    
    Payload: 
    {
    "PaymentProduct": ["WERO"],
    "CommonPaymentData": {
          "RemittanceInformationStructured": {
          "Reference": "12345"
        },
        "RemittanceInformation": "Example payment",
        "Amount": {
            "Amount": "100.00",
            "Currency": "EUR"
        }
    }
}

Response:

ResponseCode: 201
    
    Headers: {X-Request-ID=0e1b8b7d-2438-4bb0-acf5-d68f967c8b25, MessageCreateDateTime=2022-03-22T14:02:13.694Z, Digest=SHA-256=gJNKvdO+dlRlWyevVFfDeEAAJDtmw41A3pQOyNX3K6o=, Signature=keyId="3EBEF6033C00730D9C6DA05165A3CAA1F31036FB",algorithm="rsa-sha256",headers="messagecreatedatetime x-request-id digest",signature="NMQImrvrg664n3rBCF9s8fQLvZVH/zPsHfzzxJ671BWz6fvjtn81Arv6TPd8N6/nLLNNjY23YubI33tYDjyEf1vq1wF3vq/gFqmF2s66dxHFy7Gd9mOEdpxc0BYCwpG2ozntRvnrIv2z9SXFlKljc6OT+mqLo+vCB8Gn6frdrwGgZqY6uHOEh3rPvYJ/nWTHQkfxzx/U624wqtuoI8Va4kIXM2pPBCPo4AAq2hFXtj4Okh5vFmRlRiIM9CFgfO+5k1lMC3YzrmE8aB9CyFoJoT3e5pSKNePL+hunGlJG6XPg92Hg/gpS06PyvCtHA5585ONkQv+oNhFdpfdtob1qBQ=="}
    Payload: {
    "CommonPaymentData": {
       "PaymentStatus": "Open",
       "PaymentId": "1282",
       "AspspPaymentId": "0001092688873027"
   },
   "Links": {
       "RedirectUrl": {
           "Href": "https://pay.int.epi.engineering/516ca41d-d47a-468a-9726-8299d69168a9"
       }
    },
    "UseWaitingScreen": false
}

GET Payment Status

Endpoint: GET /payments/{paymentId}/status

This endpoint is used to retrieve the status of a payment.

Data model

Legend

  • Purple fields: are applicable to a WERO payment.
  • Orange fields: are mandatory for a WERO payment.
RequestResponse (click to enlarge)
Payment Status RequestPayment Status Response

Example: WERO payment status

Request:


Address: https://digitalroutingservice.awltest.de/xs2a/routingservice/services/ob/pis/v3/payments/1282/status
HttpMethod: GET
Headers: {Accept=application/json, Digest=SHA-256=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=, X-Request-ID=aa9ec3e7-dc34-f625-2e97-e16644ea1e77, Authorization=Bearer 59519322f1f56db6bd1d23ac0e22cf5015088f085970fb9b461ff2684bc2e96a, MessageCreateDateTime=2024-01-08T12:55:34.630Z, Signature=keyId="39d8e82bb33e7e2a09cbcb3ef3eab351ee1c5e8f",algorithm="SHA256withRSA",headers="x-request-id (request-target) digest messagecreatedatetime",signature="W/6ViHZJ/x0/KM61H7mwCZQp2/3WPax5seqLpCby0BXwgpVoFrSmCu5oHF2pLS2AdHuTiE6qFsBnMkfeGMEDwtqCdY0GZVQGwZ6j9+6zjJHwm21xZ+BmXXH4puRgqxt7DSnOou3SkstzCblf4gSL8MqIyYu7n+eLQlWvjl57t7dNgX0sNTwJE/1GgU/ukDyUoJl4aO1n9ID8EnLDUpXunbZ+1pyCPGbfz5/pDMrJsKZ9l58tLxj7IneU+Mnai8UJEqrQ441ONgYCHF7KoDxu15XA+IY7DnwkA5u/+QN7IY5KpHG3zP19m7jiOimkI6lrqLAc2Ld4iehjNMGve7Ci7w=="}

Response:

    ResponseCode: 200
     
    Headers: {X-Request-ID=3a3df5d3-fa9e-4fee-b9fd-067c23dc91fa, MessageCreateDateTime=2024-01-08T12:55:35.032Z, Digest=SHA-256=pV9HQh/XGpLmawhfj9d/hxYucKkOQCKV9BJ978PeW5k=, Signature=keyId="3EBEF6033C00730D9C6DA05165A3CAA1F31036FB",algorithm="rsa-sha256",headers="messagecreatedatetime x-request-id digest",signature="DMvxRTvhRG1kFAy0JPbBzdoRrXq5C9OUJHl6GMQkdNriG4SeuHGaFpdaDA6NgFw2+Ky/RBYiruL18ul+1ZvmdhlyhMaRqR0J7Jg/m9JMyu3wFunBVINysQ+2yj0ucXRMck/CoBW1mYwjDCGCN7xOofw2mZLV6PHjP9xHaDA855iPYE7HUaukB/qveA/S6B2qsjFxDs5AJh6VSWEoknA1+NJZCEX2VC23bnkMgy92qN6bZch5bL3462yFA/0uA75k9XH3O7+Jesl86tBU3kKATNk5n2//vun+Bg4NlSQjU21m6B+nOZT1M+TUkVzG0KWdByf6yFv/x0rp7hifnFZvjA==", Date=Mon, 08 Jan 2024 12:55:35 GMT, Content-Type=application/json;charset=UTF-8}
    Payload: {
    "PaymentProductUsed": "WERO",
    "CommonPaymentData": {
        "PaymentStatus": "SettlementCompleted",
        "PaymentId": "1282",
        "AspspPaymentId": "0001092688873027",
        "AspspId": "10002",
        "InitiatingPartyReferenceId": "7cc080484bd74d2c8c1d8d2b296ee5b9"
        }
    }
Enable "on this page" menu on doc section
On

WERO Transaction Flow

WERO Transaction Flow

This page describes the transaction flows for WERO payments, designed to provide a seamless payment experience whether accessed via the WERO mobile app or through bank-integrated solutions. 

Which Wero Payments are supported?

  • Single Immediate Payments 

More Wero payment plans will be added in the future.

In the paragraphs below you can find a brief explanation of the payment flows from the Consumer perspective and from the Acceptor's  (technical) perspective. 

WERO flow from the Consumer perspective

What is the difference between an e-commerce and m-commerce flow?

 The flows differ in how the redirection between the online shop and the Wero digital wallet happens: 

  • in the e-commerce flow (web storefront checkout (desktop or mobile web), a Wero landing page is displayed with a QR code for linking the online shop to the Wero digital wallet. 
  • in the m-commerce flow (shop and pay in smartphone), the wallet is launched automatically after tapping the "pay with Wero" button, and no QR code is needed.

The actual WERO transaction flow that the Consumer follows depends on where the payment authorization takes place (in a standalone Wero wallet or in the Consumer PSP's app) And if a Consumer is already registered for WERO.

Below you'll find an example screen flow of the e-commerce flow for a Wero single immediate payment:

Wero ecom example flow 1Wero ecom example flow part 2

The Consumer flow does not impact the integration between the Acceptor and the Worldline Open Banking Solution.

Wero flow from the Acceptor perspective (technical)

WERO Single Immediate Payment

In the diagrams below, the sequence of requests is shown to initiate a Wero Single immediate payment. The vertical green bars indicate which party is responsible for the session of the Consumer. If a party has the session, a screen can be displayed. Notice that in the WERO flow, the Acceptor can receive a notification when the authorization of the payment is finished on the Consumer PSP side. To receive this notification, the Acceptor should implement the Post status API, so that this can be called by the Open Banking Service. The Acceptor also has the option to request the status by calling the Get /payments/status API of the Open Banking Service. 

Wero single immediate payment sequence diagram
Enable "on this page" menu on doc section
On

WERO

WERO

These pages describe the components from the Open Banking API version 3 which are used to initiate a WERO payment. WERO is an European payment system created by the European Payments Initiative (EPI). It helps facilitate quick, secure, and straightforward bank-to-bank (A2A) transactions for individuals and companies. 

If you would like to learn about the various ways WERO can be used, we recommend visiting this very informative interactive website: Wero - Digital Payment Wallet. The page is published by EPI - owner of the Wero brand - and presents practical use cases for individuals and businesses, offers interactive demos to explore how it works, and provides step-by-step guidance to get started, including onboarding paths and deployment timelines, plus essential privacy and security notes.

Here you learn, how Worldline simplifies the WERO flow - one single API, which is used for nearly all payment means, does all needed steps (consent, authorization, capture) in one single call for you. 

Ecosystem overview

The Open Banking Services, marked in green, is provided by Worldline. The Consumer interacts with the Acceptor to start a payment. He is redirected to their Wallet to authenticate/authorize. The Wallet communicates with the EPI Central Services via the Wero API. The Acceptor uses the OB v3 API to talk to Open Banking Services / Acceptor PSP. The EPI Central Services coordinates between the Wallet and the Open Banking Services / Acceptor PSP using the Wero API.

With the Open Banking Service Worldline is a Technical Solution Provider (TSP) within the Wero scheme, providing it's services to the Acceptor PSP. Thereby enabling the Acceptor PSP and it's Acceptors (Merchants) to provide the Wero payment product. 

Wero overview

Terminology

The terminology used in these pages and the mapping to their Payment Service Directive 2 equivalents.

TermEquivalent PSD2 termDescription
Consumer PSPASPSP

The Account Servicing Payment Service Provider (ASPSP); the Issuer bank which is responsible for the Consumer's account.

EPI European payments initiative (EPI Company | Home), owner of both the iDEAL and Wero brand. EPI provides an EPI Central Services hub which connects to the participants of Wero.
AcceptorInitiating PartyThe Acceptor contracts the TSP for the WERO service, and sends a WERO payment request to the Open Banking Service on behalf of a Consumer.
ConsumerPSUThe Consumer is account holder by one or more Consumer PSP's and allows other parties to initiate payment requests. 
SCT Inst The SEPA Instant Credit Transfer is the underlying instant-settlement infrastructure that powers WERO’s real-time payments across Europe. Payments are settled in seconds, available 24/7/365, for transfers between participating banks across the SEPA region. 
Technical Service Provider (TSP)TPPThe Technical Service Provider (TSP) can be contracted by acceptor PSPs or consumer PSPs and be authorised to participate in the payments flow. The 'Open Banking Service' refers to the Worldline provided software, which handles the routing of the WERO payments for the Acceptor PSP.
Wallet The Wero wallet can be a standalone app or can be access through the Consumer PSP's bank app. 
WERO We - Euro, is the new pan European payment system created by the European Payments Initiative (EPI), which will replace iDEAL and other national payment products. It is designed to enable fast, secure payments for individuals and businesses, can be accessed via bank apps or a dedicated mobile app, and aims to become Europe’s standard for digital payments.
EPI Central Services The EPI Central Services operates as the centralized control point for WERO payments, ensuring end-to-end coordination across participants.

Open Banking API features for WERO payments

WERO will support different payments plans, at the moment the following is supported:

  • Single Immediate Payment: For a successful single, immediate payment, the Consumer is strongly authenticated and consents to one payment. The payment is immediately authorized and captured. The money is settled immediately using the SEPA SCT Inst rail.
Enable "on this page" menu on doc section
On

REST API V2 - 2.33.2

REST API V2 - 2.33.2

Version 2.32.0 to 2.33.2

What's New

POST /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/reverse-reimbursement-operation

Reverse a reimbursement operation by external reference (beta)

The API is used to fully reverse a reimbursement operation previously posted on an account. As an input, it must be provided

  • the account, identified either by its account reference generated by WL or its issuer external account reference, on which the reimbursement operation was previously posted
  • the reimbursement operation to be reversed the information related to the reversal operation (reference, date, service poster).

Idempotency is managed by the API; that is, if the request with the same WL-Correlation-ID is sent multiple times, it will be executed only once. The response will be retrieved directly from our system.

POST /issuers/{issuerId}/accounts/{accountReference}/reverse-reimbursement-operation

Reverse a reimbursement operation (beta)

The API is used to fully reverse a reimbursement operation previously posted on an account. As an input, it must be provided

  • the account, identified either by its account reference generated by WL or its issuer external account reference, on which the reimbursement operation was previously posted
  • the reimbursement operation to be reversed the information related to the reversal operation (reference, date, service poster).

Idempotency is managed by the API; that is, if the request with the same WL-Correlation-ID is sent multiple times, it will be executed only once. The response will be retrieved directly from our system.

POST /issuers/{issuerId}/transactions/{transactionId}/dispute

Create a dispute from a transaction (beta)

The API allows an issuer to create a dispute folder in the system for a given operation. This API enables the issuer to initiate the dispute from its application. Several actions can be performed :

  • Dispute only
  • Dispute + refund/redebit (full or partial)
  • Dispute + write-off (full or partial)
  • Dispute + fraud declaration
  • Dispute + event creation
  • Dispute + attach documents
  • Dispute + combination of above options

Main data in input are :

  • the external operation reference which can be retrieved using a search operation in the system, for example using the API retrieves list of operations for an account.
  • in option, several fields in the case additional actions have to be done besides the dispute folder creation (e.g operation(s) posting, event(s) creation, add document(s)).

In response, the created dispute folder identifier is provided back systematically; then depending on the additional requests, the response includes also the posting, event creation and documents add response.

 

What's Changed

GET /issuers/{issuerId}/transactions/{transactionId}
Response:
  • Changed property data (object Transaction)
    • Added property virtualServiceCardReference (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/operations/{operationId}
Response:
  • Changed property data (object Operation)
    • Changed property virtualCardService (object VirtualCardService)
      • Added property virtualServiceCardNumber (string)
POST /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/inquire-operation
Response:
  • Changed property data (object Operation)
    • Changed property virtualCardService (object VirtualCardService)
      • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/{accountReference}/operations/{operationId}
Response:
  • Changed property data (object Operation)
    • Changed property virtualCardService (object VirtualCardService)
      • Added property virtualServiceCardNumber (string)
POST /issuers/{issuerId}/accounts/{accountReference}/inquire-operation
Response:
  • Changed property data (object Operation)
    • Changed property virtualCardService (object VirtualCardService)
      • Added property virtualServiceCardNumber (string)
PATCH /issuers/{issuerId}/contracts/external-contracts/{issuerContractExternalReference}/contract-fees/{accountReference}
Request body :
  • Added property postingAccountForMembershipFee (string)
  • Added property postingAccountForAccountSetupFee (string)
PATCH /issuers/{issuerId}/contracts/external-contracts/{issuerContractExternalReference}/contract-fees/external-accounts/{issuerAccountExternalReference}
Request body :
  • Added property postingAccountForMembershipFee (string)
  • Added property postingAccountForAccountSetupFee (string)
PATCH /issuers/{issuerId}/contracts/{contractReference}/contract-fees/{accountReference}
Request body :
  • Added property postingAccountForMembershipFee (string)
  • Added property postingAccountForAccountSetupFee (string)
PATCH /issuers/{issuerId}/contracts/{contractReference}/contract-fees/external-accounts/{issuerAccountExternalReference}
Request body :
  • Added property postingAccountForMembershipFee (string)
  • Added property postingAccountForAccountSetupFee (string)
POST /issuers/{issuerId}/operations/{externalOperationReference}/disputes
POST /search-transactions
Response:
  • Changed property data (array)
    • Changed items (object Transaction)
      • Added property virtualServiceCardReference (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/statements/last/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/statements/next/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/statements/{cycleClosureDate}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/{accountReference}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/{accountReference}/statements/last/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/{accountReference}/statements/next/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/accounts/{accountReference}/statements/{cycleClosureDate}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
POST /search-operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Changed property virtualCardService (object VirtualCardService)
        • Added property virtualServiceCardNumber (string)
GET /issuers/{issuerId}/contracts/external-contracts/{issuerContractExternalReference}/contract-fees
Response:
  • Changed property data (array)
    • Changed items (object ContractFee)
      • Added property postingAccountForMembershipFee (string)
      • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/contracts/{contractReference}/contract-fees
Response:
  • Changed property data (array)
    • Changed items (object ContractFee)
      • Added property postingAccountForMembershipFee (string)
      • Added property postingAccountForAccountSetupFee (string)
POST /issuers/{issuerId}/corporate-contracts/{contractReference}/add-virtual-cards-accounts-service
Request body :
  • Changed property addCorporateVcaServiceCardsAndAccounts (object CreateCorporateContractRequest.AddCorporateVcaServiceCardsAndAccounts)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CreateCorporateContractRequest.CorporateEmployeeAccount)
        • Changed property contractFee (object CreateCorporateContractRequest.CorporateContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
POST /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}/add-virtual-cards-accounts-service
Request body :
  • Changed property addCorporateVcaServiceCardsAndAccounts (object CreateCorporateContractRequest.AddCorporateVcaServiceCardsAndAccounts)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CreateCorporateContractRequest.CorporateEmployeeAccount)
        • Changed property contractFee (object CreateCorporateContractRequest.CorporateContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/contract
Response:
  • Changed property data (object Contract)
    • Changed property contractFees (array)
      • Changed items (object ContractFee)
        • Added property postingAccountForMembershipFee (string)
        • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/accounts/{accountReference}/contract
Response:
  • Changed property data (object Contract)
    • Changed property contractFees (array)
      • Changed items (object ContractFee)
        • Added property postingAccountForMembershipFee (string)
        • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/card-contracts/external-card-contracts/{issuerCardContractExternalReference}/contract
Response:
  • Changed property data (object Contract)
    • Changed property contractFees (array)
      • Changed items (object ContractFee)
        • Added property postingAccountForMembershipFee (string)
        • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/card-contracts/{cardContractReference}/contract
Response:
  • Changed property data (object Contract)
    • Changed property contractFees (array)
      • Changed items (object ContractFee)
        • Added property postingAccountForMembershipFee (string)
        • Added property postingAccountForAccountSetupFee (string)
PATCH /issuers/{issuerId}/corporate-contracts/{contractReference}/corporate-employee-accounts/{accountReference}
Request body :
  • Changed property contractFee (object ModifyCorporateEmployeeAccountRequest.CorporateContractFee)
    • Added property postingAccountForMembershipFee (string)
    • Added property postingAccountForAccountSetupFee (string)
    • Added property entityIdentifierMembershipFeePosting (object)
    • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/corporate-contracts/{contractReference}/corporate-employee-accounts/{accountReference}
Response:
  • Changed property data (object CorporateEmployeeAccount)
    • Changed property contractFee (object ContractFee)
      • Added property postingAccountForMembershipFee (string)
      • Added property postingAccountForAccountSetupFee (string)
      • Added property entityIdentifierMembershipFeePosting (object)
      • Added property entityIdentifierAccountSetupFeePosting (object)
PATCH /issuers/{issuerId}/corporate-contracts/{contractReference}/corporate-employee-accounts/external-accounts/{issuerAccountExternalReference}
Request body :
  • Changed property contractFee (object ModifyCorporateEmployeeAccountRequest.CorporateContractFee)
    • Added property postingAccountForMembershipFee (string)
    • Added property postingAccountForAccountSetupFee (string)
    • Added property entityIdentifierMembershipFeePosting (object)
    • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/corporate-contracts/{contractReference}/corporate-employee-accounts/external-accounts/{issuerAccountExternalReference}
Response:
  • Changed property data (object CorporateEmployeeAccount)
    • Changed property contractFee (object ContractFee)
      • Added property postingAccountForMembershipFee (string)
      • Added property postingAccountForAccountSetupFee (string)
      • Added property entityIdentifierMembershipFeePosting (object)
      • Added property entityIdentifierAccountSetupFeePosting (object)
PATCH /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}/corporate-employee-accounts/external-accounts/{issuerAccountExternalReference}
Request body :
  • Changed property contractFee (object ModifyCorporateEmployeeAccountRequest.CorporateContractFee)
    • Added property postingAccountForMembershipFee (string)
    • Added property postingAccountForAccountSetupFee (string)
    • Added property entityIdentifierMembershipFeePosting (object)
    • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}/corporate-employee-accounts/external-accounts/{issuerAccountExternalReference}
Response:
  • Changed property data (object CorporateEmployeeAccount)
    • Changed property contractFee (object ContractFee)
      • Added property postingAccountForMembershipFee (string)
      • Added property postingAccountForAccountSetupFee (string)
      • Added property entityIdentifierMembershipFeePosting (object)
      • Added property entityIdentifierAccountSetupFeePosting (object)
PATCH /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}/corporate-employee-accounts/{accountReference}
Request body :
  • Changed property contractFee (object ModifyCorporateEmployeeAccountRequest.CorporateContractFee)
    • Added property postingAccountForMembershipFee (string)
    • Added property postingAccountForAccountSetupFee (string)
    • Added property entityIdentifierMembershipFeePosting (object)
    • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}/corporate-employee-accounts/{accountReference}
Response:
  • Changed property data (object CorporateEmployeeAccount)
    • Changed property contractFee (object ContractFee)
      • Added property postingAccountForMembershipFee (string)
      • Added property postingAccountForAccountSetupFee (string)
      • Added property entityIdentifierMembershipFeePosting (object)
      • Added property entityIdentifierAccountSetupFeePosting (object)
POST /issuers/{issuerId}/corporate-contracts/{contractReference}/add-corporate-employee-cards-accounts
Request body :
  • Changed property addCorporateEmployeeCardsAndAccounts (object CreateCorporateContractRequest.AddCorporateEmployeeCardsAndAccounts)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CreateCorporateContractRequest.CorporateEmployeeAccount)
        • Changed property contractFee (object CreateCorporateContractRequest.CorporateContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
POST /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}/add-corporate-employee-cards-accounts
Request body :
  • Changed property addCorporateEmployeeCardsAndAccounts (object CreateCorporateContractRequest.AddCorporateEmployeeCardsAndAccounts)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CreateCorporateContractRequest.CorporateEmployeeAccount)
        • Changed property contractFee (object CreateCorporateContractRequest.CorporateContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/contracts/external-contracts/{issuerContractExternalReference}
Response:
  • Changed property data (object Contract)
    • Changed property contractFees (array)
      • Changed items (object ContractFee)
        • Added property postingAccountForMembershipFee (string)
        • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/contracts/{contractReference}
Response:
  • Changed property data (object Contract)
    • Changed property contractFees (array)
      • Changed items (object ContractFee)
        • Added property postingAccountForMembershipFee (string)
        • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/corporate-contract
Response:
  • Changed property data (object CorporateContract)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CorporateEmployeeAccount)
        • Changed property contractFee (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/accounts/{accountReference}/corporate-contract
Response:
  • Changed property data (object CorporateContract)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CorporateEmployeeAccount)
        • Changed property contractFee (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/card-contracts/external-card-contracts/{issuerCardContractExternalReference}/corporate-contract
Response:
  • Changed property data (object CorporateContract)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CorporateEmployeeAccount)
        • Changed property contractFee (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/card-contracts/{cardContractReference}/corporate-contract
Response:
  • Changed property data (object CorporateContract)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CorporateEmployeeAccount)
        • Changed property contractFee (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/corporate-contracts/{contractReference}
Response:
  • Changed property data (object CorporateContract)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CorporateEmployeeAccount)
        • Changed property contractFee (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/corporate-contracts/external-contracts/{issuerContractExternalReference}
Response:
  • Changed property data (object CorporateContract)
    • Changed property corporateEmployeeAccounts (array)
      • Changed items (object CorporateEmployeeAccount)
        • Changed property contractFee (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
          • Added property entityIdentifierMembershipFeePosting (object)
          • Added property entityIdentifierAccountSetupFeePosting (object)
POST /issuers/{issuerId}/corporate-contracts/create-corporate-contract
Request body :
  • Changed property addCorporateEmployeeCardsAndAccounts (array)
    • Changed items (object CreateCorporateContractRequest.AddCorporateEmployeeCardsAndAccounts)
      • Changed property corporateEmployeeAccounts (array)
        • Changed items (object CreateCorporateContractRequest.CorporateEmployeeAccount)
          • Changed property contractFee (object CreateCorporateContractRequest.CorporateContractFee)
            • Added property postingAccountForMembershipFee (string)
            • Added property postingAccountForAccountSetupFee (string)
            • Added property entityIdentifierMembershipFeePosting (object)
            • Added property entityIdentifierAccountSetupFeePosting (object)
POST /search-contracts
Response:
  • Changed property data (array)
    • Changed items (object Contract)
      • Changed property contractFees (array)
        • Changed items (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
POST /issuers/{issuerId}/contracts/search
Response:
  • Changed property data (array)
    • Changed items (object Contract)
      • Changed property contractFees (array)
        • Changed items (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/customers/external-customers/{issuerCustomerExternalReference}/contracts
Response:
  • Changed property data (array)
    • Changed items (object Contract)
      • Changed property contractFees (array)
        • Changed items (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/customers/{customerReference}/contracts
Response:
  • Changed property data (array)
    • Changed items (object Contract)
      • Changed property contractFees (array)
        • Changed items (object ContractFee)
          • Added property postingAccountForMembershipFee (string)
          • Added property postingAccountForAccountSetupFee (string)
GET /issuers/{issuerId}/companies/{customerReference}/corporate-contracts
Response:
  • Changed property data (array)
    • Changed items (object CorporateContract)
      • Changed property corporateEmployeeAccounts (array)
        • Changed items (object CorporateEmployeeAccount)
          • Changed property contractFee (object ContractFee)
            • Added property postingAccountForMembershipFee (string)
            • Added property postingAccountForAccountSetupFee (string)
            • Added property entityIdentifierMembershipFeePosting (object)
            • Added property entityIdentifierAccountSetupFeePosting (object)
GET /issuers/{issuerId}/companies/external-customers/{issuerCustomerExternalReference}/corporate-contracts
Response:
  • Changed property data (array)
    • Changed items (object CorporateContract)
      • Changed property corporateEmployeeAccounts (array)
        • Changed items (object CorporateEmployeeAccount)
          • Changed property contractFee (object ContractFee)
            • Added property postingAccountForMembershipFee (string)
            • Added property postingAccountForAccountSetupFee (string)
            • Added property entityIdentifierMembershipFeePosting (object)
            • Added property entityIdentifierAccountSetupFeePosting (object)
POST /search-corporate-contracts
Response:
  • Changed property data (array)
    • Changed items (object CorporateContract)
      • Changed property corporateEmployeeAccounts (array)
        • Changed items (object CorporateEmployeeAccount)
          • Changed property contractFee (object ContractFee)
            • Added property postingAccountForMembershipFee (string)
            • Added property postingAccountForAccountSetupFee (string)
            • Added property entityIdentifierMembershipFeePosting (object)
            • Added property entityIdentifierAccountSetupFeePosting (object)
POST /issuers/{issuerId}/operations/{externalOperationReference}/disputes
Request body :
  • Added property originalValueDate (string)
GET /issuers/{issuerId}/disputes/{disputeFolderReference}
Response:
  • Changed property data (object Dispute)
    • Added property originalValueDate (string)
GET /issuers/{issuerId}/operations/{externalOperationReference}/dispute
Response:
  • Changed property data (object Dispute)
    • Added property originalValueDate (string)
GET /issuers/{issuerId}/disputes/external-disputes/{issuerDisputeExternalReference}
Response:
  • Changed property data (object Dispute)
    • Added property originalValueDate (string)
POST /issuers/{issuerId}/transactions/{transactionId}/dispute
Request body :
  • Added property originalValueDate (string)
GET /issuers/{issuerId}/cards/{cardReference}/disputes
Response:
  • Changed property data (array)
    • Changed items (object Dispute)
      • Added property originalValueDate (string)
GET /issuers/{issuerId}/cards/external-cards/{issuerCardExternalReference}/disputes
Response:
  • Changed property data (array)
    • Changed items (object Dispute)
      • Added property originalValueDate (string)
PATCH /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}
Request body :
  • Added property closureCalendarReference (string)
PATCH /issuers/{issuerId}/accounts/{accountReference}
Request body :
  • Added property closureCalendarReference (string)
GET /issuers/{issuerId}/customers/external-customers/{issuerCustomerExternalReference}
Parameters:

Changed: embed in query

GET /issuers/{issuerId}/customers/{customerReference}
Parameters:

Changed: embed in query

POST /issuers/{issuerId}/cards/search
Parameters:

Changed: embed in query

POST /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/post-payment-operation
Request body :
  • Added property paymentReason (string)
POST /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/post-reimbursement-operation
Request body :
  • Added property reimbursementReason (string)
POST /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/reverse-reimbursement-operation
Parameters:

Added: WL-Username in header

POST /issuers/{issuerId}/accounts/{accountReference}/post-payment-operation
Request body :
  • Added property paymentReason (string)
POST /issuers/{issuerId}/accounts/{accountReference}/post-reimbursement-operation
Request body :
  • Added property reimbursementReason (string)
POST /issuers/{issuerId}/accounts/{accountReference}/reverse-reimbursement-operation
Parameters:

Added: WL-Username in header

POST /issuers/{issuerId}/credit-transfers
Request body :
  • Added property reimbursementReason (string)
POST /issuers/{issuerId}/direct-debits
Request body :
  • Added property paymentReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/operations/{operationId}
Response:
  • Changed property data (object Operation)
    • Added property paymentTrigger (string)
    • Added property paymentReason (string)
    • Added property reimbursementTrigger (string)
    • Added property reimbursementReason (string)
POST /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/inquire-operation
Response:
  • Changed property data (object Operation)
    • Added property paymentTrigger (string)
    • Added property paymentReason (string)
    • Added property reimbursementTrigger (string)
    • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/operations/{operationId}
Response:
  • Changed property data (object Operation)
    • Added property paymentTrigger (string)
    • Added property paymentReason (string)
    • Added property reimbursementTrigger (string)
    • Added property reimbursementReason (string)
POST /issuers/{issuerId}/accounts/{accountReference}/inquire-operation
Response:
  • Changed property data (object Operation)
    • Added property paymentTrigger (string)
    • Added property paymentReason (string)
    • Added property reimbursementTrigger (string)
    • Added property reimbursementReason (string)
GET /issuers/{issuerId}/credit-transfers/{endToEndId}
Response:
  • Changed property data (object CreditTransfer)
    • Added property reimbursementTrigger (string)
    • Added property reimbursementReason (string)
GET /issuers/{issuerId}/direct-debits/{endToEndId}
Response:
  • Changed property data (object DirectDebit)
    • Added property paymentTrigger (string)
    • Added property paymentReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/credit-transfers
Parameters:

Added: reimbursementTriggers in query

Response:
  • Changed property data (array)
    • Changed items (object CreditTransfer)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/direct-debits
Parameters:

Added: paymentTriggers in query

Response:
  • Changed property data (array)
    • Changed items (object DirectDebit)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/statements/last/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/statements/next/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/external-accounts/{issuerAccountExternalReference}/statements/{cycleClosureDate}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/credit-transfers
Parameters:

Added: reimbursementTriggers in query

Response:
  • Changed property data (array)
    • Changed items (object CreditTransfer)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/direct-debits
Parameters:

Added: paymentTriggers in query

Response:
  • Changed property data (array)
    • Changed items (object DirectDebit)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/statements/last/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/statements/next/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
GET /issuers/{issuerId}/accounts/{accountReference}/statements/{cycleClosureDate}/operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)
POST /search-operations
Response:
  • Changed property data (array)
    • Changed items (object Operation)
      • Added property paymentTrigger (string)
      • Added property paymentReason (string)
      • Added property reimbursementTrigger (string)
      • Added property reimbursementReason (string)

      •  

What's Deprecated

POST /issuers/{issuerId}/operations/{externalOperationReference}/disputes

Create Dispute

This API is deprecated and is replaced by the API Create a dispute from a transaction. The API allows an issuer to create a dispute folder in the system for a given operation. This API enables the issuer to initiate the dispute from its application. Several actions can be performed :

  • Dispute only
  • Dispute + refund/redebit (full or partial)
  • Dispute + write-off (full or partial)
  • Dispute + fraud declaration
  • Dispute + event creation
  • Dispute + attach documents
  • Dispute + combination of above options

Main data in input are :

  • the external operation reference which can be retrieved using a search operation in the system, for example using the API retrieves list of operations for an account.
  • in option, several fields in the case additional actions have to be done besides the dispute folder creation (e.g operation(s) posting, event(s) creation, add document(s)).

In response, the created dispute folder identifier is provided back systematically; then depending on the additional requests, the response includes also the posting, event creation and documents add response.

 

Enable "on this page" menu on doc section
On

Digital Signatures

Digital Signatures

In this section we cover the different ways digital signatures are used for Security in the Open Banking API. There are three main uses :

  • Sending authorization requests
    • This applies to all Initiating Parties sending requests to the Open Banking Service.
  • Sending signed requests and responses (iDEAL 2.0 only)
    • This only applies to certain Acquirers in the IDEAL 2.0 service. If not applicable, this section can be skipped.
  • Receiving signed requests and responses (iDEAL 2.0 only)
    • This refers to the Notification requests that the Initiating Party receives from the Open Banking Service.
    • This only applies to certain Acquirers in the IDEAL 2.0 service. If not applicable, this section can be skipped.

Sending authorization requests

On the application level, the Initiating Party is authenticated and authorized by sending a digitally signed request to the POST /token endpoint (see Access Tokens - V1, or Access Tokens - V2). The signature validation allows the Open Banking Service to check the authenticity and integrity of the request. 

This is achieved by applying the "Authorization" scheme as described in https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12 and further detailed below.

The  'Authorization' field consists of the following elements, see also the examples below

  • 'Signature keyId’ =  The thumbprint of the public certificate of the Initiating Party, viewed with the SHA1 algorithm.
  • 'algorithm' = algorithm=”rsa-sha256” or algorithm=”SHA256withRSA”
  • 'headers' = the headers ”app client id date” which are part of the signature, the sequence which they are placed here should also be used in the 'signature'
  • 'signature' = The 'signature' is created with the private key associated with 'keyId' applying the chosen signature 'algorithm'. The string to sign is created by concatenating the lowercased 'headers' field names followed with an ASCII colon `:`, an ASCII space ` `, and the header field value. Leading and trailing optional whitespace (OWS) in the header field value MUST be omitted. If the value is not the last value, then an ASCII newline `\n` is appended. The 'signature' is then created with the private key associated with 'keyId' applying the chosen signature 'algorithm'.

Example: For the request

POST /authorize/token HTTP/1.1
App: IDEAL
Date: Fri, 25 Mar 2022 20:51:35 GMT
Client: idealClient
Id: 434

The concatenated "String to sign" would be:

app: IDEAL
client: idealClient
id: 434
date: Fri, 25 Mar 2022 20:51:35 GMT

The complete 'Authorization' field looks like this:

Authorization: Signature keyId="DCAC7209573D506FC56095B8B23E8555A8F38B29", algorithm="SHA256withRSA", headers="app client id date", signature="guoLSHgl/zGRujqkDnmaWCL8kgCVnDazqkKu7nWU/uAHrS+M9eQsI8ueB4uWgxyPOnZps3vpNgkW1f4aBsdFYLS0jYeup4yhCMN6vis2zfMKxUhZFkjELslQkit9Gwc9pqvcyH0IxUnDLbCQwkiYjf6nGbP1YNfoxVXQpfq6i6CbIXCotLfwH2kbkrnSWwAS5skZY77+znmLDjtP3et2K94C36yPo0EEGqGkQ5xkD7owA7YxzA30xzsvkDvU3hzDzTK5wZmsgVsoyjRvMrokG0HrszUpNTwUtxflukcgs0pH7GuT+JrIpQ55f1dpzULqxeBggnCvD9DRSuKeTakqlw=="

The Initiating Party must upload the used public certificate in the back office portal so that Open Banking Service is able to validate the signature. If the signature can be validated and the sender has a valid subscription, a response containing an access token is returned. 

This access token can be used in all follow-up API requests until it expires. After expiration a new access token must be requested via the POST /token endpoint.

Sending signed requests and responses (iDEAL 2.0 only)

Signing requests and responses could be enforced depending on the Acquirer configuration.

Signing would impact the following cases: 

  • POST /payments API requests 
  • GET /payments/{paymentId}/status API requests 
  • GET /preferences/{id}/ API requests
  • Notification API requests received by the Initiating Party
  • Responses received by the Initiating Party

In this section, we will be looking into signing POST /payments requests and the responses from the Open Banking Service.

If signatures are enforced by the Initiating Party's Acquirer, the following fields will be mandatory in the API requests sent by the Initiating Party to the Open Banking Service:

  • Signature
  • Digest

The Signature 

The digital signing should be done by the Initiating Party by applying the “Signature” scheme as described in https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12

This is equivalent to the “Authorization” scheme and the same procedure is followed to generate the signature and header parts but it uses the Signature field instead of the Authorization field.

In order to generate the signature string that is signed with a key, the Initiating Party must use the values of following HTTP header fields:

  • Digest
  • X-Request-ID
  • MessageCreateDateTime

The headers used to generate the signature string also have to appear in the `headers` parameter of the Signature field, as shown below:

headers=”digest x-request-id messagecreatedatetime (request-target)”

To include the HTTP request target in the signature calculation, use the special `(request-target)` header field name. You can generate the header field value by concatenating the lowercased :method, an ASCII space, and the :path.

The (request-target) header field value to be used for the different APIs is:

API(request-target) header field value
POST /paymentspost /xs2a/routingservice/services/ob/pis/v3/payments
GET /payments/{paymentId}/statusget /xs2a/routingservice/services/ob/pis/v3/payments/{paymentId}/status*
GET /preferences/{Psuid}get /xs2a/routingservice/services/ob/pis/v3/preferences/{psuId}*

*The placeholders {paymentId} and {psuId} must be substituted with the values as obtained within the respective flows.

The signature string is created by concatenating the lowercased header field names followed with an ASCII colon `:`, an ASCII space ` `, and the header field value. Leading and trailing optional whitespace (OWS) in the header field value MUST be omitted. If the value is not the last value, then an ASCII newline `\n` is appended.

Example: For the payment request with the following required headers

POST /payments HTTP/1.1
digest: SHA-256=B/O1sG0L8+bEAqWF3aMZn3I0rx5YVi8r5cM6JHlTW7Q=
x-request-id: 1aad5e0f-02d7-aefb-61e3-6f4d3322cf71
messagecreatedatetime: 2023-03-15T10:07:26.264Z

The concatenated "Signature String" would be:

digest: SHA-256=B/O1sG0L8+bEAqWF3aMZn3I0rx5YVi8r5cM6JHlTW7Q=
x-request-id: 1aad5e0f-02d7-aefb-61e3-6f4d3322cf71
messagecreatedatetime: 2023-03-15T10:07:26.264Z
(request-target): post /xs2a/routingservice/services/ob/pis/v3/payments

The resulting signature parameter of the Signature field would be: 

signature="N7kFLMMi/2R5hCd1gdO+GYhS70DOLMl+n8hborf42nFuu0HFjreoqU70gvxFWzgTPaWjdmNYY/7sOAUAQWudsM61Vc536XmaOGrrSxOINlH9l9QBk31xZMlJBf/+1+GtPb1BR26PYBjxKDMbN9W7PEVZLCDoObSnVLkvKbkLRWl0U8a39mDkUBu70Jw8yWusDU0g1OVN+5YRfENPNtC2ZnVD80gxih4JoFV6f4WCcX4HXVl229veFNO5joNQyUc7qOkXUGN2g0omgN4iJxVGnzEJ9BCrNe+vK9T25LC0fwSp/W6A9dDfuHQzMZgDJZZKpaX0Gg34i68etmi5oLrM3A=="

The algorithm parameter of the Signature field is:

algorithm=”rsa-sha256” or algorithm=”SHA256withRSA”

The ‘keyId’ parameter of the Signature field is the thumbprint of the used certificate, viewed with the SHA1 algorithm. The private key associated with `keyId` is used to generate a digital signature on the concatenated signature string applying the chosen algorithm. The complete Signature header looks then like this:

Signature: keyId="DCAC7209573D506FC56095B8B23E8555A8F38B29", algorithm="SHA256withRSA", headers="digest x-request-id messagecreatedatetime (request-target)", signature="N7kFLMMi/2R5hCd1gdO+GYhS70DOLMl+n8hborf42nFuu0HFjreoqU70gvxFWzgTPaWjdmNYY/7sOAUAQWudsM61Vc536XmaOGrrSxOINlH9l9QBk31xZMlJBf/+1+GtPb1BR26PYBjxKDMbN9W7PEVZLCDoObSnVLkvKbkLRWl0U8a39mDkUBu70Jw8yWusDU0g1OVN+5YRfENPNtC2ZnVD80gxih4JoFV6f4WCcX4HXVl229veFNO5joNQyUc7qOkXUGN2g0omgN4iJxVGnzEJ9BCrNe+vK9T25LC0fwSp/W6A9dDfuHQzMZgDJZZKpaX0Gg34i68etmi5oLrM3A=="

In order for the Open Banking Service to validate the signature, the Initiating Party must upload the public certificate to the back office portal. Once the signature is confirmed and the iDEAL Subscription is authenticated, the Initiating Party will receive a successful response.

The Digest header

Calculate the Digest header as follows:

  • Step1: Create a SHA-256 hash of the Payload
    • Note-1: if the output is hex-encoded, please make sure to convert it to binary data (convert the hex-encoded string to a byte array)
    • Note-2: payload formatting is important. If the Digest is generated by using an unformatted JSON payload, then please make sure that it matches with an unformatted request body used in the API request.
  • Step 2: Base64-encode the SHA-256 hash
  • Step 3: Prepend 'SHA-256=' to the resulting base64-encoded value

Example payload :

{"PaymentProduct":["IDEAL"],"CommonPaymentData":{"Amount":{"Type":"Fixed","Amount":"10.00","Currency":"EUR"},"RemittanceInformation":"Cookie","RemittanceInformationStructured":{"Reference":"iDEALpurchase21"}},"IDEALPayments":{"UseDebtorToken":false,"FlowType":"Standard"}}

Step 1: The SHA-256 hash of this request body is: 0d426d36fca1659980b9e371b25e2f17281bb285a634290d3da04233249b56ca. (Note: this is a hex-encoded representation)

Step 2: The base64-encoded hash (Note: hex to base64 encoding): DUJtNvyhZZmAueNxsl4vFygbsoWmNCkNPaBCMySbVso=

Step 3: The Digest header value: SHA-256=DUJtNvyhZZmAueNxsl4vFygbsoWmNCkNPaBCMySbVso=

Receiving signed requests and responses (iDEAL 2.0 only)

Receiving signed requests and responses could be enforced depending on the Acquirer configuration. In the event the Acquirer enforces Signatures, the following headers will be present in the API requests and responses received by the Initiating Party: 

  • Signature
  • Digest

The digital signing performed by the Open Banking Service is done by applying the same “Signature” scheme as described above.

A notification request or response from Open Banking Service to the Initiating Party may contain the following headers (Signature and Digest included in the example):

Headers: {Authorization=Bearer iDEAL2.0testnotificationtoken, X-Request-ID=7e04be55-f710-4660-8254-a48d0246d56b, MessageCreateDateTime=2024-01-30T17:03:52.111+01:00, Digest=SHA-256=9CfdR8v5UlVl8YHNnpbO4v6uB/1B0EtWGLtnP7t2iVs=, Signature=keyId="3EBEF6033C00730D9C6DA05165A3CAA1F31036FB",algorithm="rsa-sha256",headers="messagecreatedatetime x-request-id digest",signature="v+IzPw8RKwGD3GWgLyuy/4RbA25PVwJxpvzs8QbqfAGLUSvOLhEL9dpQwvZi05DDbC80Z+1H7Kdyh3DumXRdayY7XYnunA05tcirszq1fOmESP5S6iw0It9XoV5u/L8EPTgMvOXYECuDT+zVKDsB0PXRIyfT1p+kS1iKc7kckPvDycVGRYMyfXHATmcrlHY6lSjMuw7WMlBOUo9Ac+dU8AQeqWzpzFjMa2Nd5XZkhd1vyKeVqh5cmWapJ2tZDk4/FwDZnpH3Po9PWKXwX/s+UolR/vlIUcRw+avIhU7L6Qme7JDQDpZlcAgJfj/OpF8ZDlb6yfW32yFFzYnkMyGdYQ==",   Content-Type=application/json}

In order to ensure that the contents of the sent messages are correct and have not been altered during transmission or storage, the Initiating Party can validate the received signature. For the validation of the signature, the Initiating Party can use the public certificate of the Open Banking Service which can be downloaded from the back office portal.

The high-level steps that a Initiating Party needs to take in order to validate the Signatures are:

  1. Digest calculation (as Digest is a part of the Signature)
  2. Signature validation by re-creating the signature string 

The above steps (1) and (2) are detailed below to describe the process behind signature validation. 
These steps are by default followed if standard signature validation libraries are used by the Initiating Party. 

Digest header calculation for Notification requests and API responses 

To verify the digest header, calculate the value and ensure you receive the same value as what is in the header of the Request/Response from the Open Banking Service. This is demonstrated below using a Notification request body. 

{"PaymentProductUsed":"IDEAL","CommonPaymentData":{"PaymentStatus":"Expired","PaymentId":"141110","AspspPaymentId":"0001115682120510","AspspId":"10002","DebtorInformation":{"Name":"Edsger Wybe Dijkstra - Callback","Agent":"ABNANL2AXXX","Account":{"SchemeName":"IBAN","Identification":"NL44RABO0123456789"}}}}

Step 1 : The Open Banking Service always sends unformatted JSON payloads in the Requests/Reponses towards the Initiating Party. However, in case the Initiating Party sees a pretty-printed JSON object (e.g. by viewing logs via a tool), the payload should be converted to an unformatted JSON. All blank spaces should be removed unless they are part of the field value (Example: the debtor name has spaces which can remain).

Step 2 : Create a SHA 256 hash of this payload: b1219370189b7c7d67f64fd6f72168187343d639f3aeada8ea3a2b36e0fac297
Note that this string is hex encoded.

Step 3 : Convert this hex encoding to a base64 encoding : sSGTcBibfH1n9k/W9yFoGHND1jnzrq2o6jorNuD6wpc=

Step 4 : Finally prepend "SHA-256=" to the value. The final value is : SHA-256=sSGTcBibfH1n9k/W9yFoGHND1jnzrq2o6jorNuD6wpc=

This value should match the Digest as sent by the Open Banking Service. 

Signature validation in Notification requests and API responses

The digital signing is done by the Open Banking Service by applying the “Signature” scheme as described in https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12.

In order to verify the signature header, the Initiating Party should recreate the signature with the steps outlined below: 

Re-create signature string

In order to generate the signature string that is signed with a key, the Initiating Party must use the values of HTTP header fields:

  • MessageCreateDateTime
  • X-Request-ID
  • Digest

The headers used to generate the signature string also have to appear in the `headers` parameter of the Signature header, in the fixed order appearing below:

headers=”messagecreatedatetime x-request-id digest”

The signature string is created by concatenating the lowercased HTTP header field names followed with an ASCII colon `:`, an ASCII space ` `, and the HTTP header field value. Leading and trailing optional whitespace (OWS) in the HTTP header field value MUST be omitted. If the value is not the last value, then an ASCII newline `\n` is appended.

Example: For the notification request with the following required headers

POST /notification/status HTTP/1.1
Digest: SHA-256=9CfdR8v5UlVl8YHNnpbO4v6uB/1B0EtWGLtnP7t2iVs=
X-Request-ID: 7e04be55-f710-4660-8254-a48d0246d56b
MessageCreateDateTime: 2024-01-30T17:03:52.111+01:00

The concatenated "Signature String" would be:

messagecreatedatetime: 2024-01-30T17:03:52.111+01:00
x-request-id: 7e04be55-f710-4660-8254-a48d0246d56b
digest: SHA-256=9CfdR8v5UlVl8YHNnpbO4v6uB/1B0EtWGLtnP7t2iVs=

The string to verify is now defined and it can be validated using the public key of the Open Banking Service which can be downloaded from the Open Banking Service GUI.

Validate signature

The signature parameter of the Signature header sent by the Open Banking Service was: 

Base64 encoded signature

signature="v+IzPw8RKwGD3GWgLyuy/4RbA25PVwJxpvzs8QbqfAGLUSvOLhEL9dpQwvZi05DDbC80Z+1H7Kdyh3DumXRdayY7XYnunA05tcirszq1fOmESP5S6iw0It9XoV5u/L8EPTgMvOXYECuDT+zVKDsB0PXRIyfT1p+kS1iKc7kckPvDycVGRYMyfXHATmcrlHY6lSjMuw7WMlBOUo9Ac+dU8AQeqWzpzFjMa2Nd5XZkhd1vyKeVqh5cmWapJ2tZDk4/FwDZnpH3Po9PWKXwX/s+UolR/vlIUcRw+avIhU7L6Qme7JDQDpZlcAgJfj/OpF8ZDlb6yfW32yFFzYnkMyGdYQ=="

The signature algorithm used is also contained in the Signature header: algorithm=”SHA256withRSA”

In order to verify a signature, a server MUST:

  1. Re-create the signature string (see step above)
  2. Hash the signature string with SHA256
  3. Verify the signature with the public key of the Open Banking Service. 
Enable "on this page" menu on doc section
On

Notification Bearer Tokens

Notification Bearer Tokens

Notification Bearer Tokens are sent in the Authorization header of notifications sent from the Open Banking Service to the Initiating Party. Currently two Notification types exist:

  • Status Notification requests
  • Debtor token Callback requests

The Notification Bearer Token can be configured in the back office portal under a specific Subscription. Depending on the subscription one or more options exist: 

  • Static token
  • OAuth Client Credentials (Basic Auth)
  • OAuth Client Credentials (Query Parameters)
  • OAuth Client Credentials (Form Body) 

The 'Static token' does not have a set validity period. 

When receiving the notification request, the Initiating Party should verify that the value of the Notification Bearer Token matches what was set in the Subscription to ensure that the request is sent by Worldline.

Enable "on this page" menu on doc section
On

Access Token - Version 2

Access Token - Version 2

API Reference

To interact with the Open Banking Service securely, you need to retrieve an access token. At the moment a version 2 token can only be used for the VOP service, in the future you will be able to use the same v2 token for multiple services. Via this API JSON Web Tokens (JWT) are granted by the Central Authentication Service, as specified by RFC 7253.  

You can retrieve a version 2 token in 2 steps:

Step 1 - Get your Client Id/Secret

The Client Id and the secret will be provided to you by Worldline. 

Step 2 - Retrieve an access token using Client Id/Secret

Endpoint : POST /token
Base URL: /realms/merchant-clients/protocol/openid-connect

The tables below explain which fields have to be filled when requesting a token with Client Id/Secret. 

Request
Header fieldsMult.TypeDescription
Content-Type1..1String

Must be filled with "application/x-www-form-urlencoded"

If not provided, the Initiating Party can expect to come across the error "415, Unsupported Media Type".

The URL encoded form fields to be provided in the body of the request can be found in the table below:

Body fieldsMult.TypeDescription
grant_type1..1StringMust be filled with: client_credentials
client_id1..1StringThe Id of the client. The value will be provided to you by Worldline.
client_secret1..1StringMust be filled with the secret. The secret will be provided to you by Worldline.
scope1..1StringThe list of the services. At the moment VOP and WERO are allowed. The Open Banking Service checks if you have a valid subscription for the requested service.
Response
Body fieldsMult.TypeDescription
access_token1..1StringJson Web Token to be used in further API calls. The contents of the access_token can be viewed by base64 decoding the text between the dots, or a tool like https://jwt.io/ can be used.
expires_in1..1Integer

Expiration time in seconds, relative to when the token was issued. 

The time the token was issued is stored within the access_token string. Name of the field is 'iat', which is filled with a unix timestamp

refresh_expires_in1..1IntegerThere is no refresh supported for Initiating Party Access Tokens. The field will always be filled with: 0
token_type1..1StringType of the token. The field will always be filled with: Bearer
not-before-policy1..1IntegerFilled with a unix timestamp. The token cannot be used before this timestamp. This feature is not used at the moment, the token will be valid immediately. The field will be filled with: 0
scope1..1StringThe list of the services for which the token is valid, it's a space separated list.

Upon a successful request, the Open Banking Service provides you with an access token, which must be used in all future API interactions. The access token allows the Open Banking Service to validate and authorize your API requests. 

The Authorization header is constructed as follows:

Authorization: Bearer {access_token}

The {access_token} part must be replaced by the value of access_token, for example:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2l...qaVI-mQ3XeEqDcf4P3OrzMJBiQ

Example Post /token

Request
grant_type: "client_credentials"
client_id: "ExampleClient-000001"
client_secret: "testtest"
scope: "VOP"
Response
ResponseCode: 200Headers: {X-Request-ID=2aa0dc88-21dd-4034-a027-1d98123596f1, MessageCreateDateTime=2024-02-08T18:31:38.385Z, Date=Thu, 08 Feb 2024 18:31:38 GMT, Content-Type=application/json;charset=UTF-8}Payload: {
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnWEpSa0VzdGVHMjVoYnVTU0lOS1ZPZEdGV3B6NkstMlg2MklkVzVOc1BFIn0.eyJleHAiOjE3MjY1MDEzMTIsImlhdCI6MTcyNjUwMTAxMiwianRpIjoiOTU4N2FkYTQtMGI3NC00NjcxLWI5OWItZmU3YjBiMWRkZWQ0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MjgwL2F1dGgvcmVhbG1zL21lcmNoYW50LWNsaWVudHMiLCJzdWIiOiI0ZDllYmUxNi1kZTkwLTRiMjctYjk4ZC1jNWVmYmE0M2E3NDYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJXb3JsZGxpbmUtMDAwMDIyIiwiYWNyIjoiMSIsInNjb3BlIjoiQUlTIiwiY2xpZW50SWQiOiJXb3JsZGxpbmUtMDAwMDIyIiwiY2xpZW50SG9zdCI6IjE5Mi4xNjguMS4xIiwicm9sZXMiOlsiSU5JVFAiXSwiZW52IjoibWVyY2hhbnQtY2xpZW50cyIsImluaXRpYXRpbmdQYXJ0eSI6IjAwMDAyMiIsImNsaWVudEFkZHJlc3MiOiIxOTIuMTY4LjEuMSIsInRlbmFudCI6IldvcmxkbGluZSJ9.pjro9uLmDcQiqzpIaE2JxpyIbRyVAQ-_CWzoWB0nxzuWXBIzpwWZ__R9RYl6zdNYb2_wBoVNs_bt6mQiTIWn-0oQ-5te5LujLehvCbVJZntK_C9mD80mobEuhDXnJiZCxPVS2hWD4FwYeSpy7mM0Vm3iCMZqtsIERmzm5QFQAY6N1Ym1al_gLIkFgYtaAo1hM-8ZpNCacEB4J8HtBzkOIvNsNegUZ4qdPp7N_Vl2u4pyecxrpNe_VdXPNQftncbQUE9JBOM12jp8G7ncEKW9PH29yKlapKWX_ssMvngGwGSTfZNR-GsQKrcnzef5A_rOjbv8ozUsHeMbLPA4Lh0yDA",
"expires_in": 300,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0,
"scope": "VOP"
}

The token in the example will grant access to the VOP service. 

Validity of access tokens

If you ask for a new token you will get a new token. Older tokens which are valid can still be used. 

 

Enable "on this page" menu on doc section
On