Required fields for a corridor: validate the corridor before returning the form
This is the most important read-only endpoint in this flow because upstream payee creation occurs at dispatch, not when the payee is submitted locally. Missing a format check therefore does not merely cost a 400 response: it can leave funds already held in locked before discovering that the payee cannot be created. The order then remains in dispatching, the upstream payee is terminally failed, and manual intervention is required.
Do not hardcode a field list on your side. Render the form from this contract, validate with its pattern / max_length / required, and submit the user’s values unchanged in fields to POST /v1/remit/payees. We can add a country or clearing network or tighten a format without requiring your code changes.
Fields are evaluated per corridor, not taken from one fixed table. Even for individuals, GB/GBP requires IBAN + a 6-digit sort code, US/USD/ACH requires account number + ABA, and SG/SGD requires neither name nor address because the upstream explicitly omits them.
⚠ Only fields that are required, participate in the fingerprint, or have ambiguous documentation are returned. An unused form control only makes users think they missed something. Thus required: false is not necessarily inconsequential: the field often participates in the payee fingerprint, with in_fingerprint: true, and supplying it can decide between creating and linking an existing payee.
⚠ Inputs use snake_case, such as country_code, but the response corridor uses camelCase, such as countryCode, reflecting our internal shape. Do not send the response object directly back as input.
⚠ bind supplies fixed values that must be submitted together when the field is filled. For example, GBP + FASTER PAYMENTS uses a 6-digit sort code in bank_details.routing_code_value1, together with bank_details.routing_code_type1: sort_code. The corridor uniquely determines the type; do not let users choose it. Doing so allows routing-type changes the upstream does not validate, which could send funds through the wrong clearing rail.
⚠ A populated pending_confirm means the upstream documentation is ambiguous and we use the more permissive interpretation. You may label the field optional but must allow submission. Adding stricter checks from that documentation can immediately block valid users.
Prerequisites
- The corridor must be enabled and present in your list; restricted jurisdictions and corridors withdrawn by the upstream are rejected
- We must be able to determine a routing-code type for the corridor; otherwise it is rejected with guidance toward SWIFT
Query Parameters
| Field | Type | Required | Description |
|---|---|---|---|
country_code |
string | Required | Country of the receiving bank, two uppercase letters. Alias: country. |
currency |
string | Required | Payout currency, three uppercase letters. |
payment_method |
string | Required | LOCAL or SWIFT. Alias: method. |
clearing_system |
string | Required | Clearing network, such as FASTER PAYMENTS / ACH / PAYNOW / CHATS. Preserve its case exactly; we uppercase the other four dimensions but leave this one unchanged. Alias: clearing. |
entity_type |
"INDIVIDUAL" | "COMPANY" | Required | Whether the payee is an individual or company. Alias: entity. |
Response
fields is already sorted by group order and then within-group order; render in that order. Fields sharing a group are contiguous, enabling one screen per group. Group order is payee → bank → account → address → extra.{
"corridor": {
"countryCode": "GB",
"currency": "GBP",
"paymentMethod": "LOCAL",
"clearingSystem": "FASTER PAYMENTS",
"entityType": "INDIVIDUAL"
},
"fields": [
{
"key": "first_name",
"label_key": "payee.first_name",
"type": "text",
"group": "payee",
"order": 10,
"width": "half",
"required": true,
"max_length": 45,
"in_fingerprint": false
},
{
"key": "last_name",
"label_key": "payee.last_name",
"type": "text",
"group": "payee",
"order": 20,
"width": "half",
"required": true,
"max_length": 45,
"in_fingerprint": false
},
{
"key": "bank_details.account_holder",
"label_key": "payee.account_holder",
"type": "text",
"group": "payee",
"order": 40,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "bank_details.swift_code",
"label_key": "payee.swift_code",
"type": "text",
"group": "bank",
"order": 10,
"required": true,
"pattern": "^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$",
"normalize": "alnum_upper",
"in_fingerprint": true
},
{
"key": "bank_details.bank_name",
"label_key": "payee.bank_name",
"type": "text",
"group": "bank",
"order": 20,
"required": true,
"in_fingerprint": false
},
{
"key": "bank_details.bank_address",
"label_key": "payee.bank_address",
"type": "text",
"group": "bank",
"order": 30,
"required": true,
"in_fingerprint": false
},
{
"key": "bank_details.account_number",
"label_key": "payee.account_number",
"type": "text",
"group": "account",
"order": 10,
"required": false,
"pattern": "^[a-zA-Z0-9]*$",
"normalize": "alnum_upper",
"in_fingerprint": true
},
{
"key": "bank_details.iban",
"label_key": "payee.iban",
"type": "text",
"group": "account",
"order": 20,
"required": true,
"normalize": "alnum_upper",
"in_fingerprint": true
},
{
"key": "bank_details.routing_code_value1",
"label_key": "payee.routing.sort_code",
"type": "text",
"group": "account",
"order": 30,
"required": true,
"pattern": "^[0-9]{6}$",
"normalize": "alnum_upper",
"in_fingerprint": true,
"bind": {
"bank_details.routing_code_type1": "sort_code"
}
},
{
"key": "additional_info.proxy_id",
"label_key": "payee.proxy_id",
"type": "text",
"group": "account",
"order": 50,
"required": false,
"normalize": "trim",
"in_fingerprint": true
},
{
"key": "address.country",
"label_key": "payee.country",
"type": "text",
"group": "address",
"order": 10,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.state",
"label_key": "payee.state",
"type": "text",
"group": "address",
"order": 20,
"width": "half",
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.city",
"label_key": "payee.city",
"type": "text",
"group": "address",
"order": 30,
"width": "half",
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.street_address",
"label_key": "payee.street",
"type": "text",
"group": "address",
"order": 40,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.postal_code",
"label_key": "payee.postal_code",
"type": "text",
"group": "address",
"order": 50,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "additional_info.organization_code",
"label_key": "payee.organization_code",
"type": "text",
"group": "extra",
"order": 50,
"required": false,
"in_fingerprint": false,
"pending_confirm": "上游文档未写「Required when」,只说用于中国大陆注册的企业"
}
],
"fingerprint_keys": [
"bank_details.swift_code",
"bank_details.account_number",
"bank_details.iban",
"bank_details.routing_code_value1",
"additional_info.proxy_id"
],
"pending_count": 1
}corridor_not_supported: incomplete four-part corridor, disabled corridor, restricted jurisdiction, or no determinable routing-code type. Choose another corridor rather than retrying; switching to SWIFT in the same country often works.curl -X GET 'https://api.zinfra.vip/v1/remit/payee-form-schema' \
-H 'x-auth-token: Bearer $TOKEN'const res = await fetch("https://api.zinfra.vip/v1/remit/payee-form-schema", {
method: "GET",
headers: {
"x-auth-token": "Bearer $TOKEN",
},
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();import requests
res = requests.get(
"https://api.zinfra.vip/v1/remit/payee-form-schema",
headers={
"x-auth-token": "Bearer $TOKEN",
},
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()req, _ := http.NewRequest("GET", "https://api.zinfra.vip/v1/remit/payee-form-schema",
nil)
req.Header.Set("x-auth-token", "Bearer $TOKEN")
res, err := http.DefaultClient.Do(req)
// Decode amount fields as string, not float64.HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.zinfra.vip/v1/remit/payee-form-schema"))
.header("x-auth-token", "Bearer $TOKEN")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
// Use String / BigDecimal for amounts, not double.$ch = curl_init('https://api.zinfra.vip/v1/remit/payee-form-schema');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'x-auth-token: Bearer $TOKEN',
],
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
{
"corridor": {
"countryCode": "GB",
"currency": "GBP",
"paymentMethod": "LOCAL",
"clearingSystem": "FASTER PAYMENTS",
"entityType": "INDIVIDUAL"
},
"fields": [
{
"key": "first_name",
"label_key": "payee.first_name",
"type": "text",
"group": "payee",
"order": 10,
"width": "half",
"required": true,
"max_length": 45,
"in_fingerprint": false
},
{
"key": "last_name",
"label_key": "payee.last_name",
"type": "text",
"group": "payee",
"order": 20,
"width": "half",
"required": true,
"max_length": 45,
"in_fingerprint": false
},
{
"key": "bank_details.account_holder",
"label_key": "payee.account_holder",
"type": "text",
"group": "payee",
"order": 40,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "bank_details.swift_code",
"label_key": "payee.swift_code",
"type": "text",
"group": "bank",
"order": 10,
"required": true,
"pattern": "^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$",
"normalize": "alnum_upper",
"in_fingerprint": true
},
{
"key": "bank_details.bank_name",
"label_key": "payee.bank_name",
"type": "text",
"group": "bank",
"order": 20,
"required": true,
"in_fingerprint": false
},
{
"key": "bank_details.bank_address",
"label_key": "payee.bank_address",
"type": "text",
"group": "bank",
"order": 30,
"required": true,
"in_fingerprint": false
},
{
"key": "bank_details.account_number",
"label_key": "payee.account_number",
"type": "text",
"group": "account",
"order": 10,
"required": false,
"pattern": "^[a-zA-Z0-9]*$",
"normalize": "alnum_upper",
"in_fingerprint": true
},
{
"key": "bank_details.iban",
"label_key": "payee.iban",
"type": "text",
"group": "account",
"order": 20,
"required": true,
"normalize": "alnum_upper",
"in_fingerprint": true
},
{
"key": "bank_details.routing_code_value1",
"label_key": "payee.routing.sort_code",
"type": "text",
"group": "account",
"order": 30,
"required": true,
"pattern": "^[0-9]{6}$",
"normalize": "alnum_upper",
"in_fingerprint": true,
"bind": {
"bank_details.routing_code_type1": "sort_code"
}
},
{
"key": "additional_info.proxy_id",
"label_key": "payee.proxy_id",
"type": "text",
"group": "account",
"order": 50,
"required": false,
"normalize": "trim",
"in_fingerprint": true
},
{
"key": "address.country",
"label_key": "payee.country",
"type": "text",
"group": "address",
"order": 10,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.state",
"label_key": "payee.state",
"type": "text",
"group": "address",
"order": 20,
"width": "half",
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.city",
"label_key": "payee.city",
"type": "text",
"group": "address",
"order": 30,
"width": "half",
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.street_address",
"label_key": "payee.street",
"type": "text",
"group": "address",
"order": 40,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "address.postal_code",
"label_key": "payee.postal_code",
"type": "text",
"group": "address",
"order": 50,
"required": true,
"normalize": "trim",
"in_fingerprint": false
},
{
"key": "additional_info.organization_code",
"label_key": "payee.organization_code",
"type": "text",
"group": "extra",
"order": 50,
"required": false,
"in_fingerprint": false,
"pending_confirm": "上游文档未写「Required when」,只说用于中国大陆注册的企业"
}
],
"fingerprint_keys": [
"bank_details.swift_code",
"bank_details.account_number",
"bank_details.iban",
"bank_details.routing_code_value1",
"additional_info.proxy_id"
],
"pending_count": 1
}