Upcoming changes in Swedish payment infrastructure

Sweden is facing one of the biggest changes in the history of its payment infrastructure, regarding the updated payment type Credit Transfer. Please refer to the information in the below link.

PLEASE NOTE - It is high time to migrate to Version 2, as transfers to other banks will cease to function in Version 1 on June 18!

Information regarding SEK Credit transfer

For frequently asked questions and answers about SEK Credit transfer please follow below link

FAQ: FAQ about SEK Credit Transfer

SEK Credit Transfer FAQs

Which APIs are affected by this migration?

  • Legacy: Payments API v1.3.2 (multi-country)
  • New:
    • Payments SE Private API v2.0.0
    • Payments SE Corporate API v2.0.0

The Accounts API (v2.1.30) and Subscriptions API (v1.0.22) are not part of this migration.

Payments SE Corporate API v2.0.0

Where do I start?

  1. Review the new OpenAPI specifications on the Developer Portal.
  2. Subscribe your app to the relevant product (payments-se-private and/or payments-se-corporate) via the Subscriptions API.
  3. Develop and test in the Sandbox environment.
  4. Use the Go Live process on the Developer Portal when ready for production.

What's the recommended migration path?

  1. Subscribe your existing app to the new products via the Subscriptions API:
    • payments-se-private (PIS scope)
    • payments-se-corporate (PIS scope)
  2. Update base URL from /openbanking/psd2/v1 to /openbanking/psd2/se/v2.
  3. Split your code paths by customer segment (private vs corporate).
  4. Map your product calls to the new endpoint structure (/single/{product} vs /signing-basket).
  5. Adapt payloads to the product-specific schemas — particularly creditorAccount.accountType, chargeBearer, paymentTypeInformation and remittance text patterns.
  6. Move SEK Credit Transfer flows into baskets — single sek-credit-transfer is not supported in v2.
  7. Re-test SCA flows — both DECOUPLED and REDIRECT are still supported, but URLs and link structures are versioned.
  8. Regression-test cancellation flows for future-dated payments.
  9. Verify in Sandbox, then complete Go Live on the Developer Portal.

Which payment products are supported in the new Swedish APIs?

ProductCode (URL identifier)PrivateCorporate
Handelsbanken Domestic Credit Transfer (SHBCT)handelsbanken-domestic-credit-transfer
SEK Credit Transfer (SEKCT) — former bank transfers and giro paymentssek-credit-transfer✓ (basket only)✓ (basket only)
SEPA Credit Transfer (SEPACT)sepa-credit-transfer
Cross Currency Credit Transfer (CCCT)cross-currency-credit-transfer

What are the new base URLs?

EnvironmentURL
Sandboxhttps://sandbox.handelsbanken.com/openbanking/psd2/se/v2
Livehttps://api.handelsbanken.com/openbanking/psd2/se/v2

Note the new /se/v2 path segment. The legacy API used /openbanking/psd2/v1.

What is the URL structure for the new endpoints?

The new APIs split clearly between customer segment and payment type:

  • /payments/private/single/{paymentProduct} — single private payments
  • /payments/private/signing-basket — private basket payments
  • /payments/corporate/single/{paymentProduct} — single corporate payments
  • /payments/corporate/signing-basket — corporate basket payments
  • /payments/private/accounts/shorttermconsents — short-term consent (Private only)

In v1.3.2, all payments used a single /payments/{paymentProduct} endpoint regardless of customer type.

What is the mapping from legacy product names to the new ones?

Legacy v1.3.2 productNew SE v2.0.0 product
swedish-domestic-giro-paymentsek-credit-transfer (SEKCT, basket only)
swedish-domestic-credit-transfersek-credit-transfer (SEKCT, basket only)
sepa-credit-transfersepa-credit-transfer (Corporate only)
cross-currency-credit-transfercross-currency-credit-transfer
(new in v2)handelsbanken-domestic-credit-transfer (SHBCT)

Important: In v2, SEKCT can only be executed inside a signing basket — single SEKCT payments are no longer supported. SHBCT, SEPACT and CCCT can only be executed as single payments.

How have signing baskets changed?

AspectLegacy v1.3.2New v2.0.0
EligibilitySweden, individuals, swedish-domestic-giro-payment onlyBoth Private and Corporate, sek-credit-transfer
Max payments per basket3030 (Private) / 100 (Corporate)
Min payments per basket11

What are the main structural changes in the payment payload?

  • Dedicated product-specific schemas: each product (SHBCT, SEKCT, SEPACT, CCCT) now has its own validated request schema with the right field set, account types and patterns. The legacy API used one generic PaymentPayload for all products.
  • creditorAccount.accountType is now strictly enumerated per product:
    • SHBCTBBAN only (8–9 digit Swedish SHB account number)
    • SEKCTBBAN, IBAN (Swedish IBANs only), PG, BG
    • SEPACT, CCCT Nordic, CCCT EU-paymentIBAN only
    • CCCT Normal / ExpressIBAN or BBAN
  • chargeBearer values are now tied to product:
    • SHAR — SEPACT, CCCT Nordic, CCCT EU-payment
    • CHAR, CRED, DEBT — CCCT Normal and Express
  • PaymentTypeInformation uses ISO 20022 codes (SEPA, URGP, NURG) and category-purpose codes (SUPP, NOPA, EUSE).
  • Stricter character patterns apply to creditor.name, remittanceInformation.text and similar fields — particularly for SHBCT, where remittance text is limited to 14 characters.

Can I use the V2 to Cancel or ask for Status on payments created in V1?

No, You must use the old endpoint (V1) to cancel and ask for status on payments.

Where do I get support?

Is SEK Credit Transfer available only as a basket payment?

Yes. There is no /payments/corporate/single/sek-credit-transfer endpoint. SEK credit transfers can be initiated only via POST /payments/corporate/signing-basket.

A basket containing a single payment is the correct and supported approach: the request requires the sekCreditTransfers array with minItems 1 (maxItems 100), so an array of length 1 is the intended way to initiate an individual cross-bank SEK transfer.

How do we check status after executing a basket?

There is no basket-level status endpoint. Use the existing per-payment endpoint GET /payments/corporate/{paymentProduct}/{paymentId}/status with paymentProduct = sek-credit-transfer and the paymentId returned per payment in the initiation response.

The initiation response returns a payments array, each element carrying its own paymentId plus your tppPaymentReference; use that mapping to poll each payment.

On PARTIAL_FAILURE, how do we identify which payments failed?

The basket execute response returns only a basket-leveltransactionStatus (SUCCEEDED / FAILED / PARTIAL_FAILURE); it does not break results down per payment.

To identify individual outcomes, call the per-payment status endpoint for each paymentId. At payment level, transactionStatus uses ISO 20022 codes (ACTC, ACCP, ACSC, ACCC, PATC, CANC, RJCT). A failed payment shows RJCT, with reasonCode and reason giving the specific cause.

Recommended PARTIAL_FAILURE pattern

  1. Execute basket. If transactionStatus = PARTIAL_FAILURE,
  2. Iterate the payments array from the initiation response,
  3. Call GET .../sek-credit-transfer/{paymentId}/status for each, treating RJCT + reasonCode/reason as the failure detail.