Bank transfer description rules 📝

The description of a bank transfer (POST /v1/banking/bank_transactions) is validated twice: once by a base rule common to every bank, and once by a per-bank rule derived from the sending account's bank (sender_id). This page carries the full detail behind the summary on the createBankTransaction contract.

The base rule, read literally

The server validates the field against the Ruby regex:

/\A[A-zÀ-ú0-9 ]+\Z/

Read that character class literally rather than as "alphanumeric":

  • A-z is the ASCII range 65122, so besides upper- and lowercase letters it also admits [, \, ], ^, _ and `.
  • À-ú is U+00C0U+00FA, so besides accented letters it also admits × and ÷.
  • Digits and the plain space are admitted.

Everything outside those ranges — including the punctuation commonly used in references: -, #, ., ,, /, (, ), :, +, & — is rejected with 422 {"message": "Validation failed: Description is invalid"}. Write Pago servicios Factura 1234, not Payment for services - Invoice #1234. There is no length limit at this layer.

The pattern published on the request schema (^[A-zÀ-ú0-9 ]+$) mirrors this regex; only the anchors differ (^/$ for JSON Schema, \A/\Z in Ruby, which additionally tolerates one trailing newline). It does not encode the per-bank rules below — a value that passes pattern can still be rejected, or rewritten, by the sending bank.

Per-bank rules

A transfer is created as the subclass of sender_id's bank, and most of those banks narrow the base rule. Satisfying the base rule is necessary, not sufficient.

Sending bankMax lengthOn top of the base character set
Banco BICE14/\A[A-z0-9]+\z/ — the base class minus the space and minus À-ú. Spaces, accents and punctuation are stripped silently and the result is cut to 14 characters: BICE rewrites instead of rejecting
BCI30no accents: /\A[A-z0-9 ]+\Z/
Banco de Chile, Santander, Scotiabank, Itaú, Cardda wallet70base rule
Banco Security, Banco Internacional, STP, BCPno capbase rule

For every capped bank except BICE, going over the cap fails with 422 {"message": "Validation failed: Description is too long (maximum is N characters)"}, N being that bank's number. BICE rewrites instead of rejecting — see below.

At BCI, a description that carries accents fails with the base-rule literal Description is invalid, even though the base rule allows accents — the subclass narrows the same validation.

BICE rewrites instead of rejecting

BICE strips every non-alphanumeric character (spaces and accents included) and cuts the result to 14 characters before validating. Two consequences:

  • Pago servicios Factura 1234 is accepted verbatim at every bank except BICE, which stores it as PagoserviciosF. When the sender is a BICE account, keep the reference within 14 letters and digits and choose them yourself instead of letting the strip pick.
  • BICE never returns Description is too long — but it does reject a description with nothing left after the strip, with 422 {"message": "Validation failed: Description only allows alphanumeric characters"}.

(BICE's length validation formally declares 15 characters, but the setter cuts to 14 before it runs, so the effective cap is 14.)

BCI supplier payrolls

Inside a payroll with category: "suppliers", BCI requires the description to be exactly FACT + a space + 1 to 12 digits (e.g. FACT 1234), otherwise 422 {"message": "Validation failed: Description must be FACT, followed by a space and 1 to 12 digits"}.

Truncation at the bank

Independently of all of the above, three integrations send only the first 40 characters of what you wrote: Banco Security, the BICE Connect path and STP. Keep the reference short if it has to be readable at the bank.

Error literals, in one place

HTTP 422 literalCause
Description is invalidCharacters outside the base class — or, at BCI, accents
Description is too long (maximum is N characters)The sending bank's length cap
Description only allows alphanumeric charactersBICE, when nothing survives its strip
Description must be FACT, followed by a space and 1 to 12 digitsBCI, payroll with category: "suppliers"

All of them arrive in the shared envelope {"message": "Validation failed: <reasons>"} — match on the fragment, not the whole string, since several failed validations are joined by a comma and a space into one message.


Did this page help you?