Skip to content
Last updated

The Payments API lets you submit outgoing credit transfers, track their status, and — for banks/customers configured with pre-approved payments — route them through a signing basket before they reach the bank.

Concepts

  • A payment request creates one bulk payment (P1B), which contains one or more payment lines (P1P). A single request can submit several payment lines at once.
  • Always resolve the real outcome at the P1P (line) level, not just P1B. A bulk payment can show a partial status (PART) while its individual lines have different outcomes from each other.
  • Whether a payment requires manual sign-off depends on the account's approval model:
    • Non pre-approved (RGB off): the payment is sent straight to the bank with no signing step, and then the customer needs to do a manual approval withing the online bank.
    • Pre-approved (RGB on): the payment stays at RCVD until it's approved through the signing basket flow.
    • Which model applies depends on the bank and how the customer's integration was ordered — RGB configuration is not identical across banks (see Troubleshooting).
    • RGB ON is the recommended setup for the best user flow, and the signing basket is the recommended way to approve payments within that setup.

Common headers

HeaderValue
AuthorizationBearer {access_token}
Channel-TypeopenBanking
Subscription-Id{subscriptionId}
Resource-Group-Name{resourceGroupId}
TPP-Redirect-URIYour configured bank signing/redirect URL
Acceptapplication/json
Content-Typeapplication/json (when the request has a body)
api-version1.0
Idempotency-Key{UUID} — recommended on every POST, to safely retry without creating duplicate payments

Submit bulk payment

MethodEndpointBody
POST{BankingBaseUrl}/api/bulk-payments/credit-transferJSON, structure below
{
  "debtorAccount": {
    "iban": "...",
    "bban": "...",
    "currency": "..."
  },
  "debtorName": "...",
  "debtorAddress": {
    "streetName": "...",
    "postCode": "...",
    "townName": "...",
    "country": "..."
  },
  "batchBooking": false,
  "requestedExecutionDate": "...",
  "paymentLines": [
    {
      "endToEndIdentification": "...",
      "instructedAmount": { "currency": "...", "amount": "..." },
      "creditorAccount": { "iban": "...", "bban": "..." },
      "creditorName": "...",
      "creditorAddress": { "streetName": "...", "postCode": "...", "townName": "...", "country": "..." },
      "remittanceInformationUnstructured": "...",
      "remittanceInformationStructured": { "reference": "...", "referenceType": "SCOR|CINV" },
      "purposeCode": "...",
      "purposeProprietary": "...",
      "regulatoryReportingCode": "...",
      "regulatoryReportingInformation": "...",
      "bundleReference": "..."
    }
  ]
}

Fields with empty values are normally omitted from the request. paymentLines can contain multiple payment lines in a single call.

Include as much remittance/reference information as you have — for cross-border payments, IBAN, SWIFT/BIC, and country codes are required. The payment goes through initial validation (illegal characters, etc.) before being sent onward, so malformed requests fail fast rather than reaching the bank.

Structured reference (remittanceInformationStructured)

referenceType identifies which kind of structured reference is used — you don't need to (and shouldn't) pick the local reference format explicitly. The local form is set implicitly based on the account/country data in the API call itself.

Examples of local equivalents behind the same referenceType:

CountryLocal reference namereferenceType
NorwayKIDSCOR
SwedenOCRSCOR
DenmarkFIKSCOR (mapped to FIK locally)
General ISO/creditor reference—SCOR
Invoice-based reference—CINV

In other words: KID in Norway and OCR in Sweden are the same underlying concept (a structured payment reference), just under different local names — the API represents them with the same referenceType value, and the correct local variant is applied automatically based on the payment's country/account context.

Domestic versus non-domestic payments

There is no separate domestic / international flag. Domestic and non-domestic payments are sent to the same endpoint using the same JSON structure — the API distinguishes them based on the account, currency, country, and payment-agent data you provide.

In simplified terms:

  • Domestic: debtor and creditor are normally in the same country, the same local currency is used, and BBAN or IBAN can be sent without a foreign payment agent.
  • Non-domestic: the creditor is in another country, or the payment uses another currency. In this case, send the creditor's IBAN and — where available — creditorAgent (SWIFT/BIC) and creditorAgentCountryCode.

Example: domestic payment

A Swedish payment in SEK to a Swedish account. creditorAgent can be omitted if no SWIFT code is registered for the recipient's bank.

{
  "debtorAccount": {
    "iban": "SE3550000000054910000003",
    "bban": "54910000003",
    "currency": "SEK"
  },
  "debtorName": "Aritma AB",
  "debtorAddress": {
    "streetName": "Example Street 1",
    "postCode": "111 22",
    "townName": "Stockholm",
    "country": "SE"
  },
  "batchBooking": false,
  "requestedExecutionDate": "2026-09-25",
  "paymentLines": [
    {
      "endToEndIdentification": "V00001234",
      "instructedAmount": {
        "currency": "SEK",
        "amount": "12500.00"
      },
      "creditorAccount": {
        "iban": "SE4550000000054910000019",
        "bban": "54910000019"
      },
      "creditorName": "Supplier Sweden AB",
      "creditorAddress": {
        "streetName": "Supplier Road 2",
        "postCode": "411 10",
        "townName": "Gothenburg",
        "country": "SE"
      },
      "remittanceInformationUnstructured": "Invoice 1234",
      "remittanceInformationStructured": {
        "reference": "1234567890",
        "referenceType": "SCOR"
      },
      "creditorAgentCountryCode": "SE",
      "bundleReference": "{guid}"
    }
  ]
}

Example: non-domestic payment

A payment from Sweden to a Norwegian account in NOK. The recipient's IBAN and SWIFT/BIC are used. creditorAgent is only populated when the recipient bank account has a SWIFT value on record.

{
  "debtorAccount": {
    "iban": "SE3550000000054910000003",
    "bban": "54910000003",
    "currency": "SEK"
  },
  "debtorName": "Aritma AB",
  "debtorAddress": {
    "streetName": "Example Street 1",
    "postCode": "111 22",
    "townName": "Stockholm",
    "country": "SE"
  },
  "batchBooking": false,
  "requestedExecutionDate": "2026-09-25",
  "paymentLines": [
    {
      "endToEndIdentification": "V00001235",
      "instructedAmount": {
        "currency": "NOK",
        "amount": "12500.00"
      },
      "creditorAccount": {
        "iban": "NO9386011117947"
      },
      "creditorName": "Supplier Norway AS",
      "creditorAddress": {
        "streetName": "Supplier Road 2",
        "postCode": "0150",
        "townName": "Oslo",
        "country": "NO"
      },
      "creditorAgent": "DNBANOKK",
      "creditorAgentCountryCode": "NO",
      "remittanceInformationUnstructured": "Invoice 1234",
      "bundleReference": "{guid}"
    }
  ]
}

How the classification actually works

There's no explicit domestic = true/false field — the distinction is implicit in the fields you send, combined with the API's own rules:

FieldWhere it comes from
debtorAccount.currencyThe debtor's bank account
instructedAmount.currencyThe payment currency
creditorAccountPopulated with IBAN and/or BBAN, depending on which values are available
creditorAddress.countryThe creditor's country code
creditorAgentSet to SWIFT/BIC when a value is available for the creditor's bank
creditorAgentCountryCodeAlways set from the creditor's country code

Retrieve and cancel a payment

MethodEndpointBody
GET{BankingBaseUrl}/api/bulk-payments/credit-transfer/{paymentId}No body
DELETE{BankingBaseUrl}/api/bulk-payments/credit-transfer/{paymentId}No body

The same endpoint pattern is used to check status for both the complete bulk transfer (P1B) and individual payment lines (P1P) — as noted above, resolve the real per-line outcome rather than relying on the P1B-level status alone.

Status progression

Full ISO 20022 status flow:

RCVD → ACTC (Accepted Technical Validation) → ACCP (Accepted Customer Profile) → ACSP (Accepted Settlement In Process) → ACSC (Accepted Settlement Completed)

with RJCT (rejected) or PART (partially accepted) as alternative branches. On rejection, check the status message / reason code returned with the payment.

Prefer webhooks over polling to track status changes (see below).

Signing baskets

Used when an account has pre-approved payments (RGB) enabled — the payment stays at RCVD until the basket is created and authorized.

MethodEndpointBody
POST{BankingBaseUrl}/api/signing-baskets{ "paymentIds": ["{paymentId1}", "{paymentId2}"] }
POST{BankingBaseUrl}/api/signing-baskets/{basketId}/authorizationsEmpty body; the signing redirect is returned via the TPP-Redirect-URI header

Multiple payment IDs can be included in one basket to approve several payments at once. After authorization, the response includes a redirect URL where the authorized user completes BankID verification and approves the basket; they're then redirected back to the configured TPP-Redirect-URI.

Both P1B (bulk payment) and P1P (individual payment line) IDs can be added to a signing basket. We recommend adding P1P IDs rather than P1B IDs, since this gives a clean 1:1 relationship between what's approved and what's actually sent — a P1B can contain multiple lines with different outcomes, which makes basket-level approval harder to reason about.

A payment is only sent on to the bank once it has been fully approved — 1 out of 1, or 2 out of 2, signatures, depending on how the account's approval requirement (numberOfApprovers) is configured. Only after that full approval is reached does the payment actually leave Aritma for the bank.

Tracking status via webhooks

Rather than polling, subscribe to payment-related events on the Events API:

FunctionEvent(s)Callback path
Payment/transfer statusbanking.payment.status.updated, banking.bulk_payment.status.updated/api/status_update/{tenantId}/{companyId}

After subscribing, the subscription must be validated via the callback included in the subscription flow.

Troubleshooting / known gotchas

SymptomCauseWhat to do
Payment stuck at RCVDAccount has pre-approved payments (RGB) enabledComplete the signing basket flow
Bulk payment status looks wrong or incompleteYou're reading only the P1B-level statusAlways resolve the real outcome at the P1P (payment line) level
Unsure whether an account needs signingRGB configuration differs by bank/country — e.g. most Norwegian banks use an Aritma toggle, while DNB and banks in Sweden/Denmark require RGB to be ordered as part of the bank agreement, and Handelsbanken doesn't support it until Q4 2026Check with the customer's bank onboarding setup, or contact Aritma support if unsure

For anything not covered above — production incidents, account-specific payment failures, or billing — escalate to support@aritma.com