# Form Schemas

> Form schemas are JSON Schema definitions describing the data a channel needs to complete a payment, and how to validate against them.

## Overview

Form schemas define the data required to complete a payment through a specific channel. They are standard [JSON Schema](https://json-schema.org/) definitions that you can use to:

- **Validate payment data** before submission
- **Generate forms** using libraries like [JSON Forms](https://jsonforms.io/) or [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form)
- **Build automated integrations** that programmatically populate payment details

We publish all form schemas to a public GitHub repository for full transparency and offline access.

:::tip

View our published schemas at [github.com/noah-labs/public-schemas](https://github.com/noah-labs/public-schemas)

:::

## Understanding Channels and Schemas

A **Channel** represents a specific payment route, uniquely identified by:

| Parameter             | Description                      | Example                                |
| --------------------- | -------------------------------- | -------------------------------------- |
| **Country**           | ISO 3166-1 alpha-2 country code  | `BR`, `DE`, `US`                       |
| **PaymentMethodType** | The payment method               | `BankSepa`, `BankAch`, `IdentifierPix` |
| **Direction**         | Transaction direction            | `In` (deposit), `Out` (payout)         |
| **Provider**          | The underlying payment processor | (internal)                             |

### Multiple Channels per Route

For a given Country + PaymentMethodType + Direction, there may be **multiple channels** available — one or more per payment provider. These channels are not always identical and may differ in:

| Aspect              | Description                                                          |
| ------------------- | -------------------------------------------------------------------- |
| **Features**        | One provider may support QR codes while another supports identifiers |
| **Required Data**   | Some providers require more customer information than others         |
| **Cost**            | Fee structures vary between providers                                |
| **Processing Time** | Settlement times differ                                              |

Each channel has its own form schema, tailored to that provider’s specific data requirements. We normalise field names and structures across providers wherever possible, but each schema is deliberately scoped to the minimum information required for that provider.

That means you’ll never be asked to collect extra data just because another provider (or channel) needs it. If a particular provider requires additional information, those fields will appear only in that provider’s form schema, never as superfluous requirements applied across the board.

## Retrieving Form Schemas

### Option 1: Via the Channels API (Recommended)

When you query available channels, each channel includes its `FormSchema` directly in the response:

```bash
curl -L 'https://api.sandbox.noah.com/v1/channels/sell?Country=BR&FiatCurrency=BRL&CryptoCurrency=USDC_TEST' \
  -H 'Accept: application/json' \
  -H 'X-Api-Key: <X-Api-Key>'
```

Response:

```json
{
  "Items": [
    {
      "ID": "channel-uuid-1",
      "Country": "BR",
      "FiatCurrency": "BRL",
      "PaymentMethodType": "IdentifierPix",
      "FormSchema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
          "PixKey": {
            "type": "string",
            "title": "PIX Key"
          }
        },
        "required": ["PixKey"]
      },
      "Limits": { "MinLimit": "1" },
      "ProcessingSeconds": 300
    },
    {
      "ID": "channel-uuid-2",
      "Country": "BR",
      "FiatCurrency": "BRL",
      "PaymentMethodType": "IdentifierPix",
      "FormSchema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
          "PixKey": { "type": "string", "title": "PIX Key" },
          "TaxId": { "type": "string", "title": "Tax ID" },
          "FullName": { "type": "string", "title": "Full Name" }
        },
        "required": ["PixKey", "TaxId", "FullName"]
      },
      "Limits": { "MinLimit": "10" },
      "ProcessingSeconds": 600
    }
  ]
}
```

In this example, two PIX channels are available for Brazil — one requires only a PIX key, while the other requires additional customer information. Use the schema from whichever channel you select.

### Option 2: Via Published Schema Files

:::warning Important

The published schemas are provided for **informational purposes** and are subject to change. We strongly recommend integrating dynamically using the [Channels API](#option-1-via-the-channels-api-recommended) rather than hardcoding against the published schema files. This ensures your integration automatically adapts to any schema updates.

:::

For offline access or pre-integration planning, schemas are published to our [public-schemas repository](https://github.com/noah-labs/public-schemas):

```
public-schemas/
├── prod/
│   ├── README.md          # Lookup table
│   ├── a1b2c3d4.json      # Schema files
│   └── ...
└── sandbox/
    ├── README.md
    └── ...
```

Each environment folder contains:

1. **README.md** — A lookup table mapping channels to schema files:

   | Country | Payment Method | Direction | Provider  | Schema          |
   | ------- | -------------- | --------- | --------- | --------------- |
   | BR      | IdentifierPix  | Out       | Provider1 | ./a1b2c3d4.json |
   | BR      | IdentifierPix  | Out       | Provider2 | ./e5f6g7h8.json |

2. **Schema JSON files** — Each file includes the schema plus metadata. The `id` in channel metadata is for reference only. Always obtain channel IDs from the Channels API at runtime—they are not suitable for caching or hardcoding.

   ```json
   {
     "metadata": {
       "channels": [{
         "id": "channel-uuid-1",
         "country": "BR",
         "direction": "Out",
         "finServiceID": "b9s4g",
         "paymentMethodType": "IdentifierPix"
       }],
       "contentHash": "sha256...",
       "generatedAt": "2025-01-29T12:00:00Z"
     },
     "$schema": "http://json-schema.org/draft-07/schema#",
     "type": "object",
     "properties": { ... }
   }
   ```

## Sandbox vs Production

**The schemas themselves are identical between environments** when a channel is available in both. However, **different channels may be enabled** in sandbox versus production.

This means:

- A channel available in production might not be enabled in sandbox (or vice versa)
- Always query the appropriate environment to discover available channels

:::tip

**Recommendation:** Use the Channels API to discover available channels at runtime rather than hardcoding assumptions about availability.

:::

## Selecting a Channel

When multiple channels exist for the same route, select based on your requirements:

- **Features needed** — Does your use case require QR codes, identifiers, or specific payment flows?
- **Data availability** — Do you have the customer data required by each schema?
- **Cost** — Compare fee structures between channels
- **Processing time** — Consider settlement speed requirements

We support channel prioritization configuration if you need consistent routing behavior.

## Correlating Dynamic and Static Schemas

Every dynamic form response includes a `FormMetadata` object with a `ContentHash` field — a SHA256 hash of the form schema content. This is the same value as the `contentHash` in the published static schema metadata.

Use `FormMetadata.ContentHash` to match a dynamically returned form with its corresponding pre-compiled static schema:

| Source                    | Field                       | Value             |
| ------------------------- | --------------------------- | ----------------- |
| Dynamic API response      | `FormMetadata.ContentHash`  | `sha256...`       |
| Published schema file     | `metadata.contentHash`      | `sha256...`       |
| Published schema filename | First 10 characters of hash | `a1b2c3d4e5.json` |

This enables automated integrations to use pre-compiled models for a known schema, while still dynamically adapting when the schema changes or when customer context reduces the required fields.

## Using Schemas for Automation

For automated integrations where you want to pre-fill payment data without user interaction:

1. **Query available channels** for the customer's country and payment method
2. **Review the schemas** to understand data requirements for each channel
3. **Select the channel** that matches your available data and requirements
4. **Validate your data** against the schema before submission

```typescript
import Ajv from 'ajv';

// 1. Get available channels
const { Items: channels } = await api.get('/v1/channels/sell', {
  params: { Country: 'BR', FiatCurrency: 'BRL', CryptoCurrency: 'USDC' },
});

// 2. Find a channel where you have all required data
const selectedChannel = channels.find((channel) => {
  const required = channel.FormSchema?.required || [];
  return required.every((field) => customerData[field] !== undefined);
});

// 3. Validate data against the schema
const ajv = new Ajv();
const validate = ajv.compile(selectedChannel.FormSchema);
const isValid = validate(customerData);

if (!isValid) {
  console.error('Validation errors:', validate.errors);
}
```

## Address fields in form schemas

Some channels include address objects (for example `AccountHolderAddress`) in their `FormSchema`. These are separate from the `StreetAddress` type used on customer and checkout endpoints. Requirements can differ by channel — always validate against the schema returned for your selected channel.

For shared rules on customer and checkout `StreetAddress` fields, see [Address Validation](./address-validation.md).

## Related Pages

- [Address Validation](./address-validation.md) — `StreetAddress` field rules for customers and checkout
- [Channels](./channels.md) — Understanding the channel framework
- [Dynamic User Interface](./dynamic-ui.md) — Building UIs with dynamic forms
- [Dynamic Form API Reference](../../api-reference/dynamic-form) — API endpoint details
