# Payout Methods

A **payout method** is a bank account or virtual IBAN registered as a destination for a specific payee. When you request a payout, you target a payout method — it tells Fynex where to send the money.

> [!NOTE]
> Payout methods are **bank accounts only** (`type: bank_account`). Card destinations are not supported. IBAN methods in EUR, GBP, and USD are executable through the current banking-provider mapping. GBP `uk_local` methods are executable through Faster Payments. US-local and SWIFT formats can be onboarded and approved, but execution is blocked before funds are held until their mappings are enabled.

Payout methods have two API surfaces:

| Surface | Auth | Operations |
|---------|------|------------|
| REST `/payments-api/v1/payees/{payee_id}/payout-methods[/{method_id}]` | Bearer token | Full CRUD: list, create, update, delete |
| GraphQL `/dashboard/graphql` | `dashboard_session` cookie | Full CRUD: create, update, delete |

> [!NOTE]
> Integrators with a Bearer token have full REST CRUD over payout methods. `update` and `delete` operate on a single method at `…/payout-methods/{method_id}`; the method must belong to the payee in the path and to your seller account.

---

## Prerequisite ordering

1. **Create a payee** — a payout method must be attached to an existing payee. See [Payees](https://api.fynex.ai/payments-api/v2/docs#tag/payees).

2. **Create a payout method** on that payee — supply the bank account details documented below.

3. **Request a payout** — pass the `payoutMethodId` and a `payeeId` when calling `POST /payments-api/v1/payouts`. See [Payouts](https://api.fynex.ai/payments-api/v2/docs#tag/payouts).

> [!NOTE]
> `payee_id` in the REST path is the **numeric integer ID** returned by `createPayee` or from the payee list — not a UUID or string.

---

## Payout method fields (from `schema.graphql`)

### `type PayoutMethod`

| Field | Type | Description |
|-------|------|-------------|
| `id` | `Int!` | Numeric payout method ID — pass this as `payoutMethodId` when creating a payout |
| `payeeId` | `Int!` | ID of the payee this method belongs to |
| `type` | `String!` | Account type identifier. The only value the platform uses is `bank_account` (the default). Card destinations are not supported. |
| `bankAccountType` | `String!` | Destination identifier format: `iban`, `uk_local`, `us_local`, or `swift`. Fynex selects the eventual payout rail; clients do not select it. |
| `currency` | `String!` | Three-letter ISO 4217 currency code (e.g. `EUR`, `GBP`) |
| `bankCountry` | `String` | Two-letter ISO country code for the destination bank. |
| `iban` | `String` | IBAN for SEPA / SWIFT destinations |
| `bic` | `String` | BIC / SWIFT code |
| `accountNumber` | `String` | Account number for domestic rails (eight digits for UK Faster Payments) |
| `sortCode` | `String` | Six-digit sort code for UK Faster Payments |
| `routingNumber` | `String` | ABA routing number for US local accounts. |
| `bankName` | `String` | Bank name for reference |
| `accountName` | `String` | Account holder name |
| `status` | `String!` | Account status (e.g. `active`) |
| `createdAt` | `Time!` | Creation timestamp |
| `updatedAt` | `Time!` | Last update timestamp |

---

## REST — List payout methods for a payee

**Auth: Bearer token** (`Authorization: Bearer <token>`)

```
GET /payments-api/v1/payees/{payee_id}/payout-methods
```

Returns a list of active payout methods for the specified payee. Use this before creating a payout to confirm that a method exists and to retrieve its `id`.

#### curl

```bash
curl -sS "https://api.fynex.ai/payments-api/v1/payees/7/payout-methods" \
  -H "Authorization: Bearer $FYNEX_TOKEN"
```

#### JavaScript

```js
const payeeId = 7;
const res = await fetch(
  `${process.env.FYNEX_API}/payees/${payeeId}/payout-methods`,
  {
    headers: { Authorization: `Bearer ${process.env.FYNEX_TOKEN}` },
  }
);
const data = await res.json();
console.log(data); // { items: [...], totalCount: N }
```

#### Python

```python
import os, requests

payee_id = 7
res = requests.get(
    f"{os.environ['FYNEX_API']}/payees/{payee_id}/payout-methods",
    headers={"Authorization": f"Bearer {os.environ['FYNEX_TOKEN']}"},
)
res.raise_for_status()
print(res.json())
```

---

## REST — Create a payout method for a payee

**Auth: Bearer token** (`Authorization: Bearer <token>`)

```
POST /payments-api/v1/payees/{payee_id}/payout-methods
```

Registers a new payout destination for the payee. The owning payee is taken from the path and pinned to your seller account, so `payeeId` is **not** accepted in the body. Only `bank_account` methods are supported. `bankAccountType` describes the supplied account identifiers; Fynex selects the rail. IBAN destinations can be used for EUR, GBP, and USD payouts. GBP `uk_local` destinations use Faster Payments. US-local and SWIFT formats can be saved and reviewed but payout execution is rejected before funds are held until their provider mappings are enabled.

Returns `201 Created` with the payout method. A payee that does not exist, or belongs to another seller, returns `404`.

### Request body fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `currency` | `String` | Yes | ISO 4217 currency code: `EUR`, `GBP`, or `USD`. |
| `type` | `String` | No | Defaults to `bank_account` (the only supported value). |
| `bankAccountType` | `String` | No | `iban` (default), `uk_local`, `us_local`, or `swift`. |
| `bankCountry` | `String` | Conditional | Required for local and SWIFT formats. Use `GB` for `uk_local` and `US` for `us_local`. |
| `iban` | `String` | Conditional | Required when `bankAccountType` is `iban`; optional account identifier for `swift`. |
| `bic` | `String` | No | BIC / SWIFT code. |
| `accountNumber` | `String` | No | Account number for domestic rails; exactly eight digits for `uk_local`. |
| `sortCode` | `String` | No | Sort code for UK Faster Payments; exactly six digits after spaces/hyphens are removed. |
| `routingNumber` | `String` | No | Nine-digit ABA routing number for `us_local`. |
| `bankName` | `String` | No | Bank name for reference. |
| `accountName` | `String` | No | Account holder name. |

#### curl

```bash
curl -sS -X POST "https://api.fynex.ai/payments-api/v1/payees/7/payout-methods" \
  -H "Authorization: Bearer $FYNEX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "EUR",
    "bankAccountType": "iban",
    "iban": "DE89370400440532013000",
    "bic": "DEUTDEFF",
    "accountName": "Acme Supplies Ltd"
  }'
```

---

## REST — Update a payout method

**Auth: Bearer token** (`Authorization: Bearer <token>`)

```
PATCH /payments-api/v1/payees/{payee_id}/payout-methods/{method_id}
```

Updates only the fields present in the body; omitted fields are left unchanged. `currency` cannot be changed (it is fixed at creation). The method must belong to the payee in the path and to your seller account, otherwise `404`. Set `status` to `inactive` to retire a method (it is then excluded from the list and can no longer be used for new payouts) or `active` to restore it.

### Request body fields (all optional)

| Field | Type | Description |
|-------|------|-------------|
| `bankAccountType` | `String` | New destination identifier format. |
| `bankCountry` | `String` | New two-letter bank country. |
| `iban` | `String` | New IBAN. |
| `bic` | `String` | New BIC. |
| `accountNumber` | `String` | New account number. |
| `sortCode` | `String` | New sort code. |
| `routingNumber` | `String` | New ABA routing number. |
| `bankName` | `String` | New bank name. |
| `accountName` | `String` | New account holder name. |
| `status` | `String` | `active` or `inactive`. |

#### curl

```bash
curl -sS -X PATCH "https://api.fynex.ai/payments-api/v1/payees/7/payout-methods/501" \
  -H "Authorization: Bearer $FYNEX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "accountName": "Acme Supplies Ltd" }'
```

---

## REST — Delete a payout method

**Auth: Bearer token** (`Authorization: Bearer <token>`)

```
DELETE /payments-api/v1/payees/{payee_id}/payout-methods/{method_id}
```

Deletes a payout method your seller account owns. The method must belong to the payee in the path, otherwise `404`. Returns `{ "deleted": true }`.

#### curl

```bash
curl -sS -X DELETE "https://api.fynex.ai/payments-api/v1/payees/7/payout-methods/501" \
  -H "Authorization: Bearer $FYNEX_TOKEN"
```

---

## GraphQL — Full CRUD

**Auth: `dashboard_session` cookie** — see [GraphQL Authentication](https://api.fynex.ai/payments-api/v2/docs#tag/graphql-auth) for the login flow.

| Operation | Type | Permission |
|-----------|------|------------|
| `payoutMethods(payeeId, limit, offset)` | Query | `PAYOUTMETHODS_READ` |
| `payoutMethod(id: Int!)` | Query | `PAYOUTMETHODS_READ` |
| `createPayoutMethod(input: CreatePayoutMethodInput!)` | Mutation | `PAYOUTMETHODS_CREATE` |
| `updatePayoutMethod(id: Int!, input: UpdatePayoutMethodInput!)` | Mutation | `PAYOUTMETHODS_UPDATE` |
| `deletePayoutMethod(id: Int!)` | Mutation | `PAYOUTMETHODS_DELETE` |

### `CreatePayoutMethodInput` fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `payeeId` | `Int!` | Yes | ID of the payee to attach this method to |
| `currency` | `String!` | Yes | ISO 4217 currency code: `EUR`, `GBP`, or `USD`. |
| `type` | `String` | No | Account type. Defaults to `bank_account`, the only value the platform uses — it does not affect routing. |
| `bankAccountType` | `String` | No | Destination identifier format: `iban` (default), `uk_local`, `us_local`, or `swift`. |
| `bankCountry` | `String` | Conditional | Required for local and SWIFT formats. |
| `iban` | `String` | Conditional | Required for `iban`; may identify a `swift` destination instead of `accountNumber`. |
| `bic` | `String` | No | BIC/SWIFT code |
| `accountNumber` | `String` | No | Account number — required for domestic rails |
| `sortCode` | `String` | No | Six-digit sort code — required for UK Faster Payments |
| `routingNumber` | `String` | No | Nine-digit ABA routing number — required for `us_local`. |
| `bankName` | `String` | No | Bank name |
| `accountName` | `String` | No | Account holder name |

### `UpdatePayoutMethodInput` fields

All fields are optional. Supply only the fields you want to change.

| Field | Type | Description |
|-------|------|-------------|
| `bankAccountType` | `String` | New destination identifier format |
| `bankCountry` | `String` | New two-letter bank country |
| `iban` | `String` | New IBAN |
| `bic` | `String` | New BIC |
| `accountNumber` | `String` | New account number |
| `sortCode` | `String` | New sort code |
| `routingNumber` | `String` | New ABA routing number |
| `bankName` | `String` | New bank name |
| `accountName` | `String` | New account holder name |
| `status` | `String` | Update status (e.g. set to `inactive`) |

---

## Create a payout method — code samples

#### curl

```bash
# Step 1 — login and save the cookie
curl -sc cookies.txt \
  -X POST https://api.fynex.ai/api/v1/login/dashboard \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "your_password"}'

# Step 2 — create the payout method (IBAN example)
curl -b cookies.txt \
  -X POST https://api.fynex.ai/dashboard/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation CreatePayoutMethod($input: CreatePayoutMethodInput!) { createPayoutMethod(input: $input) { id payeeId currency iban isDefault status } }",
    "variables": {
      "input": {
        "payeeId": 7,
        "currency": "EUR",
        "type": "bank_account",
        "iban": "DE89370400440532013000",
        "bic": "COBADEFFXXX",
        "bankName": "Commerzbank AG",
        "accountName": "Acme Supplies Limited"
      }
    }
  }'
```

#### JavaScript

```js
const BASE = 'https://api.fynex.ai';

// Assumes login was already called and the dashboard_session cookie is present
async function createPayoutMethod(input) {
  const res = await fetch(`${BASE}/dashboard/graphql`, {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: `
        mutation CreatePayoutMethod($input: CreatePayoutMethodInput!) {
          createPayoutMethod(input: $input) {
            id
            payeeId
            currency
            iban
            isDefault
            status
          }
        }
      `,
      variables: { input },
    }),
  });
  const { data, errors } = await res.json();
  if (errors?.length) throw new Error(errors[0].message);
  return data.createPayoutMethod;
}

const method = await createPayoutMethod({
  payeeId: 7,
  currency: 'EUR',
  type: 'bank_account',
  iban: 'DE89370400440532013000',
  bic: 'COBADEFFXXX',
  bankName: 'Commerzbank AG',
  accountName: 'Acme Supplies Limited',
});
console.log(method);
// { id: 3, payeeId: 7, currency: 'EUR', iban: 'DE89370400440532013000', isDefault: true, status: 'active' }
```

#### Python

```python
import requests

BASE = "https://api.fynex.ai"
session = requests.Session()

# Login first
session.post(
    f"{BASE}/api/v1/login/dashboard",
    json={"email": "you@example.com", "password": "your_password"},
).raise_for_status()

mutation = """
  mutation CreatePayoutMethod($input: CreatePayoutMethodInput!) {
    createPayoutMethod(input: $input) {
      id
      payeeId
      currency
      iban
      isDefault
      status
    }
  }
"""
variables = {
    "input": {
        "payeeId": 7,
        "currency": "EUR",
        "type": "bank_account",
        "iban": "DE89370400440532013000",
        "bic": "COBADEFFXXX",
        "bankName": "Commerzbank AG",
        "accountName": "Acme Supplies Limited",
    }
}
resp = session.post(
    f"{BASE}/dashboard/graphql",
    json={"query": mutation, "variables": variables},
)
resp.raise_for_status()
body = resp.json()
if "errors" in body:
    raise RuntimeError(body["errors"][0]["message"])
print(body["data"]["createPayoutMethod"])
```

---

## Other operations

### Update a payout method

```graphql
mutation UpdatePayoutMethod($id: Int!, $input: UpdatePayoutMethodInput!) {
  updatePayoutMethod(id: $id, input: $input) {
    id
    iban
    bic
    isDefault
    status
    updatedAt
  }
}
```

### Delete a payout method

```graphql
mutation DeletePayoutMethod($id: Int!) {
  deletePayoutMethod(id: $id)
}
```

Returns `true` on success. You cannot delete a method that is currently referenced by a pending payout — cancel or complete the payout first.

### List payout methods via GraphQL

```graphql
query ListPayoutMethods($payeeId: Int!, $limit: Int, $offset: Int) {
  payoutMethods(payeeId: $payeeId, limit: $limit, offset: $offset) {
    items {
      id
      currency
      type
      iban
      accountNumber
      isDefault
      status
    }
    totalCount
  }
}
```

---

## Common pitfalls

| Pitfall | Resolution |
|---------|------------|
| `payee_id` treated as UUID | The `payee_id` path parameter is a **numeric integer** from the `Payee.id` field. |
| Creating a method before the payee exists | `createPayoutMethod` requires a valid `payeeId`. Create the payee first (see [Payees](https://api.fynex.ai/payments-api/v2/docs#tag/payees)). |
| Required identifiers missing | For `iban`, provide `iban`; for `uk_local`, provide a GBP account with `GB`, account number, and sort code; for `us_local`, provide a USD account with `US`, account number, and ABA routing number; for `swift`, provide bank country, BIC, and either account number or IBAN. |
| US-local or SWIFT method selected for payout | These formats can be onboarded and approved, but execution is not enabled yet. Fynex rejects the payout before funds are held. GBP `uk_local` methods are enabled through Faster Payments. |
| Using Bearer auth on `/dashboard/graphql` | The GraphQL endpoint only accepts the `dashboard_session` cookie. Bearer tokens are for the REST surface only. |

## See also

- **[GraphQL Authentication](https://api.fynex.ai/payments-api/v2/docs#tag/graphql-auth)** — Obtain a dashboard_session cookie before calling any GraphQL mutation.
- **[Payees](https://api.fynex.ai/payments-api/v2/docs#tag/payees)** — Create and manage the payees that payout methods are attached to.
- **[Payouts](https://api.fynex.ai/payments-api/v2/docs#tag/payouts)** — Send money from a seller wallet to a payee
