Session
The concept of sessions was introduced to enable the execution of multiple flows in an efficient manner as the consumer has to authorize the access only once per session. For example: It might be convenient to first check the balance of an account to ensure sufficient funds for a following transfer.
Without sessions the consumer would first have to grant access to the account in order for the TPP/merchant to retrieve the balance information. Then the consumer would have to grant access to the account once again and would possibly have to provide a one-time password that could be required to complete the transfer. With sessions, the second redundant access grant is not necessary.
For this concept to work smoothly a bank and the corresponding login is bound to the session, meaning it can not be changed any more during the session.
Starting a Session
A session can be started by making a PUT request towards the XS2A API endpoint /xs2a/v1/sessions
.
This request needs to be authenticated.
The Request
PUT /xs2a/v1/sessions HTTP/1.1
Content-Type: application/json
Authorization: Token <Token>
Host: <Host>
<payload>
curl -X "PUT" "<Host>/xs2a/v1/sessions" \
-H "Authorization: Token <Token>" \
-H "Content-Type: application/json" \
-d $'<payload>'
The following properties can be specified in the JSON payload:
{
"selected_bank": ?{
"bank_code": String,
"country_code": String
},
"language": ?String,
"allowed_countries": ?Array<String>,
"preselected_country": ?String,
"psu": {
"user_agent": String,
"ip_address": String
},
"redirect_return_url": ?URL,
"consent_scope": ?{
"accounts": ?{
},
"account_details": ?{
"ibans": ?Array<String>
},
"balances": ?{
"ibans": ?Array<String>
},
"transactions": ?{
"ibans": ?Array<String>,
"last_days": ?Integer,
"from_date": ?Date,
"to_date": ?Date
},
"transfer": ?{
"ibans": ?Array<String>
},
"insights_refresh": ?{
"intended_reports": ?Array<IntendedReport>,
"ibans": ?Array<String>,
"insights_account_ids": ?Array<String>,
"insights_consumer_id": ?String,
"refresh_days": ?Integer,
"from_date": ?Date,
"to_date": ?Date
},
"lifetime": ?Integer
},
"prefill": ?{
"pno" : ?{
"value": String
},
"force_mobile_bank_id": ?{
"value": Boolean
},
"force_customer_type": ?{
"value": Enum<'PRIVATE','BUSINESS'>
},
"organization_registration_ids" : ?{
"values": Array<String>,
"verification_mode": ?Enum<'NONE', 'CONFIRM', 'FORCE_IF_SUPPORTED', 'FORCE'>
}
},
"client_consumer_id": ?String,
"client_correlation_id": ?String,
}
The object identifies the bank that should be selected for the session.
If there should not be a preselected bank, the selected_bank
property has to be omitted.
Needs to be specified if the bank search in the Open banking. by Klarna XS2A App should be skipped. If the BankUniverse API is used to fetch a bank code we do not always provide a bank code because of country specifics or a bank simply does not have one. In this case, you can as well pass values from the fields bic_bank_codes, synthetic_bank_codes, or local_routing_numbers in here.
The country_code
property needs to be specified if the bank search in the Open banking. by Klarna XS2A App should be skipped. It must comply with the ISO 3166-1 alpha-2 representation of the country, e.g. DE
, GB
, SE
.
The language
property specifies in which language the banks website will be accessed.
This determines which language the consumer sees e.g in the login-form.
A default language is used if the language is not specified or not supported.
However caution is advised as a bank-website might not support the specified language.
The language must comply with the ISO 639-1 representation of the language name.
Country code | Default language | Supported languages |
---|---|---|
AT | de | de, en |
BE | nl | nl, fr, de, en |
CH | de | de, fr, it, en |
CZ | en | en |
DE | de | de, en |
EE | en | en |
ES | es | es, en |
FI | fi | fi, sv, en |
FR | fr | fr, en |
GB | en | en |
HU | en | en |
IT | it | it, en, de |
LU | en | en |
NL | nl | nl, en |
NO | nb | nb, en |
PL | en | en, en |
PT | pt | pt, en |
IE | en | en |
SE | sv | sv, en |
SK | en | en, de |
US | en | en |
The allowed_countries
property is used to only allow banks from the specified countries for this session.
The country identifiers in the list must comply with the ISO 3166-1 alpha-2 representation of the country, e.g. DE
, GB
, SE
.
The preselected_country
property is used to preselect a country for the Klarna bank search, e.g. DE
, GB
, SE
.
The psu
property contains information about the consumer (payment service user).
The user_agent
property holds the user agent string of the consumer's client application, e.g. the web browser.
The ip_address
property holds the IP address of the consumer. Both IPv4 and IPv6 are accepted formats.
The redirect_return_url
parameter defines the URL to which the consumer is redirected after the interaction with the banks website is completed.
If you integrate our offering in a mobile application we recommend setting this parameter, as it can be used to redirect back to the Android or iOS app. Additionally, we recommend following the guide on mobile redirects.
The consent_scope
property is used to request concrete scopes before starting a flow.
Specifying consent scopes may lead to fewer strong customer authentications because the customer only has to grant access for the required scopes.
If the consent_scope
field is not defined all AIS- and PIS-scopes are requested with a lifetime of 90 days. Scopes are only applied for PSD2 interfaces and ignored otherwise.
Note that our service might request additional scopes to the ones defined in this field if it is necessary for the successful execution of a flow.
The lifetime
property defines for how many days the consent should be valid for. It can be any integer between 1 and even more than 180 depending on the bank whereas 1 should be used for one-time or 24 hour access. The default value is 90 days.
This means that the lifetime
property defines for how long a consent can be used with the Consent API except for the transfer state.
Note that banks have different consent lifetimes. Details on the bank consent capabilites can be found in the Bank Universe.
As depicted in the JSON structure above, the consent can be scoped for one or multiple flows by providing a consent_scope.<flow_type>
property with <flow_type>
being one of the flow types (accounts
, account_details
, balances
, transactions
, transfer
, insights_refresh
).
The default value for this parameter is an empty object.
A list of sender IBANs can be provided in the ibans
property in order to restrict the scope for the flow type to the specified IBAN(s).
ibans
is a valid property for all but the accounts
flow as this is used to obtain the IBANs of a consumer.
The from_date
property (in combination with the to_date
property) describes the range of transactions to retrieve.
The from_date
property marks the inclusive start of the range.
A broad timerange can lead to additional strong customer authentication steps.
This can only be used in combination with consent_scope.transactions.to_date
and not in combination with consent_scope.transactions.last_days
.
The to_date
property (in combination with the from_date
property) describes the range of transactions to retrieve.
The to_date
property marks the inclusive end of the range.
This can only be used in combination with consent_scope.transactions.from_date
and not in combination with consent_scope.transactions.last_days
.
The date range defined by consent_scope.transactions.from_date
and consent_scope.transactions.to_date
is final for the resulting consent. If you plan to fetch transactions from any other dates then those dates need to be included. For example to fetch transactions on each day for the next 90 days then to_date
= today + consent_scope.lifetime
(90 days).
The last_days
field can be used to query the last X days from today. The time range will automatically adapt to provide future transactions until the end of the lifetime of the consent as specified in consent_scope.lifetime
.
If neither to_date
and from_date
nor last_days
are provided we will default to 90
being set for last_days
.
The insights_refresh
flow requires more detailed information. It is needed to provide all data for the required flows, which would be triggered by the insights_refresh flow. This will be determined by the intended_reports property.
With the intended_reports
property the kind of insights will be determined. This will trigger other flows, which might require some additional information (e.g. the from_date
property). If missing, all AIS flows will be triggered to ensure enough data for any insight will be stored/refreshed.
Supports the filter for accounts via list of IBANs, see more details here.
A list of Account Insights identifiers representing an account used by a previous insights_refresh flow. Also the corresponding consumer of those accounts must be provided in the insights_consumer_id
parameter.
The insights_consumer_id
identifies the consumer and is required if any insights_account_ids
are sent.
This parameter allows to define a timeframe without the need to calculate dates. If refresh_days
provides a value, the parameters from_date
and to_date
will be derived from current day (today) minus the given number of days.
The timeframe for which the data should be updated can be set by specifying either the from_date
and to_date
parameters or this refresh_days
parameter. If no timeframe is specified, the default timeframe of the last 62 days will be used.
The from_date
property (in combination with the to_date
property) will be used as the inclusive start date for the account information to be retrieved.
The timeframe for which the data should be updated can be set by specifying either the from_date
and to_date
parameters or this refresh_days
parameter. If no timeframe is specified, the default timeframe of the last 62 days will be used.
The to_date
property (in combination with the from_date
property) will be used as the inclusive end date for the account information to be retrieved.
The timeframe for which the data should be updated can be set by specifying either the from_date
and to_date
parameters or this refresh_days
parameter. If no timeframe is specified, the default timeframe of the last 62 days will be used.
The prefill
property can be used to provide data that will be automatically prefilled or preselected in forms that the consumer encounters.
For each form all applicable provided data is prefilled. If all required fields are filled the form will also be submitted automatically.
The prefill feature is currently only available for Swedish banks.
The pno
property is an object that holds information about the swedish personal identity number (Swedish: personnummer).
The value
property has to be a string containing the personal identity number.
The force_mobile_bank_id
property is an object that holds information about forcing the BankID authentication in Sweden.
The value
property has to be a boolean indicating whether the BankID authentication should be enforced if available.
The force_customer_type
property is an object that holds information about the selection of the private or business account connection. It allows an automatic selection in case a bank offers such a selection. No automatic selection is done in case of doubt, e.g. there are more than 1 possible option or the options given are unclear.
The value
property has to be one of two possible values:
private
business
The organization_registration_ids
property is an object that holds its configuration, for example prefilling or verification modes.
The values
property is a string array that contains the organization registration id(s). These will be used to prefill the corresponding input field if it is supported.
An enum that can be configured to verify the usage of the prefilled value. If set to anything other than NONE
It will verify if the organization registration id(s) that was submitted towards the bank is matching against the one(s) that was configured in prefill.organization_registration_ids.values
.
The result can be fetched in the "GET session" response.
The verification_mode
property can be one of four possible values:
NONE
No verification is being made. Default value.CONFIRM
The flow will not be aborted in any case.FORCE_IF_SUPPORTED
The flow will be aborted if it is supported by the integration and the organization id(s) submitted to the bank is different from thevalues
property that was configured.FORCE
Same asFORCE_IF_SUPPORTED
and also aborts if prefilling organization ids is not supported by the integration.
The client_consumer_id
property holds a unique ID per consumer that can be used to identify the consumer throughout multiple sessions.
The client_correlation_id
property holds unique information to identify the session in the Open Banking Portal.
For further configuration on the session creation call a white label integrator can visit the White Label Integration section.
Example consent scope structure to request all AIS scopes without PIS for one day
{
...
"consent_scope": {
"accounts": { },
"account_details": { },
"balances": { },
"transactions": { },
"lifetime": 1
},
...
}
Example consent scope structure to request only a PIS scope for a pre-defined account
{
...
"consent_scope": {
"transfer": {
"ibans": [ "DE06000000000023456789" ]
},
"lifetime": 1
},
...
}
The Response
After a successful call is made the following response is returned along with a 201 CREATED
status code:
HTTP/1.1 201 Created
Content-Type: application/json
{
"data": {
"session_id": String,
"session_id_short": String,
"self": URL,
"consent": URL,
"flows": {
<flow_type>: URL,
...
}
}
}
The data
property wraps the actual information in every response returned by the XS2A-API and has no other purpose.
The session_id
property holds a unique id which identifies the XS2A-API session.
This id should be saved for later use and debugging purposes.
The session_id_short
property holds a non-unique 8 character code.
The code can be shown to the consumer and used for interaction with customer service.
The self
property holds a url which identifies the session and has to be saved for further calls.
This url is bound to the session and can not be used for other sessions.
The consent
property holds a url which can be called to retrieve the consent, if available.
This url is bound to the session and can not be used for other sessions.
For more information see the documentation about fetching the consent token.
The flows
property is a map that holds flows.
Each entry in the flows
property represents a flow of the type specified by the entry's key (flow_type
).
The value of an entry is the url that, when called, starts a flow of the specified type.
Getting Information about a Session
The Request
In order to obtain information about a session on the XS2A-API the self
-url that is returned in the CREATE call when initiating a session needs to be called with GET:
GET <session.self> HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Token <Token>
curl "<session.self>" -H "Authorization: Token <token>"
There is no payload attached.
The Response
After a successful call is made the following response is returned:
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": {
"session_id": String,
"session_id_short": String,
"state": Enum<'IN_FLOW', 'IDLE', 'EXCEPTION', 'CLOSED'>,
"current_flow": ?{
"flow_id": String,
"url": String,
"type": String
},
"previous_flows": Array<{
"flow_id": String,
"url": String,
"type": String
}>,
"bank": {
"bank_name": ?String,
"country_code": ?String,
"bank_code": ?String,
"connection": ?Enum<'PSD2', 'FALLBACK'>,
"bank_krn": ?String,
"integration_krn": ?String,
"sub_integration_krn": ?String
},
"consumer_id": ?String,
"prefill": ?{
"organization_registration_ids": ?{
"verification_mode": ?Enum<'CONFIRM', 'FORCE_IF_SUPPORTED', 'FORCE'>,
"verification_result": ?Enum<'NONE', 'MATCHING', 'NOT_MATCHING', 'NOT_SUPPORTED'>
},
}
}
}
The data
property wraps the actual information in every response returned by the XS2A-API and has no other purpose.
The session_id
property holds a unique id which identifies the XS2A-API session.
The session_id_short
property holds a non-unique 8 character code.
The code can be shown to the consumer and used for interaction with customer service.
The state
property holds the current state of the session that can be one of the following:
IN_FLOW
- Currently in a running flow. The flow must be aborted or finished before the session can start a new flow or be closed.IDLE
- Currently not in a running flow but still open. Both starting a new flow and closing the session is possible.EXCEPTION
- Session ended in an exception and can not be used anymore.CLOSED
- Session is closed and can not be used anymore.
The current_flow
property holds information about the currently running flow in the session.
A url to call in order to get the state of the flow (see Retrieving Information about a Flow for more information).
The type of the flow (see Flow for a list of possible flow types).
The previous_flows
property is an array holding all flows that were executed before.
The properties of the objects in the previous_flows
array are the same as those listed for the current_flow
object.
The bank
property holds information about the selected bank in the session. All fields are optional and may be filled during the execution of a flow.
The country_code
property holds the ISO 3166-1 alpha-2 country code of the chosen bank, e.g. DE
, GB
, SE
.
The connection
property holds the type of the integration towards the bank. Possible values are PSD2
and FALLBACK
.
The bank_krn
property holds the bank krn, which is an identifier of the chosen bank. Further information can be found here.
The consumer_id
identifies the consumer throughout multiple sessions. It has a maximum length of 512 characters.
The field will only be available after the consumer has successfully logged in.
The prefill
can hold information regarding different topics from what was configured, for example the result of verifying if a configured prefill value was used or not.
organization_registration_ids
can hold information depending on how it was configured in the session creation.
verification_mode
is what was configured in the session creation. It is not present if it was set to NONE
.
If the verification mode is set to NONE
it will not be present.
verification_result
can be one of four different values.
NONE
The verification has not yet been made.MATCHING
The configured value(s) is matching against what was submitted.NOT_MATCHING
The configured value(s) did not match against what was submitted.NOT_SUPPORTED
The prefill fieldorganization_registration_ids
is not supported for the integration in use.
Closing a Session
XS2A sessions should be closed as soon as possible because this, in turn, allows the XS2A API to close the session with the bank. An unclosed session between the XS2A API and the bank might influence or interfere with the consumer's future interaction with the bank.
A quick progression through the XS2A session also reduces the risk of "losing" sessions as some banks terminate sessions that have been inactive for some time. Sessions that have run in such a timeout on bank-side can not be interacted with anymore. Furthermore, these sessions are not ended "properly" and thus sometimes influence the consumer's future interaction with the bank as well.
Data from XS2A sessions with a terminated bank session can still be retrieved up to 30 minutes after the last interaction with the XS2A session. When the XS2A session expires or is closed, the data is deleted from Klarna's systems and can thus not be retrieved anymore.
In case a XS2A session has surpassed the lifetime of 30 minutes or is not usable anymore due to an exception in the flow, the session is closed automatically. We still recommend to actively close a session and not rely on that behaviour for the above mentioned reasons.
How to close a Session
A running session can be closed by making a DELETE request towards the self
-url that is returned when initiating a session.
The Request
DELETE <session.self> HTTP/1.1
Authorization: Token <Token>
curl -X "DELETE" "<session.self>"
-H "Authorization: Token <token>"
There is no attached payload.
The Response
There are 3 possible responses.
HTTP 204
This response indicates that the session was closed successfully.
HTTP/1.1 204 No Content
HTTP 404
This response indicates that either the session_id
is incorrect and no session can be found for that id or the session has surpassed the session lifetime and was already closed as a result and removed from the system.
{
"error": {
"code": "notFound",
"message": "Session for provided id not found"
}
}
HTTP 409
This response indicates that either there is still a flow running as part of the session, meaning the session can not be closed unless the flow is closed or finished, or the session is in a final state, i.e. CLOSED
or EXCEPTION
.
HTTP/1.1 409 Conflict
Content-Type: application/json
The response holds the following payload in case there is still a flow running.
{
"data": {
"code": "CONFLICT",
"message": "Session with id <session.session_id> is still in running flow, finish/end all running flows before closing session"
}
}