Field Validation Rules
Every regex the Corporate API enforces, and where the published rules differ from them.
Before You Start
Read the following guides before proceeding:
| Guide | Why |
|---|---|
| Api Basics | Request configuration |
Overview
The Corporate API validates most string fields against a regular expression before the request reaches
a handler. The patterns are published at runtime so a client can validate locally and avoid a round
trip.
GET /api/v1/validation/rules
Anonymous — no Authorization header.
Response:
{
"rules": {
"firstName": "^[a-zA-Z][a-zA-Z\\-']{1,50}$",
"email": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"iban": "^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$"
}
}| Field | Description |
|---|---|
rules | Map of rule name to regular expression |
The published rules are not identical to the enforced ones. Four of them differ, and two are
published for fields the Corporate API does not validate at all. The differences are listed below.
Where they disagree, the enforced pattern is what decides whether a request succeeds.
Enforced Patterns
These are the patterns the API applies.
Identity
| Rule | Pattern | Applies to |
|---|---|---|
| First name | ^[a-zA-Z][a-zA-Z\-' ]{0,49}$ | first_name on employee invite and update |
| Last name | ^[a-zA-Z][a-zA-Z\-' ]{0,49}$ | last_name on employee invite and update |
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ | email | |
| Phone | ^\+\d{1,15}$ | phone — required on employee invite |
| Company name | ^[A-Za-z0-9&.,'’\-/() :+#]{2,100}$ | corporation_name, company_name |
| Registration number | ^[A-Z0-9\-]{6,15}$ | corporation_registration_number |
| Country code | ^[A-Z]{2}$ | corporation_registration_country, country |
| Recipient name | ^[\p{L}\p{N}\s.'\-]{1,100}$ | recipient_name on corridor payment details |
| Employee search term | ^[A-Za-z0-9@._%+' -]{2,100}$ | term on employee search |
Employee names accept only unaccented Latin letters, apostrophes, hyphens and spaces. Recipient names
accept any Unicode letter or digit.José Mülleris a valid recipient name and an invalid employee
name.
Addresses
| Rule | Pattern | Applies to |
|---|---|---|
| Address line 1 | ^[A-Za-z0-9&.,'’\-/() :+#]{2,100}$ | line1 |
| Address line 2 | ^[A-Za-z0-9&.,'’\-/() :+#]{2,100}$ | line2 |
| City | ^[A-Za-z\s\-'.]{2,100}$ | city |
| State | ^[A-Za-z][A-Za-z\s\-']{1,99}$ | state |
| Postal code | ^[A-Za-z0-9\s\-]{3,12}$ | postal_code, zip_code |
| Country | ^[A-Z]{2}$ | country |
City accepts no digits. An address in a city whose name contains a numeral fails validation.
Blockchain
| Rule | Pattern | Applies to |
|---|---|---|
| Address | ^(0x[a-fA-F0-9]{40}|C[A-Za-z2-7]{55}|G[A-Za-z2-7]{55}|T[1-9A-HJ-NP-Za-km-z]{33})$ | corporation_address, token and wallet addresses |
| EVM address | ^0x[a-fA-F0-9]{40}$ | manager_address |
manager_addressaccepts EVM addresses only. A Stellar or Tron address is rejected there while
being accepted as acorporation_address.
Cards
| Rule | Pattern | Applies to |
|---|---|---|
| Name on card | ^[A-Za-z][A-Za-z .'-]{1,25}$ | name_on_card |
| Card name | ^[a-zA-Z0-9]+[a-zA-Z0-9\-':+#& ]{1,50}$ | card_name, card name |
| Expiry date | ^(0[1-9]|1[012])/\d{4}$ | expiry_date on card activation |
| Card number last 4 | ^\d{4}$ | card_number_last4 |
Bank Details
| Rule | Pattern | Applies to |
|---|---|---|
| IBAN | ^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$ | iban |
| UAE IBAN | ^AE\d{21}$ | iban on IPP details |
| BIC | ^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$ | bic |
| Account number | ^\d{8,18}$ | account_number on Faster Payments and ACH |
| Sort code | ^\d{6}$ | sort_code |
| Routing number | ^\d{9}$ | routing_number |
| CLABE | ^\d{18}$ | clabe |
| Currency | ^[A-Za-z0-9]{3,10}$ | currency |
| Catalog index | ^[a-zA-Z]$ | catalog_index on the recipient catalog filter |
IBAN and card number checksums are not validated. Both
IsValidIbanandIsValidCardNumber
returntrueunconditionally — only the format is checked. A format-valid IBAN with a bad check
digit passes here and is rejected by the rail after the transfer has been accepted.
Corridor Details
| Rule | Pattern | Applies to |
|---|---|---|
| PIX key type | ^(CPF|CNPJ|EMAIL|PHONE|EVP)$ | pix_key_type |
| PIX key — CPF | ^\d{11}$ | pix_key |
| PIX key — CNPJ | ^\d{14}$ | pix_key |
| PIX key — phone | ^\+55\d{10,11}$ | pix_key |
| PIX key — EVP | ^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$ | pix_key |
| FPS ID type | ^(FPS_ID|MOBILE|EMAIL)$ | fps_id_type |
| FPS-HK bank code | ^\d{3}$ | bank_code on FPS-HK |
| IMPS account number | ^\d{9,18}$ | account_number on IMPS |
| IFSC code | ^[A-Z]{4}0[A-Z0-9]{6}$ | ifsc_code |
| InstaPay bank code | ^([A-Z]{3,4}|[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?)$ | bank_code on InstaPay |
| BI-FAST bank code | ^(\d{3}|[A-Z]{4}ID[A-Z]{2})$ | bank_code on BI-FAST |
| NIP account number | ^\d{10}$ | account_number on NIP |
| NIP bank code | ^\d{3}$ | bank_code on NIP |
| PSE account type | ^(SAVINGS|CHECKING)$ | account_type on PSE |
| PSE bank code | ^\d{3}$ | bank_code on PSE |
| PSE document type | ^(CC|NIT|CE|PP)$ | document_type on PSE |
| PSE document number | ^[A-Z0-9]{5,20}$ | document_number on PSE |
Where the Published Rules Differ
| Rule | Published by GET /api/v1/validation/rules | Actually enforced | Consequence |
|---|---|---|---|
firstName, lastName | ^[a-zA-Z][a-zA-Z\-']{1,50}$ | ^[a-zA-Z][a-zA-Z\-' ]{0,49}$ | The published rule rejects names containing a space and single-character names, both of which the API accepts; it accepts 51-character names, which the API rejects |
state | ^[A-Za-z\s\-']{2,100}$ | ^[A-Za-z][A-Za-z\s\-']{1,99}$ | The published rule accepts a state starting with a space or hyphen; the API does not |
department, job | ^[a-zA-Z0-9][a-zA-Z0-9\-':+#]{1,50}$ | Not enforced | department and job_title accept any string. Validating locally against the published rule rejects input the API would take |
cardNumber | ^[0-9]{13,19}$ | Not used | The Corporate API never accepts a full card number |
Client-side validation against
firstNameas published will rejectMary Jane. Validate employee
names against^[a-zA-Z][a-zA-Z\-' ]{0,49}$.
Error Shape
Validation failures come back in two shapes, depending on the endpoint.
Structured — the field is in error_details under the key field:
{
"error_reason": "ErrorInvalidField",
"error_description": "Invalid format for corporation address",
"error_category": {
"category": "CategoryValidationFailure",
"http_status_code": 400
},
"error_details": [
{ "key": "field", "details": "corporation_address" },
{ "key": "issue", "details": "invalid_format" },
{ "key": "pattern", "details": "^(0x[a-fA-F0-9]{40}|C[A-Za-z2-7]{55}|G[A-Za-z2-7]{55}|T[1-9A-HJ-NP-Za-km-z]{33})$" }
]
}Keyed — the field is the key, and error_description is generic:
{
"error_reason": "ErrorGeneral",
"error_description": "Request failed validation",
"error_category": {
"category": "CategoryValidationFailure",
"http_status_code": 400
},
"error_details": [
{ "key": "first_name", "details": "First name is invalid" }
]
}The employee, role, FX and v2 card endpoints use the keyed shape; corporations, bank, recipient and v1
card endpoints use the structured shape. Handle both: read error_details[].key, and where it is
field, read the field name from details.
The structured shape often includes the offending pattern, which is the most reliable source of the
enforced regex for a specific field.
Updated 20 days ago

