# Payment methods & capabilities

`GET /payments-api/v1/payment-methods` is the first call a server integration should make.
It returns the exact set of instruments, currencies, and payment rails your seller account
has been configured for — the intersection of your account settings and what the active
terminals support. Use this response to drive your checkout UI rather than hard-coding
assumptions.

## Request

| Aspect | Value |
|--------|-------|
| Method | `GET` |
| Path | `/payments-api/v1/payment-methods` |
| Auth | `Authorization: Bearer <token>` |
| Body | None |
| Query params | None |

No `Idempotency-Key` is required — this is a read-only endpoint.

#### curl

```bash
curl -sS "$FYNEX_API/payments-api/v1/payment-methods" \
  -H "Authorization: Bearer $FYNEX_TOKEN"
```

#### JavaScript

```js
export async function getPaymentMethods() {
  const res = await fetch(
    `${process.env.FYNEX_API}/payments-api/v1/payment-methods`,
    {
      headers: {
        Authorization: `Bearer ${process.env.FYNEX_TOKEN}`,
      },
    }
  );
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}
```

#### Python

```python
import os
import requests

def get_payment_methods() -> dict:
    res = requests.get(
        f"{os.environ['FYNEX_API']}/payments-api/v1/payment-methods",
        headers={"Authorization": f"Bearer {os.environ['FYNEX_TOKEN']}"},
        timeout=10,
    )
    res.raise_for_status()
    return res.json()
```

## Response

**`200 OK`** — returns `dtos.PaymentMethodsResponse`:

```json
{
  "sellerAccountId": 42,
  "allowedPaymentMethods": ["card", "google_pay", "apple_pay"],
  "allowedCurrencies": ["GBP", "EUR"],
  "allowedPaymentRails": ["card"]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `sellerAccountId` | `integer` | The numeric ID of the authenticated seller account. |
| `allowedPaymentMethods` | `string[]` | Payment instruments enabled for this account. See [Payment instruments](#payment-instruments) below. |
| `allowedCurrencies` | `string[]` | ISO 4217 currency codes supported by this account. See [Currencies](#currencies) below. |
| `allowedPaymentRails` | `string[]` | Active payment rails. Omitted (`omitempty`) when no rails are configured. See [Payment rails](#payment-rails) below. |

## Enum values

### Payment instruments

Values from `model.PaymentInstrumentType`:

| Value | Description |
|-------|-------------|
| `card` | Standard card payment (Visa, Mastercard, Amex, etc.) |
| `bank_account` | Bank account / direct debit |
| `google_pay` | Google Pay (tokenised card via Google's wallet) |
| `apple_pay` | Apple Pay (tokenised card via Apple's wallet) |
| `bancontact` | Bancontact (Belgian local scheme, `apm` rail) |
| `multibanco` | Multibanco (Portuguese reference/voucher payment, `apm` rail) |
| `mbway` | MB WAY (Portuguese mobile-app payment, `apm` rail) |
| `wero` | Wero (European account-to-account wallet, `apm` rail) |
| `swish` | Swish (Swedish mobile payment, `apm` rail) |

### Currencies

Values from `model.CurrencyCode`. All 3-letter ISO 4217:

| Code | Currency |
|------|----------|
| `EUR` | Euro |
| `USD` | US Dollar |
| `GBP` | British Pound |
| `DKK` | Danish Krone |
| `NOK` | Norwegian Krone |
| `SEK` | Swedish Krona |

### Payment rails

Values from `model.PaymentRailType`:

| Value | Description | Instruments |
|-------|-------------|-------------|
| `card` | Card network processing | `card`, `google_pay`, `apple_pay` |
| `bank_transfer` | Bank transfer / account-to-account | `bank_account` |
| `apm` | Alternative / local payment methods (redirect-based) | `bancontact`, `multibanco`, `mbway`, `wero`, `swish` |

The instrument-to-rail mapping is enforced by the server: a `card` rail will only accept
`card`, `google_pay`, or `apple_pay` instruments; `bank_transfer` only accepts `bank_account`;
the `apm` rail carries the local-scheme instruments (`bancontact`, `multibanco`, `mbway`,
`wero`, `swish`).

> [!NOTE]
> The `apm` instruments are **redirect-based**: accept them either server-to-server via
> `POST /initialize-payment` with `paymentType: "apm"` (follow the returned redirect action),
> or through Fynex-hosted checkout. See [Alternative payment methods
> (APM)](https://api.fynex.ai/payments-api/v2/docs#tag/alternative-payment-methods-apm) for both flows and the per-checkout
> availability rules.

## Status codes

| Status | When |
|--------|------|
| `200` | Success |
| `401` | Missing or invalid bearer token |
| `404` | Payment configuration not found for this seller account |
| `500` | Service dependency unavailable or terminal load failure |

## Using the response to drive your checkout UI

> [!NOTE]
> Always fetch payment methods at session start and render **only** what the response
> contains. Do not hard-code which instruments or currencies to show — your account
> configuration can change without a code deployment.

1. **Fetch on server startup or per-request**

   Call `GET /payment-methods` when your server starts (and cache for a short period),
   or fetch it once per checkout session before rendering the payment form.

2. **Render only enabled instruments**

   ```js
   const { allowedPaymentMethods, allowedCurrencies } = await getPaymentMethods();

   // Show card form only if enabled
   const showCard = allowedPaymentMethods.includes('card');

   // Show Google Pay button only if enabled and browser supports it
   const showGooglePay =
     allowedPaymentMethods.includes('google_pay') && await isGooglePayReady();

   // Show Apple Pay button only if enabled and browser supports it
   const showApplePay =
     allowedPaymentMethods.includes('apple_pay') && isApplePayAvailable();

   // Populate currency selector from the live list
   renderCurrencySelect(allowedCurrencies);
   ```

3. **Pass the correct instrument and rail when initializing a payment**

   When you call `POST /payments-api/v1/initialize-payment` or
   `POST /payments-api/v1/checkout`, the `paymentType` (rail) and `paymentMethod`
   (instrument) fields must be values the server already told you are allowed.
   Sending a disallowed combination returns `400 Bad Request`.

> [!CAUTION]
> `allowedPaymentRails` uses `omitempty` — it will be absent from the response if no
> rails are configured on the account. Always check for the key's presence before
> reading it; don't assume an empty array.

## See also

- **[Hosted checkout](https://api.fynex.ai/payments-api/v2/docs#tag/hosted-checkout)** — Accept payments by redirecting customers to a Fynex-hosted page.
- **[Server-to-server payments](https://api.fynex.ai/payments-api/v2/docs#tag/server-to-server)** — Collect card details in your own UI and call the API directly.
