---
description: >-
  Retrieve a country's complete draft-07 JSON Schema with GET
  /schema/{countryCode}. It defines the recipient, sender, amount, and
  additionalData rules the gateway validates a push against.
---

# Schemas

`GET /schema/{countryCode}` returns a **country-specific [JSON Schema](https://json-schema.org/) (draft-07)** describing everything a payout to that country must contain. Query it before building a `recipient` so your form renders exactly the fields — and the validation rules — that corridor requires.

Because required fields, postal-code formats, document types, and payout methods vary by country, a form hardcoded for one corridor will fail in another. Drive the form off the schema instead:

- **Build dynamic forms** that adapt to each destination country
- **Validate input** client-side using the schema's `pattern`, `enum`, `minLength`, and `required`
- **Display the right fields** for each payout method (bank deposit, PIX, wallet)

The response is a draft-07 JSON Schema document: an object with `type`, `required`, and `properties`, where nested objects (`address`, `paymentMethod`) and arrays (`documents`) carry their own `required`/`properties`.

> **Country codes are ISO 3166-1 alpha-3 throughout** — in the path (`BRA`, `MEX`, `PHL`) and in the `address.countryCode` field, which the schema enforces with `"pattern": "^[A-Z]{3}$"` on both `recipient.address` and `sender.address`.

---

## Country Schema

Returns the **complete push contract** for a destination country: the `recipient` (identity, address, documents, payout method), the currency `recipientAmount` must carry, the `additionalData` that corridor requires, and — on corridors that constrain it — a `sender` block. This is the schema the gateway itself validates `POST /v2/payment` against, so it is the authoritative answer to "what does this country need?"

> **Not every country schema carries every top-level block.** `sender` in particular is present on some corridors and absent on others; where absent, only the generic push schema's sender rules apply. Read the blocks that are there rather than assuming a fixed shape — the set is being extended.

Unlike the three endpoints below, the country code is a **path parameter**, not a query parameter.

### Endpoint

```
GET https://{FQDN}/schema/{countryCode}
```

**Headers:**

| Header | Value |
|---|---|
| `Authorization` | `Bearer {accessToken}` |

### Path Parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `countryCode` | string | Yes | ISO 3166-1 **alpha-3** country code (e.g., `"IND"`, `"BRA"`, `"DEU"`) |

### Example Request

```bash
curl -X GET 'https://{FQDN}/schema/DEU' \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...'
```

### Response (200)

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Inyo Global PUSH Country Schema - Germany",
  "version": "1.0.1",
  "description": "Schema for processing a transaction to a DEU recipient",
  "type": "object",
  "properties": {
    "recipient": {
      "type": "object",
      "required": ["firstName", "lastName"],
      "properties": {
        "firstName": { "type": "string", "minLength": 1 },
        "lastName": { "type": "string", "minLength": 1 },
        "address": { "type": "object", "properties": { "…": {} } },
        "paymentMethod": {
          "type": "object",
          "required": ["countryCode"],
          "properties": {
            "type": { "type": "string", "enum": ["BANK_DEPOSIT"] },
            "countryCode": { "type": "string", "enum": ["DEU"] },
            "accountNumber": {
              "type": "string",
              "description": "The International Bank Account Number (IBAN).",
              "pattern": "^DE\\d{20}$"
            }
          }
        }
      }
    },
    "recipientAmount": {
      "type": "object",
      "properties": {
        "total": { "type": "number", "minimum": 0 },
        "currency": { "type": "string", "enum": ["EUR"] }
      }
    },
    "additionalData": {
      "type": "object",
      "properties": {
        "statementNarrative": { "type": "string" }
      }
    }
  }
}
```

### Reading the conditionals

Richer corridors express their rules as JSON Schema conditionals rather than a flat `required` list. Two shapes appear:

- **`allOf` with `if`/`then` on `paymentMethod.type`** — the corridor offers more than one payout method and each demands different fields. Brazil requires `accountNumber`, `accountType`, `bankCode`, `routingNumber` when `type` is `BANK_DEPOSIT`, but `key` and `keyType` when it is `PIX`.
- **`if`/`then`/`else` on `accountNumberType`** — the corridor offers an alias rail alongside conventional accounts. India requires only `accountNumber` (a UPI VPA) when `accountNumberType` is `UPI`, and `accountNumber` + `bankCode` + `accountType` otherwise.

A validator that only reads the top-level `required` will accept payloads the gateway rejects with [`VE_001`](../payment/push-transaction/errors.md#ve_001-the-payload-does-not-satisfy-the-schema). Evaluate the whole document.

> **`recipientAmount.currency` is an enum, not a suggestion.** Each country pins its destination currency — `BRA` accepts only `BRL`. Guinea (`GIN`) is the sole corridor accepting two (`GNF`, `XOF`).

### Errors

| Status | Condition |
|---|---|
| `400` | Unknown or unsupported country code — `PAY_271: Error retrieving JSON schema for country code: {countryCode}` |

---

## Per-Country Differences

The schemas are the source of truth, but a few corridors have quirks worth calling out. Always render from the live schema rather than hardcoding these — they can change.

| Country | Difference |
|---|---|
| **Brazil (`BRA`)** | Offers `BANK_DEPOSIT` and `PIX` from one schema, each with its own required set. Recipient requires a **CPF** via `documents[].document` (11 digits, or formatted `123.456.789-09`). For bank deposit: `bankCode` (3 digits) and `routingNumber` = branch/*agência*. |
| **Mexico (`MEX`)** | The **CLABE** (18 digits in `accountNumber`) already encodes the bank, so a `BBAN` payout needs nothing else. Selecting `accountNumberType: "DIMO"` switches `accountNumber` to a 10-digit phone number and makes `bankCode` required. |
| **India (`IND`)** | `accountNumberType: "UPI"` puts a Virtual Payment Address (`user@psp`) in `accountNumber` and drops `bankCode`/`accountType`. `BBAN` requires all three, with `bankCode` an IFSC (`^[A-Z]{4}0[A-Z0-9]{6}$`). |
| **South Korea (`KOR`)** | The only corridor that constrains the **sender's** identity: `sender.birthDate` (`YYYY-MM-DD`) and `sender.birthCountryCode` (alpha-3) are both required. |
| **SEPA (23 countries)** | Only the IBAN in `accountNumber`, validated against that country's own IBAN shape (`^DE\d{20}$`, `^FR\d{12}[A-Z0-9]{11}\d{2}$`, …). No `accountNumberType`, no bank code. |

---

## How to Consume a Schema

Reading the draft-07 keywords when rendering a field:

| Keyword | Use |
|---|---|
| `type` | Data type: `"string"`, `"object"`, `"array"`, `"number"`, `"boolean"` |
| `required` | Array of mandatory property names (at that object's level) |
| `properties` | Field definitions for an object |
| `items` | Element schema for an array (e.g. `documents`) |
| `enum` | Allowed values — render a single-value enum as read-only, a multi-value enum as a select |
| `pattern` | Regex the value must match (postal codes, CPF, account numbers) |
| `minLength` | Minimum string length |
| `description` | Human-readable hint — good default for a placeholder or label |

Note the two conditional keywords above: a validator that reads only the top-level `required` will accept payloads the gateway rejects with [`VE_001`](../payment/push-transaction/errors.md#ve_001-the-payload-does-not-satisfy-the-schema).

Recommended flow:

1. Read the destination country from your form and convert it to **ISO-3**.
2. `GET /schema/{countryCode}` for that code.
3. Render the recipient form from `recipient.properties` — including `paymentMethod`, whose fields depend on `type` and, on some corridors, `accountNumberType`.
4. Apply the `sender` block if the schema carries one, and offer only the `recipientAmount.currency` values its enum allows.
5. Validate every value against its `pattern`/`enum`/`required`, evaluating `allOf`/`if`/`then`/`else`.
6. Submit the collected `sender`, `recipient`, and `additionalData` in the [Push Transaction](../payment/push-transaction.md) payload.

## What's Next

- [Push Transaction](../payment/push-transaction.md) — Build the `recipient` and `paymentMethod` from this schema
- [Banks](banks.md) — Look up bank codes to populate `bankCode` fields
- [Check Account](../check-account.md) — Validate account details before transacting
