> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rolla.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Beneficiary

> Creates a new saved beneficiary for the business.

Create a new saved beneficiary for your business. The required fields depend on the `withdrawal_method` and `currency`.

<Warning>
  **New required fields (`account_owner_type`, `account_category`).** Every bank-account
  beneficiary must now declare `account_owner_type` (`individual` or `business`), and
  every USD beneficiary must also declare `account_category` (`checking` or `savings`).
  During a 60-day grace period, requests that omit these fields still succeed but return a
  `deprecation_warning` in the response; after the enforcement date they are rejected with a
  `400`. See [Beneficiary Account Fields](/api-reference/endpoint/beneficiaries/account-fields)
  for the full migration guide.
</Warning>

## Example Request (NGN Bank Transfer)

For Nigerian Naira transfers, omit `withdrawal_method` (or set it to `null`). `bank_code` is always required for NGN.

```bash theme={null}
curl -X POST "https://api.rolla.xyz/api/v1/external/beneficiaries" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "NGN",
    "label": "Office rent",
    "account_name": "JOHN DOE",
    "account_number": "0123456789",
    "bank_name": "Access Bank",
    "bank_code": "000014",
    "account_owner_type": "business",
    "email": "john@example.com"
  }'
```

## Example Request (Domestic Wire — USD)

```bash theme={null}
curl -X POST "https://api.rolla.xyz/api/v1/external/beneficiaries" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "withdrawal_method": "domestic_wire",
    "label": "US Supplier",
    "account_name": "John Doe",
    "account_number": "123456789",
    "bank_name": "Chase Bank",
    "routing_number": "021000021",
    "account_owner_type": "business",
    "account_category": "checking",
    "beneficiary_address": {
      "street": "123 Main St",
      "city": "New York",
      "state": "NY",
      "postalCode": "10001",
      "country": "US"
    },
    "bank_address": {
      "street": "270 Park Ave",
      "city": "New York",
      "state": "NY",
      "postalCode": "10017",
      "country": "US"
    }
  }'
```

## Example Request (ACH — USD)

ACH is the low-cost domestic US rail. It reaches the same US bank accounts as a domestic wire but settles in business days rather than same-day, and is usually priced lower — so quote the fee per rail rather than assuming they match. Use `account_category` to say whether the destination is a checking or savings account.

```bash theme={null}
curl -X POST "https://api.rolla.xyz/api/v1/external/beneficiaries" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "withdrawal_method": "ach",
    "label": "US Payroll",
    "account_name": "John Doe",
    "account_number": "123456789",
    "bank_name": "Chase Bank",
    "routing_number": "021000021",
    "account_owner_type": "individual",
    "account_category": "checking",
    "beneficiary_address": {
      "street": "123 Main St",
      "city": "New York",
      "state": "NY",
      "postalCode": "10001",
      "country": "US"
    },
    "bank_address": {
      "street": "270 Park Ave",
      "city": "New York",
      "state": "NY",
      "postalCode": "10017",
      "country": "US"
    }
  }'
```

<Info>
  `routing_number` is the beneficiary bank's 9-digit ABA number and is **required** for both `ach` and `domestic_wire` — those rails are addressed by routing number, so a beneficiary saved without one can never be paid and is rejected with a `400`. `international_wire` uses `swift_code` instead and is unaffected.
</Info>

<Warning>
  The `domestic_wire` requirement is newly **enforced**. It has always been listed as required below, but the server previously accepted domestic wire beneficiaries without a `routing_number`. If you have saved any, backfill them via [`PATCH /beneficiaries/{beneficiaryId}`](/api-reference/endpoint/beneficiaries/update) — otherwise the next update to that beneficiary will be rejected.
</Warning>

## Example Request (International Wire — USD)

```bash theme={null}
curl -X POST "https://api.rolla.xyz/api/v1/external/beneficiaries" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "withdrawal_method": "international_wire",
    "label": "US Supplier",
    "account_name": "John Doe",
    "account_number": "123456789",
    "bank_name": "Barclays Bank",
    "swift_code": "BARCGB22",
    "account_owner_type": "business",
    "account_category": "checking",
    "beneficiary_address": {
      "street": "123 Main St",
      "city": "New York",
      "state": "NY",
      "postalCode": "10001",
      "country": "US"
    },
    "bank_address": {
      "street": "1 Churchill Place",
      "city": "London",
      "state": "England",
      "postalCode": "E14 5HP",
      "country": "GB"
    }
  }'
```

## Example Request (Crypto USDC)

```bash theme={null}
curl -X POST "https://api.rolla.xyz/api/v1/external/beneficiaries" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "withdrawal_method": "crypto_usdc",
    "label": "Base USDC wallet",
    "account_name": "My USDC Wallet",
    "wallet_address": "0x1234567890abcdef1234567890abcdef12345678",
    "wallet_chain": "base"
  }'
```

## Example Request (Rolla Transfer)

For sending funds to another Rolla business. Use `recipient_business_id` to identify the target business. You can send in any supported currency.

```bash theme={null}
curl -X POST "https://api.rolla.xyz/api/v1/external/beneficiaries" \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "withdrawal_method": "rolla_transfer",
    "label": "Partner company",
    "account_name": "Acme Corp",
    "recipient_business_id": "d4e5f6a7-b8c9-0123-defa-456789012345"
  }'
```

<Info>
  `recipient_business_id` is the Rolla-assigned UUID of the destination business. Each currency requires a separate beneficiary record — you cannot reuse the same `recipient_business_id` + `currency` combination.
</Info>

## Example Response

```json theme={null}
{
  "status": 201,
  "success": true,
  "message": "Beneficiary created successfully",
  "data": {
    "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "currency": "NGN",
    "label": "Office rent",
    "account_name": "JOHN DOE",
    "account_number": "0123456789",
    "bank_name": "Access Bank",
    "bank_code": "000014",
    "withdrawal_method": null,
    "account_owner_type": "business",
    "email": "john@example.com",
    "created_at": "2024-01-15T10:30:00.000Z",
    "updated_at": "2024-01-15T10:30:00.000Z"
  }
}
```

## Account Classification Fields

For compliant payout routing, bank-account beneficiaries carry two classification fields:

| Field                | Values                   | Required when                                                                                                                                                                                            |
| -------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account_owner_type` | `individual`, `business` | Every bank-account beneficiary — any fiat method that is not crypto or `rolla_transfer` (NGN bank transfer, `ach`, `domestic_wire`, `international_wire`). Not applicable to crypto or `rolla_transfer`. |
| `account_category`   | `checking`, `savings`    | Only when `currency` is `USD`. If you are not sure, use `checking`.                                                                                                                                      |

<Note>
  These fields are being rolled out with a **60-day grace period**. Requests that omit a
  required field currently still succeed but include a `deprecation_warning` object in the
  response (see below). After the enforcement date, the same request is rejected with a `400`.
  Send the fields now to avoid disruption. Full details in the
  [Beneficiary Account Fields migration guide](/api-reference/endpoint/beneficiaries/account-fields).
</Note>

### Deprecation warning (during grace period)

```json theme={null}
{
  "status": 201,
  "success": true,
  "message": "Beneficiary created successfully",
  "data": { "...": "..." },
  "deprecation_warning": {
    "code": "BENEFICIARY_FIELDS_REQUIRED_SOON",
    "message": "The field(s) account_owner_type will soon be required for beneficiaries. account_owner_type (individual|business) is required for bank-account beneficiaries; account_category (checking|savings) is required for USD beneficiaries.",
    "missing_fields": ["account_owner_type"],
    "enforcement_date": "2026-09-01T00:00:00.000Z"
  }
}
```

## Required Fields by Withdrawal Method

| Method                                     | Required Fields                                                                                                                                              |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| NGN bank transfer (no `withdrawal_method`) | `currency`, `account_name`, `account_number`, `bank_name`, `bank_code`, `account_owner_type`                                                                 |
| `ach` (USD)                                | `currency`, `account_name`, `account_number`, `bank_name`, `routing_number`, `beneficiary_address`, `bank_address`, `account_owner_type`, `account_category` |
| `domestic_wire` (USD)                      | `currency`, `account_name`, `account_number`, `bank_name`, `routing_number`, `beneficiary_address`, `bank_address`, `account_owner_type`, `account_category` |
| `international_wire` (USD)                 | `currency`, `account_name`, `account_number`, `bank_name`, `swift_code`, `beneficiary_address`, `bank_address`, `account_owner_type`, `account_category`     |
| `crypto_usdc` / `crypto_usdt`              | `currency`, `account_name`, `wallet_address`, `wallet_chain`                                                                                                 |
| `rolla_transfer`                           | `currency`, `account_name`, `recipient_business_id`                                                                                                          |

Both `beneficiary_address` and `bank_address` are objects with the following fields:

| Field        | Required | Notes                                   |
| ------------ | -------- | --------------------------------------- |
| `street`     | Yes      | Street address                          |
| `city`       | Yes      | City                                    |
| `state`      | Yes      | State or province                       |
| `postalCode` | Yes      | Zip/postal code                         |
| `country`    | Yes      | 2-letter country code (e.g. `US`, `GB`) |

<Warning>
  For NGN beneficiaries, use the `/beneficiaries/beneficiary-lookup` endpoint first to validate the account number and retrieve the correct account name before saving.
</Warning>


## OpenAPI

````yaml POST /beneficiaries
openapi: 3.1.0
info:
  title: Rolla Developer API
  description: >-
    API for programmatic transaction management on the Rolla platform. Monetary
    `amount` fields use the smallest unit of the referenced currency unless an
    endpoint says otherwise (e.g. NGN = kobo, USD = cents, where **100 cents =
    USD 1.00**).
  version: 1.0.0
servers:
  - url: https://api.rolla.xyz/api/v1/external
    description: Production server
security:
  - apiKeyAuth: []
paths:
  /beneficiaries:
    post:
      summary: Create Beneficiary
      description: Creates a new saved beneficiary for the business.
      operationId: createBeneficiary
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BeneficiaryRequest'
      responses:
        '201':
          description: Beneficiary created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Beneficiary created successfully
                  data:
                    type: object
                    properties:
                      beneficiary:
                        $ref: '#/components/schemas/SavedBeneficiary'
        '400':
          description: Bad request - Invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    BeneficiaryRequest:
      type: object
      required:
        - currency
      properties:
        currency:
          type: string
          description: Currency code (e.g., NGN, USD)
          example: NGN
        label:
          type: string
          description: Friendly label for the beneficiary
        account_name:
          type: string
          description: Account holder name
          maxLength: 100
          example: JOHN DOE
        account_number:
          type: string
          description: Bank account number
          maxLength: 50
          example: '0123456789'
        bank_name:
          type: string
          description: Bank name
          maxLength: 100
          example: Access Bank
        bank_code:
          type: string
          description: Bank code (required for NGN beneficiaries)
          maxLength: 20
          example: '000014'
        bank_address:
          type: object
          description: >-
            Bank's physical address. Required for USD domestic and international
            wire transfers.
          properties:
            street:
              type: string
              example: 270 Park Ave
            city:
              type: string
              example: New York
            state:
              type: string
              example: NY
            postalCode:
              type: string
              example: '10017'
            country:
              type: string
              example: US
        swift_code:
          type: string
          description: SWIFT/BIC code (required for international wire)
          maxLength: 20
        email:
          type: string
          format: email
          description: Beneficiary email
          maxLength: 100
        contact_person:
          type: string
          description: Contact person name
          maxLength: 100
        beneficiary_address:
          type: object
          description: >-
            Beneficiary's physical address. Required for USD domestic and
            international wire transfers.
          properties:
            street:
              type: string
              example: 123 Main St
            city:
              type: string
              example: New York
            state:
              type: string
              example: NY
            postalCode:
              type: string
              example: '10001'
            country:
              type: string
              example: US
        withdrawal_method:
          type: string
          description: Withdrawal method
          enum:
            - domestic_wire
            - international_wire
            - ach
            - crypto_usdt
            - crypto_usdc
            - rolla_transfer
        routing_number:
          type: string
          description: 9-digit ABA routing number. Required for USD ach and domestic_wire.
          maxLength: 20
        wallet_address:
          type: string
          description: Crypto wallet address (for crypto withdrawals)
        wallet_chain:
          type: string
          description: Blockchain network (for crypto withdrawals)
          maxLength: 50
        intermediary_bank_name:
          type: string
          description: Intermediary bank name
          maxLength: 255
        intermediary_bank_routing_number:
          type: string
          description: Intermediary bank routing number
          maxLength: 50
        recipient_business_id:
          type: string
          format: uuid
          description: >-
            Required for rolla_transfer. The UUID of the destination Rolla
            business.
          example: d4e5f6a7-b8c9-0123-defa-456789012345
        account_owner_type:
          type: string
          enum:
            - individual
            - business
          description: >-
            Whether the account is held by an individual or a business. Required
            for every bank-account beneficiary (any fiat method that is not
            crypto or rolla_transfer, including NGN bank transfer,
            domestic_wire, and international_wire). Not applicable to
            crypto_usdt, crypto_usdc, or rolla_transfer. During the deprecation
            grace period, requests that omit this field still succeed but return
            a `deprecation_warning` object; after the enforcement date the
            request is rejected with a 400. See the Beneficiary Account Fields
            migration guide.
          example: business
        account_category:
          type: string
          enum:
            - checking
            - savings
          description: >-
            Whether a USD account is checking or savings. Required only when
            `currency` is USD. If you are not sure, use "checking". Subject to
            the same grace-period behaviour as account_owner_type.
          example: checking
    SavedBeneficiary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        currency:
          type: string
          example: NGN
        label:
          type: string
          example: Office rent
        account_name:
          type: string
          example: JOHN DOE
        account_number:
          type: string
          example: '0123456789'
        bank_name:
          type: string
          example: Access Bank
        bank_code:
          type: string
          example: '000014'
        bank_address:
          type: string
        swift_code:
          type: string
        email:
          type: string
          format: email
        contact_person:
          type: string
        beneficiary_address:
          type: string
        withdrawal_method:
          type: string
          enum:
            - domestic_wire
            - international_wire
            - ach
            - crypto_usdt
            - crypto_usdc
            - rolla_transfer
        routing_number:
          type: string
        wallet_address:
          type: string
        wallet_chain:
          type: string
        intermediary_bank_name:
          type: string
        intermediary_bank_routing_number:
          type: string
        recipient_business_id:
          type: string
          format: uuid
          description: >-
            Required for rolla_transfer. The UUID of the destination Rolla
            business.
        account_owner_type:
          type: string
          enum:
            - individual
            - business
          description: >-
            Whether the account is held by an individual or a business. Present
            for bank-account beneficiaries; null on legacy records that predate
            this field.
          example: business
        account_category:
          type: string
          enum:
            - checking
            - savings
          description: >-
            Whether a USD account is checking or savings. Present for USD
            beneficiaries; null on legacy records that predate this field.
          example: checking
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    Error:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Your Rolla API key

````