Validation reference
Audience: 🔌 Integration Client
When a payment is rejected, the reasons come back as a list of issues in error.details.issues, under 422 and under 400 alike, so one parse handles both. 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"
}
severityiserror(blocks) orwarning(informational: the payment still proceeds). It's omitted when it would beerror(the default); checkvalid/ the absence oferror-severity issues to know if a payment can proceed.leveltells you which stage raised it:generic,bank, orpayment-type.
Validation runs in four levels, and stops at the first structural failure:
- Structural (schema): if the JSON doesn't match the canonical schema, you get only
GENERIC_SCHEMA_*issues and nothing else runs. OnBankConnector-Version: 2026-08-25this returns422, the same as a payment that fails a semantic rule (levels 2–4 below). Both mean "we read your request and cannot process this payment". A body that is not JSON at all is a400. ⚠️ On2026-06-01(and with no version header) a schema failure is a400instead; see the changelog. - Generic rules: currency, amount, dates, references (below).
- Bank rules: per-bank requirements (BIC required, national account checksums, etc.).
- Payment-type rules: per scheme (SEPA EUR-only, KID checksum, etc.).
Generic rules (apply to every payment)
| Code | Severity | Meaning |
|---|---|---|
GENERIC_SCHEMA_* | error | JSON failed the canonical schema (per-field codes, e.g. GENERIC_SCHEMA_AMOUNT_REQUIRED) |
GENERIC_AMOUNT_POSITIVE | error | amount ≤ 0 (so "0.00" fails here) |
GENERIC_AMOUNT_PRECISION | error | a non-zero sub-unit the currency can't represent (e.g. "1000.50" JPY). Trailing zeros ("1000.00") are fine; the engine converts precision for you |
GENERIC_CURRENCY_CODE_INVALID | error | not an active ISO 4217 code |
GENERIC_COUNTRY_CODE_INVALID | error | a country on any party (debtor, creditor, their agents, ultimate parties, regulatory reporting) is not an assigned ISO 3166-1 alpha-2 code. UK is accepted and sent as GB |
GENERIC_PAYMENT_ID_DUPLICATE | error | paymentId reused across payments |
GENERIC_END_TO_END_ID_DUPLICATE | error | endToEndId reused in the batch |
GENERIC_INSTRUCTION_ID_DUPLICATE | error | instructionId reused in the batch. InstrId is a point-to-point de-duplication reference, so a repeat can silently drop a real payment |
GENERIC_CREDITOR_REFERENCE_RF_INVALID | error | RF reference fails ISO 11649 mod-97 |
GENERIC_CREDITOR_REFERENCE_KID_INVALID | error | KID fails MOD10/MOD11 |
GENERIC_CREDITOR_REFERENCE_OCR_INVALID | error | a reference typed ocr is not a Swedish OCR reference: 2–25 digits with a valid modulus-10 check digit |
GENERIC_CREDITOR_REFERENCE_OGM_INVALID | error | Belgian structured communication (OGM/VCS) is not 12 digits or fails its mod-97 check |
GENERIC_CREDITOR_REFERENCE_VIITE_INVALID | error | a reference typed viite is not a Finnish creditor reference: 4–20 digits with a 7-3-1 check digit |
GENERIC_CREDITOR_REFERENCE_KENMERK_INVALID | error | a reference typed kenmerk is not a Dutch payment reference: 7–16 digits, a 16-digit one with a valid modulus-11 check digit first |
GENERIC_FIK_CREDITOR_ACCOUNT_NEEDS_FIK_TYPE | error | the creditor account is a Danish FIK/giro creditor number (scheme FIK, or OCR at a DK/GL/FO bank) on a payment whose type is not fik, only a FIK payment can pay it |
GENERIC_IBAN_FR_BBAN_FORMAT_INVALID | error | a French IBAN whose BBAN is not 5 digits (bank), 5 digits (branch), 11 digits or letters (account), 2 digits (clé RIB) |
GENERIC_IBAN_FR_RIB_KEY_INVALID | error | a French IBAN whose clé RIB does not match its bank code, branch code and account number |
GENERIC_IBAN_NL_BANK_CODE_INVALID | error | a Dutch IBAN without the 4-letter bank code (then 10 digits) in positions 5-18 |
GENERIC_IBAN_NL_BANK_CODE_UNKNOWN | warning | a well-formed Dutch IBAN whose 4-letter bank code is not on the Betaalvereniging BIC list; it is sent as given |
GENERIC_IBAN_DE_BANK_CODE_UNKNOWN | warning | a well-formed German IBAN whose bank code is not a live code in the Bundesbank Bankleitzahlendatei, or is one it lists as deleted; it is sent as given |
GENERIC_IBAN_BE_BBAN_FORMAT_INVALID | error | a Belgian IBAN whose BBAN is not 12 digits |
GENERIC_IBAN_BE_ACCOUNT_KEY_INVALID | error | a Belgian IBAN whose last 2 digits are not the first 10 mod 97 (97 for a remainder of 0) |
GENERIC_BE_ENTERPRISE_NUMBER_INVALID | warning | a Belgian enterprise number (scheme KBO / KBO-BCE) that is not 10 digits with valid check digits; it is sent as given |
GENERIC_PURPOSE_CODE_NOT_PLACEABLE | error | a purposeCode override longer than the ISO Purp/Cd limit (4 chars) with no corridor rule to place it. Use a 4-char ISO code, or supply regulatoryReporting explicitly |
GENERIC_BIC_IBAN_COUNTRY_MISMATCH | warning | BIC country ≠ IBAN country |
GENERIC_CREDITOR_REFERENCE_VIITE_CHECK_FAILED | warning | an untyped or scor all-digit reference to a Finnish account fails the viitenumero 7-3-1 check; it is sent as given |
GENERIC_CREDITOR_REFERENCE_KENMERK_CHECK_FAILED | warning | an untyped or scor 16-digit reference to a Dutch account fails the betalingskenmerk modulus-11 check; it is sent as given |
GENERIC_EXECUTION_DATE_PAST | warning | date is in the past |
GENERIC_EXECUTION_DATE_FAR_FUTURE | warning | more than a year ahead |
GENERIC_EXECUTION_DATE_NON_BANKING | warning | weekend/holiday; suggests next banking day |
GENERIC_EXECUTION_DATE_INTL_TOO_SOON | warning | a cross-border payment to a country whose banking calendar isn't modelled, with little lead time. International settlement usually needs a few business days |
GENERIC_EXECUTION_DATE_AFTER_CUTOFF | warning | the execution date is today and the bank's published cut-off has passed, so the bank will usually value-date it the next banking day. Only for a bank whose cut-off we hold |
GENERIC_EXECUTION_DATE_BACS_LEAD_TIME | warning | a Bacs payment's execution date gives fewer than 2 GB working days of lead time (Bacs' own Translation Guide §4.9), counted from the next GB banking day when today is a weekend |
GENERIC_MIXED_CURRENCY_BATCH | warning | more than one currency in one payment |
The duplicate-id errors matter: banks de-duplicate on paymentId, endToEndId and instructionId and may silently drop repeats, so BankConnector blocks them up front. Keep them unique within a batch.
Cut-off times
A bank stops accepting orders for same-day execution at a deadline it publishes itself, its _cut-off_. Submit a payment dated today after that time and the bank will usually value-date it on the next banking day, so an urgent-rail fee buys a next-day execution. GENERIC_EXECUTION_DATE_AFTER_CUTOFF tells you before you send it, and names the deadline and the current time in the bank's zone:
executionDate 2026-09-22 is today, and Postbank's published cut-off for this payment
(15:30 Europe/Berlin) has passed (it is 17:00 there). The bank will usually value-date
the payment on the next banking day. (Not rejected: send it anyway, or set the next
banking day as the execution date.)
It is a warning and never a rejection: a cut-off is the bank's operational deadline, not a scheme rule, and it varies per rail, channel and agreement. The payment stays your decision.
Which deadline applies depends on the rail your payment rides. A bank may publish separate times for SEPA credit transfers, urgent (TARGET2 / priority: "urgent") payments, foreign payments and even per currency, or a single blanket time for everything. SEPA instant is never flagged: it settles in seconds on any calendar day.
⚠️ Absence of this warning does not mean you are inside a cut-off. The engine only carries times it has read out of a bank's own price list or EBICS sheet; a time is never copied from a sibling institute or guessed. For a bank whose document we do not hold, or whose document names no time, the engine says nothing. Check the deadline with your bank.
Profile warnings (character set / truncation)
| Code | Severity | Meaning |
|---|---|---|
PROFILE_NAME_TRUNCATED | warning | a name was shortened to the bank's limit |
PROFILE_REMITTANCE_TRUNCATED | warning | remittance text was shortened |
PROFILE_CHARSET_TRANSLITERATED | warning | characters were transliterated to the rail's character set (the SEPA set; a German SEPA file keeps umlauts, ß and &) |
PROFILE_NAME_CHARS_DROPPED | warning | a mixed-script name survives transliteration but loses characters that have no Latin rendering ("王伟 Ltd" → "Ltd"). The bank receives a materially different name (Confirmation-of-Payee mismatch risk). Supply the Latin form of the full name |
PROFILE_ID_CHARSET_INVALID | warning | an identifier (messageId, paymentId, instructionId, endToEndId) has characters outside the SEPA set. Unlike names, ids are sent exactly as given, unchanged (to keep pain.002/camt correlation), so the bank may reject the batch or transcode the id and break correlation. Use only A–Z a–z 0–9 and / - ? : ( ) . , ' + and space |
SEPA_ID_SLASH_INVALID | error | on a SEPA rail, an identifier (messageId, paymentId, instructionId, endToEndId) starts or ends with / or contains //, forbidden by the EPC SCT C2PSP Implementation Guidelines, CFONB and the German DK, and the bank rejects the batch. A single internal / stays legal (e.g. a Belgian OGM reference used as an id) |
PROFILE_NAME_UNREPRESENTABLE | error | a required name transliterates to empty (e.g. CJK-only) |
PROFILE_NATIVE_CHARSET_UNSUPPORTED | warning | a bank that keeps text exactly as entered (no transliteration) has its own MIG-documented character set, and a name or remittance line carries characters outside it (e.g. Ω/中 sent to a bank whose MIG states Windows-1252, ISO-8859-1 or the SWIFT set). Nothing is filtered, the bank may substitute a look-alike, reject the file, or degrade the name. Only fires for the handful of banks whose own MIG states a set (one, jpmorgan-us, only on the one rail its MIG names it for); most non-transliterating banks have none on file |
Transliteration runs before truncation, and it can expand text (ä→ae, ß→ss), so a name that looks short can still truncate.
Note the split between the two "lossy name" codes: PROFILE_CHARSET_TRANSLITERATED fires on any change (é→e counts); PROFILE_NAME_CHARS_DROPPED fires only when characters are removed outright, which is the one that actually changes who the bank thinks is being paid.
Bank-rule examples
Banks require different things. Common ones are below. Four remittance warnings carry one code whatever bank or standard raises them, and the message names the bank's rule: BANK_REMITTANCE_DOCUMENTS_AS_TEXT (the documents go out as one line of text), BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT (additionalInfo is left out), BANK_REMITTANCE_TEXT_NOT_SENT (text or documents beside the one remittance sent are left out) and BANK_REMITTANCE_TEXT_JOINED (two or more unstructured lines go as one).
BANK_BIC_REQUIRED: this bank requires the debtor BIC.BANK_BIC_VALUE_INVALID: the debtor BIC doesn't match the expected institution.BANK_DEBTOR_BIC_SUPERSEDED(warning): the debtor BIC belongs to a bank that merged into this one (Spar Nord Bank'sSPNODK22on Nykredit Bank). The payment is sent, and the file names the bank's current BIC.BANK_INITIATING_PARTY_ID_REQUIRED: aninitiatingParty.organisationIdis required.BANK_DEBTOR_COUNTRY_REQUIRED/BANK_DEBTOR_ACCOUNT_CURRENCY_REQUIRED.BANK_BBAN_FORMAT_INVALID/BANK_BBAN_CHECKSUM_INVALID: national account number checks (Norwegian MOD-11, Danish structure, Polish NRB mod-97, Swedish clearing number + account length against the Bankgirot/Bankinfrastruktur register).BANK_BBAN_CHECKSUM_UNCERTAIN(warning): a Swedish account under Swedbank's 5-digit clearing range (8000-8999) fails the modulus-10 check that range's source states applies only "as a rule". It is worth a second look and is not refused outright.BANK_AE_REGULATORY_COUNTRY_UNKNOWN(warning): a UAE payment carries apurposeCode, which the engine reports asRgltryRptg/Dtls/Cd, but states nocreditor.country(and no creditor IBAN to take one from). The siblingCtryholds the beneficiary's residence country, so it is left out rather than guessed, and the UAE high-value rail requires it. Setcreditor.country, or supplyregulatoryReportingyourself.BANK_CNY_CNAPS_MISSING(warning): a Société Générale France CNY payment names a creditor bank in mainland China (agent country or BIC countryCN) but no CNAPS code. The French CFONB guide makes the CNAPS code mandatory there. Setcreditor.agent.clearingto{ "system": "CNAPS", "memberId": "<12 characters>" }andcreditor.agent.name. It is a warning because the bank has accepted BIC-only files.BANK_FOREIGN_CURRENCY_PURPOSE_OF_PAYMENT_REQUIRED(error): an HSBC Indonesia payment in a currency other than IDR lacks part of the purpose of payment the bank requires on it: the beneficiary's country (creditor.country, written asCdtr/CtryOfRes), the beneficiary category and affiliation (regulatoryReporting.details[0].type) or the purpose of transfer (regulatoryReporting.details[0].code). One issue per missing part, at that field.BANK_USTRD_SLASH_POSITION_REJECTED(error): an HSBC Indonesia remittance line has/at character 1, 36 or 71, which the bank's guideline says rejects the file. Move or remove the/.BANK_EG_PURPOSE_OF_PAYMENT_REQUIRED(error): an HSBC Egypt payment states no purpose of payment. The Central Bank of Egypt requires one and HSBC rejects the payment without it, so the engine refuses it first. SetpurposeCode, or send the description asregulatoryReporting.details[0].info[0](bare, because choosing the/BENEFRES/EG//or/ORDERRES/EG//wrapper is the engine's job). Two siblings:BANK_EG_PURPOSE_OF_PAYMENT_TOO_LONG(error: the field leaves 21 characters for the description) andBANK_EG_RELATIONSHIP_EXPECTED(warning: an Egypt-to-Egypt foreign-currency payment owes the payer↔beneficiary relationship too, inremittance).BANK_EG_PURPOSE_OF_PAYMENT_OTHER_NEEDS_DESCRIPTION(error): the purpose of payment is HSBC Egypt's published "Other" and nothing says what the payment is for. "Other" is one entry of the bank's own list and names nothing by itself, so send the meaningful purpose inregulatoryReporting.details[0].info[0]beside it.BANK_CNY_BUSINESS_PURPOSE_REQUIRED(error): a cross-border CNY payment from an HSBC bank carries none of the five phrases HSBC accepts inRgltryRptg/Dtls/Inf:/BUSINESS/GOODS TRADE,/BUSINESS/SERVICE TRADE,/BUSINESS/CHARITY DONATION,/BUSINESS/CURRENT ACC TXN,/BUSINESS/CAPITAL TRF. SetpurposeCodetoGDDS,SCVE,CHAR,INTCorCAPXand the engine writes the phrase, or put the phrase itself inregulatoryReporting.details[0].info. AregulatoryReportingyou send replaces the engine's line, so it must carry the phrase. A CNY payment to a creditor in the bank's own country owes nothing (HSBC China exempts domestic CNY). The siblingBANK_CNY_BUSINESS_PURPOSE_EXPECTED(warning) says the same where the payment names no destination (nocreditor.country, creditor IBAN or creditor agent BIC), so the engine cannot tell whether it crosses a border.BANK_CNY_PAIN_VERSION_ADVISED(warning): a CNY payment to Mainland China, or one that names no destination, is built in a pain.001 version other than the one the bank's own notes ask for. HSBC Germany's "Notes for foreign currency payments" ask for pain.001.001.03, so a connection set to pain.001.001.09 gets this warning. The file is still built. Ask the bank whether it takes the payment in that version, or set the connection's pain.001 version to the one the note names.BANK_BNP_SEPA_CATEGORY_PURPOSE_NOT_ALLOWED(error): a SEPA credit transfer from a BNP Paribas account carriescategoryPurposeSALA,INTC,INTE,FCOLorFCIN. This applies at BNP Paribas in France, Germany, Spain, the Netherlands, Ireland, the UK, Bulgaria and Hungary, and at BNL (Italy), BGL BNP Paribas (Luxembourg) and BNP Paribas Bank Polska: the entities BNP's European SEPA guideline (SEPACT MX v3, 4 May 2026) lists. RuleBNPP_CtgyPurpCd_02does not allowSALAorINTC; BNP takes payroll and intra-company transfers as separate PAYR and INTC orders, which BankConnector does not build for BNP. RuleBNPP_CtgyPurpCd_01does not allowINTE,FCOLorFCIN, citing the 2021 SEPA Rulebook. RemovecategoryPurposeto send the payment as an ordinary SEPA transfer. SEPA Instant payments are not affected.BANK_DANSKE_SEPA_INSTANT_NOT_HONOURED(error): a SEPA Instant payment from a Danske Bank account in Denmark, Finland, Ireland or Sweden carriescategoryPurposeSALA,INTCorURGP, orSDVAin Finland only. Danske's CGI-MP Appendix (v5.3, Appendix J) says it ignores the SEPA Instant marker on salary, group (intra-company) and urgent payments, and on capital payments in Finland, and sends them as ordinary SEPA payments, so the payment would not be instant. This covers an explicitsepa-instantpayment and, in Finland, an urgent euro payment, which is sent as SEPA Instant there. RemovecategoryPurposeto send it as SEPA Instant, or send it assepa(in Finland, withoutpriority: "urgent").BANK_SEPA_REMITTANCE_TEXT_AND_REFERENCE,BANK_SEPA_REMITTANCE_UNSTRUCTURED_REPEATED(errors): a SEPA credit transfer from a German or Belgian bank carries more remittance than the national standard allows. The German standard (DK, DFÜ-Abkommen Anlage 3) and the Belgian one (Febelfin) allow one unstructured line or one creditor reference, never both. Send eitherunstructured(one line of at most 140 characters) orcreditorReference.additionalInfois refused at a German bank (BANK_SEPA_REMITTANCE_ADDITIONAL_INFO_UNSUPPORTED, error) and left out at a Belgian bank, which ignores it (BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT, warning). A German same-day urgent euro payment (priority: "urgent", EUR) is held to one unstructured line too: a second line is refused withBANK_SEPA_REMITTANCE_UNSTRUCTURED_REPEATED. The siblingBANK_REMITTANCE_DOCUMENTS_AS_TEXT(warning) says thatdocumentsgo out as that one line, rather than as structured blocks: each document's type, number and amount when the whole line fits 140 characters, or the document numbers alone (a credit note's marked with a leading "-") once it does not. A line still longer than 140 characters is cut at a word boundary, so an invoice number in your text is left out whole rather than cut short; the warning quotes the line as sent and names what is not sent: the words the cut leaves out, and your whole text when the document numbers fill the line. At a German bank every creditor reference is sent typedSCOR, the only code the German standard admits. SEB Germany is excepted: it takes the SEB group format.BANK_CREDITOR_REFERENCE_TOO_LONG(error): a Danish account transfer or salary at Nordea Danmark (standard, same-day or NemKonto) carries acreditorReferencelonger than 25 characters. Nordea's guides for both pain.001 versions limit the reference on these payments to 25 characters. The reference is counted as the file carries it, so the spaces in a printed RF reference do not count. Shorten the reference, or send it asunstructuredtext. Transfer forms (FIK) have their own reference lengths and are not affected.BANK_NPC_REMITTANCE_UNSTRUCTURED_REPEATED(error): a Danish account transfer or salary in DKK, executed on or after the date its bank applies the move of Danish batch payments to the Nordic Payments Council rules (Nordea Danmark: 24 May 2027), carries more than oneunstructuredline. From that date the payment carries one line of at most 140 characters or one creditor reference. Combine the lines into one. The siblings are warnings:BANK_REMITTANCE_DOCUMENTS_AS_TEXT(thedocumentsgo out as that one line, as at a German bank, and the warning quotes the line as sent and names what is not sent),BANK_REMITTANCE_TEXT_NOT_SENT(a creditor reference goes alone and the text or documents beside it are left out because the bank would not forward them) andBANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT. Transfer forms (FIK), SEPA and international payments are not affected.BANK_NPC_REMITTANCE_UNSTRUCTURED_REPEATED,BANK_NPC_OCR_REFERENCE_INVALID,BANK_NPC_REFERRED_AMOUNTS_MISMATCH(errors): a Swedish account transfer or Bankgiro/PlusGiro payment in SEK, executed on or after the date its bank applies the move to the Nordic Payments Council rules (Swedbank: 30 November 2026), carries more than oneunstructuredline; carries a numeric creditor reference typedscoron a Bankgiro or PlusGiro payment that is not a valid OCR number (2–25 digits, 5–25 for PlusGiro, modulus-10 check digit); or carries two or more invoices and credit notes whose amounts do not add up to the payment. The bank rejects each of these from that date. Combine the lines into one, check the OCR number on the invoice, or correct the amounts.BANK_NPC_ERI_TOO_MANY_REFERENCES,BANK_NPC_ERI_DOCUMENT_AMOUNT_MISSING,BANK_NPC_ERI_REFERENCE_WITHOUT_AMOUNT,BANK_NPC_ERI_CREDIT_NOTE_ALONE(errors): the same Swedish payments from the date their bank takes Extended Remittance Information (Swedbank: 30 November 2026) carry more than 999 invoices, credit notes and references; or, with more than one, a document without its amount or a creditor reference beside documents; or credit notes with no invoice. Split the documents over more payments, give each its amount, and send a reference alone.BANK_NPC_ERI_CATEGORY_PURPOSE_CONFLICT(error): a Swedbank Sweden payment carrying two or more invoices, credit notes or references, executed from 30 November 2026, names acategoryPurposeother thanSUPP. Swedbank's guide takes such a payment only as a supplier payment, and the engine writesSUPPfor it when no category purpose is given. Remove the category purpose, set it toSUPP, or send one document per payment. On such a paymentadditionalInfois not sent (BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT, warning): every structured record carries an invoice, credit note or reference and its amount, so a note for the whole payment has no place. From the same date a payment with no invoice, credit note or reference does not send itsadditionalInfoeither, with the same warning: Swedbank's guide places a note only beside the reference it clarifies. Put the text in theunstructuredline. Handelsbanken Sweden does the same withadditionalInfofrom 11 October 2026: a note travels inside the record of the one invoice, credit note or reference it belongs to, and with none or two or more it is not sent, with the same warning code. Handelsbanken's guide sets no category-purpose rule for ERI.BANK_SE_ERI_CREDIT_NOTE_BEFORE_DATE(error): a credit note on its own in a Swedbank Sweden payment executed BEFORE 30 November 2026. A credit note travels beside the invoice it reduces. Add the invoice the credit note reduces.BANK_REMITTANCE_TEXT_NOT_SENT,BANK_REMITTANCE_TEXT_JOINED,BANK_REMITTANCE_DOCUMENTS_AS_TEXT,BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT(warnings): the same Swedish payments at Swedbank, executed BEFORE it takes Extended Remittance Information (30 November 2026). Swedbank's guide allows one structured reference or one line of text until then, never both, so the payment is sent in that shape: a creditor reference goes alone and the text or documents beside it are not sent; two or moreunstructuredlines are joined into one line (the warning shows it); two or more invoices and credit notes go as one text line (the warning shows it); one invoice goes alone and text beside it is not sent;additionalInfois not sent. To have the text reach the payee, send it without the reference or the invoice. At SEB,additionalInfoon an account transfer is not sent on any date (BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT): SEB's guide takes none there; put the text in theunstructuredline. On a Bankgiro or PlusGiro payment at SEB,additionalInfois sent only beside an invoice, a credit note or a creditor reference; with none of them it is not sent, with the same warning, and the text belongs in theunstructuredlines. At Handelsbanken Sweden, from 11 October 2026, a Bankgiro, PlusGiro or account payment carries one line of text or one invoice, credit note or reference, and both only as Extended Remittance Information with two or more of them: one invoice or reference goes alone and text beside it is not sent (BANK_REMITTANCE_TEXT_NOT_SENT); on Bankgiro and PlusGiro before 1 November 2026 two or more invoices go as one text line (BANK_REMITTANCE_DOCUMENTS_AS_TEXT). Account payments there take Extended Remittance Information, with its rules, from 11 October 2026.BANK_REMITTANCE_TOO_MANY_LINES,BANK_REMITTANCE_TEXT_TOO_LONG,BANK_REMITTANCE_DOCUMENT_NUMBER_TOO_LONG,BANK_REMITTANCE_TOO_MANY_REFERENCES,BANK_REMITTANCE_TEXT_BESIDE_REFERENCE,BANK_REMITTANCE_TEXT_BESIDE_DOCUMENTS,BANK_REMITTANCE_REFERENCE_BESIDE_DOCUMENTS,BANK_REMITTANCE_DOCUMENT_AMOUNT_MISSING,BANK_REMITTANCE_AMOUNTS_MISMATCH,BANK_REMITTANCE_CREDIT_NOTE_ALONE,BANK_REMITTANCE_CREDIT_NOTE_TO_PLUSGIRO,BANK_REMITTANCE_ADDITIONAL_INFO_TOO_LONG(errors): a Swedish payment at Nordea Sverige or SEB carries remittance the bank's own guide does not take, on any date. At Nordea Sverige an account transfer or Bankgiro/PlusGiro payment carries oneunstructuredline, and document numbers and creditor references of at most 25 characters (BANK_CREDITOR_REFERENCE_TOO_LONG); a Bankgiro or PlusGiro payment carries at most 300 invoices, credit notes and references, each document with its amount when there are two or more, and a credit note only beside an invoice. At SEB a Bankgiro or PlusGiro payment carries at most threeunstructuredlines and 350 characters, at most 999 invoices, credit notes and references, each document with its amount, no credit note to a PlusGiro payee, text or documents, never both, andadditionalInfoof at most 315 characters across its lines. At both, on Bankgiro and PlusGiro, the invoices less the credit notes add up to the payment (one invoice included: send the amount paid), and a creditor reference goes without text and without documents beside it. At SEB an account transfer with invoices or a creditor reference goes as SEB's SEK Credit Transfer and carries at most oneunstructuredline, at most 999 invoices, credit notes and references, each document with its amount, the amounts adding up to the payment, and no creditor reference beside documents; text beside a reference is taken. The message names the limit and the bank's guide; shorten the text, split the documents over more payments, or correct the amounts.BANK_SE_CREDITOR_REFERENCE_NOT_RF(error): a SEB account transfer (domestic, SEK) carries a creditor reference that is not an RF creditor reference (ISO 11649). SEB's guide takes only an RF reference between bank accounts and writes it with issuerISO. An OCR number belongs to a Bankgiro or PlusGiro payment: pay the payee's Bankgiro or PlusGiro number with it, or send the reference asunstructuredtext.BANK_SE_RF_REFERENCE_ON_GIRO(error): a Swedbank Sweden Bankgiro or PlusGiro payment carries an RF creditor reference (ISO 11649), typedscoror untyped. Swedbank's guide takes an RF reference only with an IBAN or account number as the creditor account, and an OCR number only with a Bankgiro or PlusGiro number. Pay the payee's IBAN or account number with the RF reference, or pay the Bankgiro or PlusGiro number with the payee's OCR number.BANK_NEMKONTO_SCHEME_UNSUPPORTED,BANK_NEMKONTO_ID_INVALID,BANK_NEMKONTO_CREDITOR_ID_TAKEN(errors): a NemKonto payment at Nordea Danmark, where the payee's number travels as the creditor's identification (in pain.001.001.03 and pain.001.001.09 alike). Nordea takes a CPR number (schemeNKC, 10 digits) or a CVR number (NKV, 8 digits) and names no form for a P- or SE-number (NKP,NKR,NKS); and the creditor'sorganisationIdhas no place beside the number. Address the payee by CPR or CVR number, or by account number, and remove theorganisationId.BANK_DANSKE_SEPA_INSTANT_DEBIT_ACCOUNT_NOT_EUR,BANK_DANSKE_SEPA_INSTANT_AMOUNT_LIMIT(errors): a SEPA Instant payment from a Danske Bank account whose stateddebtor.account.currencyis not EUR. Danske's CGI-MP Appendix (v5.3, Appendix J) says the debit account must be in EUR, except in Finland and Ireland, where an account in another currency is limited to EUR 3,000,000 a transaction. So the payment is refused from a Danish or Swedish account in another currency, and above EUR 3,000,000.00 from a Finnish or Irish one. A EUR account has no SEPA Instant limit at Danske. Pay it from a EUR account, split it, or send it assepa.BANK_CREDITOR_REFERENCE_TYPE_MISSING(warning): a Finnish, Dutch or Swiss bank receives acreditorReferencewith notypethat is neither the country's own reference (a viitenumero, a betalingskenmerk, or a Swiss 27-digit QR reference) nor an ISO 11649 RF reference, such as an invoice number. Those banks' guides, and the Swiss Payment Standards, require every creditor reference to be typed and admit only those references, so the bank may reject the payment. The reference is sent as given, with no type. If it is free text for the creditor, send it asunstructured. An untyped RF reference is sent typed SCOR at those banks and needs nothing.BANK_CH_SCOR_REFERENCE_NOT_ISO11649(error): a payment from a Swiss bank in CHF or EUR to a Swiss or Liechtenstein account, off the SEPA rail, carries acreditorReferencethat goes out typed SCOR and is not an ISO 11649 RF reference: a non-RF value typedscor(a 27-digit QR reference among them), or a Belgian, Finnish or Dutch national reference or a Danish FIK reference. The Swiss Payment Standards validate every SCOR reference on such a payment as an RF reference and reject one that is not. Send an RF reference, a QR reference typedqrr(or untyped) to the creditor's QR-IBAN, or the text asunstructured.BANK_REMITTANCE_TEXT_NOT_SENT,BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT(warnings): a SEPA credit transfer from a Finnish or Dutch bank carries acreditorReferencebesideunstructuredtext,documentsoradditionalInfo; or, from a Finnish bank, exactly one ofdocumentsbesideunstructuredtext oradditionalInfo; or, from a Dutch bank,documentsbesideadditionalInfo. The Finnish banks' payments guide and the EPC guidelines the Dutch banks follow allow unstructured text or one structured item, never both, and Nordea ignores the text when both arrive. The creditor reference, or the one invoice or credit note, is sent alone and the rest is left out of the file. Each warning names what was left out, on the field it came from:BANK_REMITTANCE_TEXT_NOT_SENTfor the text or documents,BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENTforadditionalInfo. To have the text reach the payee instead, send it without the reference or document. A Finnish payment of severaldocuments(the ERI service) keeps its text.BANK_REMITTANCE_DOCUMENTS_AS_TEXT(warning): a SEPA credit transfer from a Dutch bank carriesdocumentsand nocreditorReference. The Dutch guide has no structured slot for invoices, so the documents go out as one unstructured line (each document's type, number and amount, then yourunstructuredtext, shortened to the document numbers when that does not fit, and cut at a word boundary past 140 characters); the warning quotes the line as sent and names what is not sent.BANK_REMITTANCE_ADDITIONAL_INFO_AS_TEXT(warning): a SEPA credit transfer from a Finnish or Dutch bank carriesadditionalInfoand nocreditorReference,documentsorunstructuredtext. Those banks' guides give additional information no structured slot, so it goes out as the payment's one unstructured line (its lines joined by a space, cut at a word boundary past 140 characters), which the payee receives as free text; the warning quotes the line as sent and names what is not sent. To send it as text without this warning, put it inunstructured.BANK_REMITTANCE_DOCUMENTS_AS_TEXT(warning): a SEPA credit transfer from an ING account carriesdocuments. ING's SEPA credit transfer guide admits a structured remittance only as a creditor reference typed SCOR and ignores referred documents, so the documents go out as one unstructured line (each document's type, number and amount, then yourunstructuredtext, shortened to the document numbers when that does not fit). A line still longer than 140 characters is cut at a word boundary. The warning quotes the line as sent and names what is not sent: the words the cut leaves out, and your whole text when the document numbers fill the line. Beside acreditorReferencethe line still goes, but ING forwards the reference to the payee rather than the line. The Dutch, German and Belgian rules above decide this for ING's accounts in those countries.BANK_REMITTANCE_ADDITIONAL_INFO_NOT_SENT(warning): a SEPA credit transfer from an ING account carriesadditionalInfo. ING's guide removes it from the structured remittance and rejects a payment that carries it, so it is left out of the file. Put the text in the oneunstructuredline to have it reach the payee. The Dutch rules above decide this for ING's Dutch accounts.BANK_CREDITOR_REFERENCE_NOT_SCOR(warning): a SEPA credit transfer from an ING account carries acreditorReferencethat goes out without the type SCOR: one with notypethat is neither a national reference nor (at a Finnish or Dutch bank) an RF reference, or akid,ocrorqrrreference, which goes out with a proprietary type ING's guide removes. ING may reject the payment, or pass the reference on as unstructured text. The reference is sent as given and never relabelled SCOR. If it is an ISO 11649 RF reference, send it withtype: "scor"; if it is free text for the creditor, send it asunstructured. An untyped reference at ING Netherlands drawsBANK_CREDITOR_REFERENCE_TYPE_MISSINGinstead.BANK_REMITTANCE_TEXT_JOINED(warning): a SEPA credit transfer carries two or moreunstructuredlines at a bank whose own guide allows one unstructured line: Swedbank Sweden, and ING (at ING Germany and ING Belgium the German and Belgian standards refuse a second line instead). The lines are sent as one, joined with a space; past 140 characters the line is cut at a word boundary, so a word or an invoice number that does not fit is left out whole rather than cut short. The warning quotes the line as sent and names any text that is not sent.BANK_REMITTANCE_TEXT_JOINED(warning): a payment carries two or moreunstructuredlines on a local instrument whose bank guide allows one unstructured line: J.P. Morgan US ACH CCD, CTX and PPD (anachpayment with nolocalInstrumentgoes as CCD). The lines are sent as one, joined with a space; past the limit J.P. Morgan sets for the instrument the line is cut at a word boundary. The warning quotes the line as sent and names any text that is not sent.BANK_FI_INVOICES_WITHOUT_CREDIT_NOTE_NOT_ERI(warning): a SEPA credit transfer from Nordea Finland, Säästöpankki, Oma Säästöpankki or Aktia carries two or more invoices indocumentsand no credit note. Nordea's Appendix Finland and Samlink's service description for the other three make at least one credit note part of the Extended Remittance Information (ERI) service, so the payment goes as a normal SEPA credit transfer, which carries one unstructured line or one structured item: the invoices, then yourunstructuredtext, as one line (the document numbers alone when the full line does not fit 140 characters, and cut at a word boundary past 140 characters), or thecreditorReferencealone when there is one.additionalInfois not sent. The warning quotes the line as sent and names what is not sent, or lists what was left out beside the reference. To send the invoices structured, add the credit note they are netted against, or pay each invoice on its own.REGULATORY_REPORTING_REQUIRED(error): a cross-border payment out of a country that runs a payer-supplied reporting regime, in that regime's currency, above its threshold, carrying noregulatoryReporting.details[].code. Today that is Norway (Skatteetaten's Valutaregisteret, above NOK 100 000, a two-digit code plus free text) and Sweden (Skatteverket's kontrolluppgift KU81, above SEK 150 000, a three-digit code). This is a legal reporting duty and the debtor's bank may refuse the payment over it, so the engine refuses it first. Read the whole rule (authority, threshold and the authority's published code list, so you can offer a dropdown) fromregulatoryReportingonGET /api/banks/<bank>/payment-types.REGULATORY_REPORTING_EXPECTED(warning): the same duty on a payment in a third currency. The engine holds no exchange rates, so it compares the bare number and cannot know the payment is over the threshold; it tells you, and the payment still converts. Convert it yourself.BANK_ADDRESS_DERIVATION_*: only when your bank settings turn onderiveHybridAddress. For a German, Austrian, Finnish, French, Dutch, UK, Jersey, Guernsey or Isle of Man party whosepostalAddresshasaddressLinesbut notownName, the engine takes the postcode and town from the one line shaped12345 Town(DE, FI, FR),1234 Town(AT),1234 AB Town(NL) orTown AB1 2CD(GB, JE, GG, IM) and sends a hybrid address; each element it fills is listed inautoFilled, and the payment's journal event names the party whose town was derived (the values themselves are in the payment's file). When it cannot do that with certainty it refuses the payment instead of guessing, and the issue names the party and quotes your lines:_TOWN_NOT_FOUND(no such line),_TOWN_AMBIGUOUS(more than one, or a line that still repeats the postcode or town),_POSTCODE_CONFLICT(yourpostCodedisagrees with the line),_TOO_MANY_LINES(more than two lines would remain),_TOWN_TOO_LONG,_COUNTRY_MISSING,_COUNTRY_UNSUPPORTED(not DE or AT) and_VERSION_UNSUPPORTED(the bank agreement emits pain.001.001.03, which has no hybrid address). SupplyingpostalAddress.townNameyourself always avoids all of them.BANK_DEBTOR_ADDRESS_NOT_FILLED_*(warning): only when your bank settings turn onfillDebtorAddressFromRegisteredAddress. A payment whosedebtorsends nopostalAddress, and whose debtor name is your organisation's legal name or organisation name (case, spacing and punctuation aside), is given your registered address from Company settings → Company: street, building number, postcode, town and county, anddebtor.countrywhen you sent none. Each element it fills is listed inautoFilled, and an address you send is never changed. When it does not fill a debtor it says why:_OTHER_PARTY(the debtor name is not your organisation's, as when a group pays for a subsidiary),_NO_REGISTERED_ADDRESS(the registered address has no town or country) or_COUNTRY_CONFLICT(debtor.countryis not the registered country).
Query GET /api/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)
| Type | Key requirements |
|---|---|
sepa | creditor IBAN required; EUR only |
sepa-instant | as SEPA; no scheme maximum, only a bank's own published ceiling |
international | creditor account and creditor BIC required |
fik (DK) | valid FIK reference (kortart + Luhn); FIK/giro creditor number; DKK only |
kid (NO) | 4–25 chars, MOD10/MOD11 (a MOD11 check value of 10 is a trailing -); NOK only |
bankgiro (SE) | Luhn-checked, digit-length bounded; scheme BGNR; SEK only |
plusgiro (SE) | Luhn-checked, digit-length bounded; scheme BBAN |
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) | CH/LI 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.
A third, rarer error means the fault is ours, not yours: PAYMENT_TYPE_BANK_OFFERS_NO_PAYMENT_TYPES says the bank profile has no payment types configured at all, so no rail can be selected and no file is produced. Setting paymentType explicitly will not help. Tell us and we fix the profile.
Where warnings are returned
A warning never blocks anything. It reports a file the bank will _accept_ while doing something other than what you asked: a payment marked urgent riding a non-urgent rail (it settles at normal speed), or a creditor name the bank will truncate. So warnings arrive on success responses, not only on a 422:
| Call | Success response | Where the warnings are |
|---|---|---|
POST /api/validate/{bank} | 200 JSON | issues, mixed with any errors, filter on severity |
POST /api/journal/payments | 201 JSON | warnings (top level, omitted when there are none) |
POST /api/journal/payments/preview | 200 JSON | warnings |
POST /api/convert-async/{bank} | 202 JSON | warnings |
POST /api/convert/{bank} | 200 XML (the file) | X-Validation-Warnings header, the body is a file, so there is no JSON field to put them in |
| any call | 422 JSON | error.details.issues, mixed with the errors that caused the rejection |
warnings holds exactly the same issue objects as issues, same code, message, path, level, filtered to severity: "warning". One shape on every path, so one parser handles them all.
Date rules are evaluated in the tenant's timezone, not UTC. GENERIC_EXECUTION_DATE_PAST, GENERIC_EXECUTION_DATE_FAR_FUTURE and GENERIC_EXECUTION_DATE_INTL_TOO_SOON all derive "today" from a timezone, so what counts as "past" depends on which calendar day the check runs in. GENERIC_EXECUTION_DATE_AFTER_CUTOFF is the exception: a cut-off is a deadline the bank publishes in its own zone ("15:30"), so both "is the execution date today?" and "has the deadline passed?" are answered in the BANK's timezone. A tenant in Auckland and a tenant in Lisbon get the same answer about a German bank. On POST /api/convert/{bank} and POST /api/convert-async/{bank} that is the timezone of the company your credential names (a signed-in session or an install's own organisation; an API key names its company by supplying ?companyId=); a call that names no single company (an API key that omits those params, or an unauthenticated/dev-mode call) is evaluated in UTC.
The header on POST /api/convert/{bank} is the one exception, and it carries codes only:
X-Validation-Warnings: SEPA_INSTRPRTY_IGNORED=1,PROFILE_NAME_TRUNCATED=3
CODE=count pairs, comma separated, one per distinct code, so the header is bounded by the number of warning _codes_, not by the size of your batch. code is the stable value you branch on anyway; for the full messages and paths, post the same body to POST /api/validate/{bank}.
All of these fields are additive: they appear only when a payment actually raised a warning, so a response for a clean payment is unchanged.
Handling issues in your client
// Rejected (422): the issues that caused it, plus any warnings alongside them.
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`.
}
// Accepted (201): the payment went through; log anything it warned about.
if (res.status === 201) {
const { journalNo, warnings = [] } = await res.json();
for (const w of warnings) console.warn(`${journalNo} ${w.code} @ ${w.path}: ${w.message}`);
}
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.
A bank with no payment rails
A bank profile with no payment types has no rail a payment could use. A payment to it is refused at conversion with the blocking issue PAYMENT_TYPE_BANK_OFFERS_NO_PAYMENT_TYPES, and no file is produced. This is a fault in the bank profile, not in your payment.
When a connection is created for a bank with no payment rails, BankConnector emits a connection.no-payment-rails event once (see Receiving results). The connection still activates. An inbound-only connection (statements and status reports, no payments) needs no action.