Quick Start Guide PIS

This quick start guide for the Payment Initiation Service (PIS) will provide an overview of the process that initates a payment on behalf of the consumer.

API Structure

Open banking. by Klarna features two sets of API endpoints.

The XS2A API is used to configure and start the payment initiation process and retrieve information about it. All endpoints are authenticated.

Whenever consumer interaction is required the client-session based Auth API can be used to obtain and submit forms that the consumer has to fill out.

Starting the Session

In order to initiate a payment for a consumer an XS2A API session has to be created. This can be done by executing a PUT request towards https://api.playground.openbanking.klarna.com/xs2a/v1/sessions.

PUT https://api.playground.openbanking.klarna.com/xs2a/v1/sessions HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Bearer <Token>
curl "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions" -X "PUT" -H "Authorization: Bearer <token>"

Several optional configurations can be made by adding a JSON-payload to this request. If e.g. a bank should be preselected for the sessions the payload would look like this:

{
    "selected_bank": {
        "bank_code": "88888888",
        "country_code": "de"
    },
    "psu": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
        "ip_address": "123.123.123.123"
    },
    "redirect_return_url": "https://merchant.com/redirect-return"
}

While the selected_bank property is optional, the properties psu and redirect_return_url have to be provided.

Once the session is created the request returns the flows that can be executed (among other details about the session).

{
    "data": {
        "session_id": "a14mjk9r6mjknfqschsnc43j915oa74t",
        "self": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t",
        "flows": {
            "balances": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t/flows/balances",
            "transfer": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t/flows/transfer",
            "account_details": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t/flows/account-details",
            "accounts": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t/flows/accounts",
            "transactions": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t/flows/transactions"
        }
    }
}

Starting the Flow

To initiate a payment the transfer flow has to be started in the previously created session. This can be done by executing a PUT request towards the URL provided in data.flow.transfer.

PUT <data.flow.transfer> HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Bearer <Token>
curl "<data.flow.transfer>" -X "PUT" -H "Authorization: Bearer <token>"

The following is an example for the payload that is required for the request to be successful:

{
    "type": "transfer",
    "amount": {
        "amount": 1234,
        "currency": "EUR"
    },
    "reference": "Flowers",
    "preferred_date": "2019-06-30",
    "to": {
        "iban": "DE53100700000648489390",
        "holder_name": "John Doe",
        "bic": "DEUTDEBBXXX",
    }
}

The response of this request could look like this:

{
    "data": {
        "flow_id": "cb7ih6o9u0hp5v9nag3aeppqp562n49g",
        "state": "CONSUMER_INPUT_NEEDED",
        "self": "https://api.playground.openbanking.klarna.com/xs2a/v1/sessions/a14mjk9r6mjknfqschsnc43j915oa74t/flows/cb7ih6o9u0hp5v9nag3aeppqp562n49g",
        "client_token":
            "eyJhbGciOiJSUzI1NiJ9.eyJ4czJhX2FwcF91cmwiOiJodHRwczovL2F1dGgucGxheWdyb3VuZC5vcGVuYmFua2luZy5rbGFybmEuY29tL2NiN2loNm85dTBocDV2OW5hZzNhZXBwcXA1NjJuNDlnIiwid2l6YXJkX3VybCI6Imh0dHBzOi8vYXV0aGFwaS5wbGF5Z3JvdW5kLm9wZW5iYW5raW5nLmtsYXJuYS5jb20veHMyYS92MS93aXphcmQvY2I3aWg2bzl1MGhwNXY5bmFnM2FlcHBxcDU2Mm40OWciLCJ0cmFuc2xhdGlvbnNfdXJsIjoiaHR0cHM6Ly9hdXRoYXBpLnBsYXlncm91bmQub3BlbmJhbmtpbmcua2xhcm5hLmNvbS94czJhL3YxL3RyYW5zbGF0aW9ucy9jYjdpaDZvOXUwaHA1djluYWczYWVwcHFwNTYybjQ5ZyIsImZsb3dfdHlwZSI6InRyYW5zZmVyIn0.mLYn6OQsTL4expO70hVtqqQG1j250aGpHA2mkyrPIs1EuCi_BdwNrHG3jRMMHL2w-JDig-TvpLNSeFPRNhEeFQm7p19aFwoMkKnDvTUuGjuiRMcO3x1RIyyt72KfiOClv2VZXHvp9rszCfQcIdb1LA9vSHlhCDJUfshlFyLBlV2Prp1xPfbUeyYzE3p2RM1kokV5RzVaUvJK-deTTkLYa0qn_oS2ih-M7ydFZ4yX0X4t9EeQ_oK3tD0HmMUxTM57QPfPYb3_aR4N5H1qKaABIwETmCA0COP0dujp141pHPtAhK7o7NLE7lgtKVIV6u8i21VjePyFXfnpg-Z2Rv7XdA"
        }
}

Handling Consumer Interaction

The state CONSUMER_INPUT_NEEDED indicates that the consumer has to provide some sort of information or configuration to enable Open banking. by Klarna to proceed with the flow. Information on the type of user interaction is contained within the JSON Web Token (JWT) in the client_token porperty. Once decoded the payload of the JWT is going to look like this:

{
    "session_id_short": "4MJK9R6M",
    "xs2a_app_url": "https://auth.openbanking.klarna.com/cb7ih6o9u0hp5v9nag3aeppqp562n49g",
    "auth_url": "https://authapi.playground.openbanking.klarna.com/xs2a/v1/wizard/cb7ih6o9u0hp5v9nag3aeppqp562n49g",
    "translations_url": "https://authapi.playground.openbanking.klarna.com/xs2a/v1/translations/cb7ih6o9u0hp5v9nag3aeppqp562n49g",
    "flow_type": "transfer"
}

The actual data about the consumer interaction can then be obtained by executing a GET request towards the URL provided in the auth_url property.

GET <data.client_token.auth_url> HTTP/1.1
Content-Type: application/json;charset=utf-8
Origin: <origin>
curl "<data.client_token.auth_url>" -X "GET" -H "Origin: <origin>"

In this example a one-time-password is required to authorize the payment. Therefore an XS2A Form has to be filled out by the consumer. Hence the response of the previous request could return the following JSON string:

{
    "data": {
        "state": "CONSUMER_INPUT_NEEDED",
        "next": "https://authapi.playground.openbanking.klarna.com/xs2a/v1/wizard/1234567890123456789",
        "result": {
            "type": "form",
            "category": "",
            "message": "",
            "configuration": {},
            "form": {
                "form_identifier": "e807915b-338a-4fc1-988c-089241efab43",
                "elements": [
                    {
                        "content": "Your bank sent an OTP to your mobile phone.",
                        "type": "text",
                        "tags": [],
                        "version": "1.0.0"
                    },
                    {
                        "key": "OTP",
                        "type": "input",
                        "tags": [],
                        "version": "1.0.0",
                        "password": false,
                        "label": "OTP",
                        "placeholder": "",
                        "prefill_value": "",
                        "read_only": false,
                        "validator": {
                            "min_length": 6,
                            "max_length": 6,
                            "required": true,
                            "numeric": true,
                            "letters": {
                                "uppercase": false,
                                "lowercase": false
                            },
                        "symbols": false
                        }
                    }
                ],
                "version": "1.0.0"
            },
            "key": "eyJhbGciOiJSUzI1NiJ9.eyJtb2R1bHVzIjoiZDEwOTA3YzBkZjc4ZmI5ZDMyNmI1NzkyZGExZDg2OGRkNGViZWRiMmM1ODI4M2UxNTQ2NzFmMmZhNWY2OThiYTI3NWJjZGE0YjA4YTMwOTM4MWNiYWRlOGVmMzRhMTJkM2RhOTM3YjlmMjI4N2EyYTZjY2YxYWU4YWI3ZGRhZTM3ZWNmNzRkM2JlYWQ1OTdhNmY0ZjkwNWZiMzczNGIxY2FhOTk0ZDlhMmNmYjZiZjUyYzAwNmU2MDNmN2E1NGFlODM0NmZiY2VhZmQzODQwMjRlOWI4ZjkyOWI3ODNiMDc0MTljZGNlNGZkMmJlYTcxMzNhYjk3N2M2OWQ1NjVhNzZjMGU4MWZiMDk0NGM3N2NkMGJjYmU4ZmQ4YzY5MmQ3MDNlMDY0ZGYwNzE0OGUxMDRlOWU3ZGY1NDgxZjIwMmRkMjBiODk5ZTEwM2FlYTZiMjM1YjkyZDc4Y2I3MGMyNTNjMjE0NzcyNWVhYmVhMWU4NDZlM2YwZDgzNmYzODZiNzc3YmMwNmYyZWQzZjVmNzllMzA1YjIzM2I3OWQ1OGI3OWVkYjUxOTU5ZGJmYjk4MjM0YmE1MDE3MWVjM2ZlZWMxOTU4Mjc2NDg1NzEyZjI3MDk1ZGNlZDQ4NDVlYjgyMzg4YWVlMmFjOWRlMDc2YzNiMjE1YzY3OTNjMDNmODkiLCJleHBvbmVudCI6IjEwMDAxIn0.zEfK3O9geI1h4l2SaxxUnbfR3pKy0a5CUs3Bfwxgmd56JCOIIMX-l7KhefELqAALekUwFXT0RnMFWmD4DY99p1gT3ETNeZEe_Spv1ednlrVpaMOi68-FT91l3tyoo-XzycCNeTJ1aGqrttZbuMzAOqLfMnwqd0PszzN7pPEDbwEoatWpX5UpTpYQNNDigZHZOHERqaYEP2Kq0YyZUBYxqPPr_Tvm6qGB4iRB6UG3DxIdCoHV_M3fmuHCP62qI9mHArLP96CC4PcAlGnqLUkRQyWgw5Kdfqj0j5LSNq4CHYlva_KcQAFjGYyBd0GwRUrFZPE6VUWda9Lt4dk0AVY1Pw",
            "context": "authorization"
        }
    }
}

A rendering of the XS2A Form in the data.form property in the JSON string above could look like this:

Form with OTP to confirm transfer

Form with OTP to confirm transfer

The data that was entered into the XS2A Form has to be transmitted to the URL provided in the data.state.next property in the response above.

POST <data.state.next> HTTP/1.1
Content-Type: application/json;charset=utf-8
Origin: <origin>
curl "<data.state.next>" -X "POST" -H "Origin: <origin>"

The payload of this POST request has to be encrypted and should be structured like this:

{
    "form_identifier": "e807915b-338a-4fc1-988c-089241efab43",
    "data": [
        {
            "key": "OTP",
            "value": "123456"
        }
    ]
}

Evaluating the Flow's Result

Information about the flow can be obtained by executing a GET request towards the URL provided in the data.self property in the response of the request that started the flow.

GET <data.self> HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Bearer <Token>
curl "<data.self>" -H "Authorization: Bearer <token>"

The response for this request could look like this:

{
    "data": {
        "result": {
            "adjusted_reference": "Flowers",
            "from": {
                "id": "0",
                "alias": "Giro account (Steven Sender)",
                "iban": "DE06000000000023456789",
                "account_number": "23456789",
                "holder_name": "Steven Sender",
                "bank_code": "",
                "bic": "SFRTDE20XXX",
                "transfer_type": "FULL",
                "account_type": "DEFAULT"
            },
            "authentication_method": "MTAN",
            "type": "transfer"
        },
        "state": "FINISHED"
    }
}

The value FINISHED of the property data.state indicates that the payment has been successfully initiated. Furthermore information about the sender account will be provided.

Closing the Session

Once the payment has been initiated the session has to be closed by executing a DELETE request towards the URL that is provided in the data.self property in the response of the request that started the session.

DELETE <data.self> HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Bearer <Token>
curl "<data.self>" -X "DELETE" -H "Authorization: Bearer <token>"

results matching ""

    No results matching ""