PaySaxas XS2A
PSD2 access to account — Berlin Group NextGenPSD2 v1.3.15

← All documentation

Payment initiation

Products

Product Path segment
SEPA credit transfer sepa-credit-transfers
SEPA instant credit transfer instant-sepa-credit-transfers

EUR only. Bulk payments, periodic payments and signing baskets are outside the interface because they are outside the customer’s own portal — not because they are unbuilt.

Initiating

curl -X POST https://xs2a.paysaxas.com/v1/payments/sepa-credit-transfers \
  --cert tpp-qwac.pem --key tpp-qwac.key \
  -H "Content-Type: application/json" \
  -H "X-Request-ID: 3c2f0e9a-2b62-4b0e-9b2d-2f0a8a2b1c33" \
  -H "TPP-Redirect-URI: https://your-app.example/psd2/return" \
  -H "PSU-IP-Address: 203.0.113.9" \
  -d '{
        "debtorAccount":    {"iban": "FI2112345600000785"},
        "instructedAmount": {"currency": "EUR", "amount": "125.50"},
        "creditorAccount":  {"iban": "FI4550009420888888"},
        "creditorName":     "Beta Oy",
        "remittanceInformationUnstructured": "Invoice 2026-114"
      }'
{
  "transactionStatus": "RCVD",
  "paymentId": "8f14...",
  "_links": {
    "scaRedirect": { "href": "https://platform.paysaxas.com/customer/xs2a/authorise/AUTH-...?state=..." },
    "status":      { "href": "/v1/payments/sepa-credit-transfers/8f14.../status" }
  }
}

Then send the customer to scaRedirect. Nothing moves until they authorise. Store the state on that link against the payment and check it when they come back — see what state is and how long it lasts.

Field notes

Idempotency

X-Request-ID is the idempotency key. Replaying the same value returns the first payment rather than initiating a second — safe to retry a timeout. Use a fresh UUID for a genuinely new payment.

The full contract, so you can reason about your retry logic:

Question Answer
Same key, same body Returns the first payment. Retry a timeout freely
Same key, different body 409 REQUEST_ID_REUSED. We do not silently return the first payment — that would let a client bug believe a second, different instruction had been executed
How long is a key remembered? 48 hours for body-conflict detection. The payment itself keeps its key permanently, so a much later replay still resolves to the original payment rather than creating a second one
Scope Global. One key binds to exactly one payment across every product and every provider. A key used on sepa-credit-transfers cannot be reused on instant-sepa-credit-transfers — it resolves to the first payment. Generate a fresh UUID v4 per instruction and this never arises
Other endpoints X-Request-ID is required everywhere and is echoed back on every response, but it only carries idempotency on writes. On GETs it is a correlation id — quote it to support and we can find your exact request in the traceability log

The one case that matters: do not reuse a key across retries of a request you changed. If a retry carries a different amount, payee or debtor, it is a new instruction and needs a new key. Reusing the key is refused rather than guessed at.

Status values

Code Meaning
RCVD Received, not yet authorised
ACTC Accepted, technical validation passed
PDNG Pending — we are waiting on something before the payment can move, usually the customer confirming the payee. Poll it. It resolves to ACSP or RJCT, or to CANC if the customer does not come back within 24 hours. You may still cancel it yourself
ACSP Accepted, settlement in process
ACSC Accepted, settlement completed
RJCT Rejected
CANC Cancelled

ACSP covers more than one internal state. A payment under compliance review reports ACSP, exactly as one moving normally through the rails does. This is deliberate and not negotiable: a distinguishable status would disclose that a specific payment attracted scrutiny. Do not build logic that infers anything beyond “in progress” from ACSP.

Cancellation

DELETE /v1/payments/{product}/{paymentId}

Possible only while the payment could still be cancelled in the customer’s own portal. Past that point the funds have moved and you get CANCELLATION_INVALID (405).

No customer authorisation is required, and there is no cancellation authorisation sub-resource. Berlin Group allows an ASPSP to demand a second ceremony for cancellation; we do not. The DELETE takes effect immediately and returns the resulting transactionStatus.

The reasoning, so you can rely on it rather than infer it: cancelling only ever stops money moving. SCA exists to protect the customer from a payment they did not intend, and a cancellation cannot create one. Demanding a fresh ceremony would mean a customer who wants to stop a payment must first be available to authenticate — worst exactly when it matters.

Two limits keep that safe:

If you receive 403, the cancellation was refused because your registration or certificate role does not permit it — not because the payment was uncancellable.

Why a payment can be refused

Initiation failures return PAYMENT_FAILED with one sentence, always the same. Insufficient funds, an unknown debtor account, a limit, a compliance hold — all identical from outside.

This is not unhelpfulness. A refusal that varied by cause would let anyone with a certificate probe our customers’ balances, limits and standing. The customer can see the real reason in their own portal, where they are authenticated as themselves.

Malformed requests are different and do say what is wrong: FORMAT_ERROR for a bad IBAN or amount, PRODUCT_INVALID for a non-EUR currency.