BBankConnectorDeveloper Docs

Validation Reference

Audience: 🔌 Integration Client

When a payment is rejected 422, the reasons come back as a list of issues in error.details.issues. Each issue looks like:

{
  "code": "PAYMENT_TYPE_SEPA_EUR_ONLY",
  "level": "payment-type",
  "severity": "error",
  "message": "SEPA payments must be in EUR.",
  "path": "payments[0].transactions[0].currency"
}

Validation runs in four levels, and stops at the first structural failure:

  1. Structural (schema) — if the JSON doesn't match the canonical schema, you get only GENERIC_SCHEMA issues and nothing else runs. This is the 400/422 line: malformed body → 400; schema-invalid canonical payment → 422.
  2. Generic rules — currency, amount, dates, references (below).
  3. Bank rules — per-bank requirements (BIC required, national account checksums, etc.).
  4. Payment-type rules — per scheme (SEPA EUR-only, KID checksum, etc.).

Generic rules (apply to every payment)

CodeSeverityMeaning
GENERIC_SCHEMAerrorJSON failed the canonical schema
GENERIC_AMOUNT_POSITIVEerroramount ≤ 0 (so "0.00" fails here)
GENERIC_AMOUNT_PRECISIONerrormore decimals than the currency allows (JPY/ISK 0, KWD 3)
GENERIC_CURRENCY_CODE_INVALIDerrornot an active ISO 4217 code
GENERIC_COUNTRY_CODE_INVALIDerrordebtor country not ISO 3166
GENERIC_PAYMENT_ID_DUPLICATEerrorpaymentId reused across payments
GENERIC_END_TO_END_ID_DUPLICATEerrorendToEndId reused in the batch
GENERIC_CREDITOR_REFERENCE_RF_INVALIDerrorRF reference fails ISO 11649 mod-97
GENERIC_CREDITOR_REFERENCE_KID_INVALIDerrorKID fails MOD10/MOD11
GENERIC_BIC_IBAN_COUNTRY_MISMATCHwarningBIC country ≠ IBAN country
GENERIC_EXECUTION_DATE_PASTwarningdate is in the past
GENERIC_EXECUTION_DATE_FAR_FUTUREwarningmore than a year ahead
GENERIC_EXECUTION_DATE_NON_BANKINGwarningweekend/holiday; suggests next banking day
GENERIC_MIXED_CURRENCY_BATCHwarningmore than one currency in one payment

The duplicate-id errors matter: banks de-duplicate on paymentId and endToEndId and may silently drop repeats, so BankConnector blocks them up front. Keep them unique within a batch.

Profile warnings (character set / truncation)

CodeSeverityMeaning
PROFILE_NAME_TRUNCATEDwarninga name was shortened to the bank's limit
PROFILE_REMITTANCE_TRUNCATEDwarningremittance text was shortened
PROFILE_CHARSET_TRANSLITERATEDwarningcharacters were transliterated to the SEPA set
PROFILE_NAME_UNREPRESENTABLEerrora required name transliterates to empty (e.g. CJK-only)

Remember the order: transliterate, then truncate. Transliteration can expand text (ä→ae, ß→ss), so a name that looks short can still truncate.

Bank-rule examples

Different banks require different things. Common ones:

Query GET /banks/<bank>/payment-types and the bank's setup info to see what a given bank expects before you build against it.

Payment-type rules (by scheme)

TypeKey requirements
sepacreditor IBAN required; EUR only
sepa-instantas SEPA + amount ≤ €100,000
internationalcreditor account and creditor BIC required
fik (DK)valid FIK reference (kortart 71 + Luhn)
kid (NO)2–25 digits, MOD10/MOD11
bankgiro / plusgiro (SE)Luhn-checked, digit-length bounded
bacs / chaps / faster-payment (UK)6-digit sort code + 8-digit account; GBP only; Faster ≤ £1,000,000
ach / wire (US)9-digit routing + ABA checksum; USD only
ch-domestic / ch-qr (CH)creditor IBAN + CHF/EUR; QR adds a 27-digit reference check
eft (CA)routing + account; CAD only

If you omit paymentType, the engine attempts to infer it and returns autoSelected in the response. If it can't (PAYMENT_TYPE_AUTO_UNRESOLVED) or the type isn't offered by that bank (PAYMENT_TYPE_NOT_OFFERED), you get an error — set it explicitly when in doubt.

Handling issues in your client

if (res.status === 422) {
  const { error } = await res.json();
  const blocking = (error.details?.issues ?? []).filter((i: any) => i.severity !== "warning");
  const warnings = (error.details?.issues ?? []).filter((i: any) => i.severity === "warning");
  // Surface `blocking` to whoever owns the payment data; log `warnings`.
}

Treat errors as "fix and resubmit," and warnings as "worth logging, but it went through." Don't discard warnings — a truncation or non-banking-day warning is often the first sign of a data-quality issue upstream.