Payment Initiation (PIS)

The Payment Initiation Service (PIS) of Klarna's XS2A v2 (Berlin Group openFinance) PSD2 API — supported payment products, the single-payment initiation flow, request structure, status model and what is not supported.
5 min read
The Payment Initiation Service (PIS) lets a licensed PISP initiate a credit transfer from the customer's payment account, once the customer has approved it through Strong Customer Authentication. Access requires the PSP_PI role in your certificate (see Authentication).

What we support

The PIS exposes single payment initiation and the operations to track an initiated payment:
OperationEndpointNotes
Initiate paymentPOST /v2/payments/{payment-product}Creates a single payment and returns a paymentId.
Payment statusGET /v2/{payment-service}/{payment-product}/{paymentId}/statusReturns the current transactionStatus.
Retrieve paymentGET /v2/{payment-service}/{payment-product}/{paymentId}Returns the submitted payment details and status.
For the status and retrieve operations the {payment-service} segment is payments.

Not supported

The following parts of the Berlin Group standard are not offered by this API:
  • pain.001 / XML encoding — only JSON request bodies are accepted. Requests with a pain.001-* product or XML payload are rejected.
  • Bulk payments (bulk-payments) and periodic payments / standing orders (periodic-payments) — initiation is not available; only single payments can be created.
  • Payment cancellation — there is no DELETE operation on a payment resource.
  • Other Berlin Group payment products — target-2-payments and cross-border-credit-transfers are not offered; a request for them returns 404 PRODUCT_UNKNOWN (400 SERVICE_INVALID on the authorization endpoints). Use one of the products in Payment products.
See Deviations from Berlin Group v2 for the consolidated list of differences from the standard.

Payment products

The {payment-product} path segment selects the scheme. The supported JSON products are:
{payment-product}SchemeCurrency
sepa-credit-transfersSEPA Credit Transfer (SCT)EUR
instant-sepa-credit-transfersSEPA Instant Credit Transfer (SCT Inst)EUR
se-domestic-credit-transfersSwedish domestic credit transferSEK
sepa-credit-transfers is the default and most widely used product. se-domestic-credit-transfers identifies accounts with bban (20 digits) instead of iban, and the customer must have an SE/SEK account. Any other {payment-product} returns 404 PRODUCT_UNKNOWN on initiation, status and retrieve, and 400 SERVICE_INVALID on the authorization endpoints.

How a payment is initiated

  1. 1.
    Initiate — POST /v2/payments/{payment-product} with the payment body. The response returns a paymentId, an initial transactionStatus of RCVD, and a _links object with self, status and startAuthorisation.
  2. 2.
    Authorize — POST to the startAuthorisation link with the PSU-ID (the customer's email) and PSU-IP-Address headers, then poll the scaStatus link while the customer approves in the Klarna app. See SCA for the full flow. The payment is only forwarded for execution once SCA succeeds.
  3. 3.
    Track — poll the status endpoint (or use the retrieve endpoint) until the payment reaches a final transactionStatus (ACTC or RJCT).

Request structure

A single payment body follows the Berlin Group openFinance 2.x credit-transfer model. Besides the body, every request needs X-Request-ID (a UUID) and, on initiation, PSU-IP-Address. The fields are:
FieldRequiredDescription
debtorAccountNoThe customer's account the funds are debited from, as an account reference (iban, or bban for se-domestic-credit-transfers). Optional: if omitted, it is resolved after authorization, but only when the customer has exactly one eligible account. Send debtorAccount whenever the customer may hold more than one account.
creditorAccountYesThe beneficiary account the funds are credited to, as an account reference (for example, iban).
creditorYesThe beneficiary party; creditor.name is required.
instructedAmountYesThe amount to transfer, as { currency, amount }.
remittanceInformationUnstructuredNoFree-text reference shown to the beneficiary (array with exactly one entry when present).
paymentIdentification.endToEndIdNoYour own reference, echoed end-to-end.
creditorAgentNoObject { "financialInstitutionId": { "bicfi": "…" } }. Accepted, but currently ignored.

Example — initiate a SEPA credit transfer

JSON
1 2 3 4 5 6 7
{ "debtorAccount": { "iban": "DE23100000001234567890" }, "instructedAmount": { "currency": "EUR", "amount": "123.50" }, "creditorAccount": { "iban": "DE89370400440532013000" }, "creditor": { "name": "Merchant GmbH" }, "remittanceInformationUnstructured": ["Invoice 12345"] }
(The debtor IBAN is the John Doe account from the sandbox test data; IBANs must carry valid check digits, otherwise the request is rejected with 400 FORMAT_ERROR. In production use the customer's and beneficiary's real account references.)

Example — initiation response

JSON
1 2 3 4 5 6 7 8 9
{ "transactionStatus": "RCVD", "paymentId": "3f6b7c52-9d1e-4a58-8b0f-6c2e4d9a1b73", "_links": { "self": { "href": "/v2/payments/sepa-credit-transfers/3f6b7c52-9d1e-4a58-8b0f-6c2e4d9a1b73" }, "status": { "href": "/v2/payments/sepa-credit-transfers/3f6b7c52-9d1e-4a58-8b0f-6c2e4d9a1b73/status" }, "startAuthorisation": { "href": "/v2/payments/sepa-credit-transfers/3f6b7c52-9d1e-4a58-8b0f-6c2e4d9a1b73/authorisations" } } }
POST to the startAuthorisation link to have the customer authorize the payment — see SCA. The response also lists the available scaMethods.

Payment status

The status endpoint returns a transactionStatus from the ISO 20022 / Berlin Group code list. A payment goes RCVD → PDNG → ACTC or RJCT; no other status is set today:
transactionStatusMeaning
RCVDReceived — payment created, awaiting authorization.
PDNGPending — the authorization has started and the customer has not answered yet.
ACTCAccepted technical validation — the customer approved the payment. This is the final success status.
RJCTRejected — the customer rejected the payment, the SCA window elapsed, or the debtor account could not be used. This status carries no reason fields.
The other Berlin Group statuses (ACCP, ACSP, ACSC, ACWC, CANC) are never returned, so do not wait for ACSC.

Verification of Payee (VOP) — planned

Coming soon
The initiation request accepts the optional Client-VOP-Requested header, but no payee verification is performed yet and the RVCM status is never returned.
Once available, you set the Client-VOP-Requested header on the initiation request; when a payee verification was performed and the names did not match, the response will carry a RVCM status together with the match outcome (creditorNameMatch, matchedCreditorName) so you can confirm with the customer before they authorize.

Errors

Errors are returned as {"apiClientMessages":[{"category","code","text"}]}. Common cases include 400 FORMAT_ERROR for a malformed body, 404 PRODUCT_UNKNOWN for an unsupported product, 401 for certificate/role problems, and 409 for resource state conflicts. See Authentication for certificate and role errors.
Support
Partner support•Service Status
Cookies|Terms & Conditions|Copyright Klarna AB 2026
Jump to section...