# MAXFI Payments API — v2.0.0

One API for cards, wallets, BNPL, payouts and KYC. Hosted-checkout-first with first-class direct-API support. Idempotent, signed webhooks, deterministic sandbox.

## Servers
- `https://maxfi-api.exezine.az` — Production (use sk_test_ keys for sandbox)

## Endpoints

### POST /v2/payments/checkout
**Create a checkout session**
Tags: `Checkout`
Operation ID: `createCheckoutSession`

### GET /v2/payments/checkout/{id}
**Get a checkout session**
Tags: `Checkout`
Operation ID: `getCheckoutSession`

### GET /checkout/{sessionId}/methods
**Effective method catalog for a hosted checkout session**
Tags: `Payment Methods`
Operation ID: `getCheckoutMethods`

Returns the list of payment methods actually enabled for this session. This is the intersection of Merchant Connector Account (MCA) allowed methods, global Connector Method Capability (CMC), and per-merchant MCS overrides. Called by the MAXFI Checkout page on load. Fail-open to card-only if the catalog lookup errors — end customers always see at least one method.

### POST /checkout/{sessionId}/submit-method
**Submit a non-card payment method (SBP, SberPay, TPay, YooMoney, Apple/Google Pay, recurrent)**
Tags: `Payment Methods`
Operation ID: `submitCheckoutMethod`

Called by the MAXFI Checkout page when the end customer picks any method other than `card`. Card payments continue to use the PCI SAQ A-EP `/checkout/:sessionId/pay` endpoint with the 2-phase 3DS flow. Response carries `next_action` telling the browser whether to render a QR code, open a deeplink, redirect, show an ACS iframe or poll. The checkout page polls `GET /checkout/:sessionId/status` until the session settles into a terminal state.

### POST /widget/v1/session
**Bootstrap a widget session and return a hosted checkout URL**
Tags: `Widget`
Operation ID: `createWidgetSession`

Called by the Widget SDK (`Maxfi` class, loaded from `/widget/v1/maxfi.js`) when the user clicks the Pay button. Creates a regular checkout session and returns its URL so the widget can embed `/checkout/:sessionId` in an iframe. Accepts `initial_method` to pre-select a tab on the checkout page — handy when the widget renders its own method picker.

### GET /widget/v1/methods
**Effective method catalog for the authenticated merchant (widget context)**
Tags: `Widget`
Operation ID: `getWidgetMethods`

Returns the same shape as `GET /checkout/:sessionId/methods` but keyed by merchant (no session required). Fail-open to card-only on any lookup error.

### GET /sbp/members
**Full list of SBP (Faster Payments System) member banks**
Tags: `Payment Methods`
Operation ID: `listSbpMembers`

Returns MAXFI's mirror of the public NSPK dictionary (qr.nspk.ru/proxyapp/c2bmembers.json). Includes every active SBP-connected bank with a 12-digit `member_id` (nspkId), localised names (en/ru/az), logo URL and iOS / Android deeplinks. Use this endpoint when you need to render your own bank picker before submitting an SBP payment, or when you want to validate a `member_id` server-side before calling MAXFI. No auth required — list is considered public information.

### GET /sbp/members/popular
**Top-N popular SBP member banks**
Tags: `Payment Methods`
Operation ID: `listSbpMembersPopular`

Curated subset of `/sbp/members` sorted by `display_order`. MAXFI Ops maintains the popular list so hosted checkout can render a compact grid (top-12 banks by SBP traffic share) instead of the full 200-bank catalogue. Returns the same entry shape as `/sbp/members`.

### GET /checkout/{sessionId}/sbp-members
**SBP member banks scoped to a hosted checkout session**
Tags: `Payment Methods`
Operation ID: `getCheckoutSbpMembers`

Same list as `/sbp/members/popular` but tied to a running checkout session. Returns an empty array and `currency_supported: false` when the session currency is not RUB (SBP is a ruble-only rail). Used by the MAXFI hosted checkout page to render the bank picker grid inside the SBP tab.

### GET /widget/v1/sbp-members
**SBP member banks for embedded Widget SDK**
Tags: `Widget`
Operation ID: `getWidgetSbpMembers`

Authenticated with your publishable key. Returns the same popular-list shape as the public `/sbp/members/popular` endpoint, cached for 5 minutes on the CDN edge.

### GET /v2/payments
**List payments**
Tags: `Payments`
Operation ID: `listPayments`

### POST /v2/payments
**Create a direct payment**
Tags: `Payments`
Operation ID: `createPayment`

### GET /v2/payments/{id}
**Get a payment**
Tags: `Payments`
Operation ID: `getPayment`

### POST /v2/payments/{id}/capture
**Capture an authorisation**
Tags: `Payments`
Operation ID: `capturePayment`

### POST /v2/payments/{id}/refund
**Refund a payment (full or partial)**
Tags: `Payments`
Operation ID: `refundPayment`

### POST /v2/payments/{id}/cancel
**Cancel an authorisation or pending payment**
Tags: `Payments`
Operation ID: `cancelPayment`

### POST /v2/payouts
**Create a payout**
Tags: `Payouts`
Operation ID: `createPayout`

### GET /v1/balance
**Get your balance**
Tags: `Balance`
Operation ID: `getBalance`

Per-currency balances of the authenticated merchant, in minor units (4900 = 49.00). `available` can be paid out, `pending` is waiting for settlement, `reserve` is the rolling reserve. An empty `balances` array means no ledger accounts yet — they are created on the first successful payment. If the ledger is temporarily unavailable the API answers **503 BALANCE_UNAVAILABLE** instead of zero balances: retry with backoff and never treat this response as an empty balance.

### GET /v1/channels
**List channels**
Tags: `Channels`
Operation ID: `listChannels`

Returns all channels of the authenticated merchant. By default soft-deleted channels are excluded.

### POST /v1/channels
**Create a channel**
Tags: `Channels`
Operation ID: `createChannel`

Slug (`code`) must be unique within your merchant. Returns the new Channel including the freshly minted `public_id` and `webhook_secret` (when set).

### GET /v1/channels/{id}
**Retrieve a channel**
Tags: `Channels`
Operation ID: `getChannel`

`id` accepts the UUID, the `ch_xxx` public id, or the merchant-defined slug.

### PATCH /v1/channels/{id}
**Update a channel**
Tags: `Channels`
Operation ID: `updateChannel`

Partial update — branding, webhook URL/secret/enabled, currencies, name. The `code` of the default channel is immutable.

### DELETE /v1/channels/{id}
**Soft-delete (default) or hard-delete (?hard=true)**
Tags: `Channels`
Operation ID: `deleteChannel`

Soft-delete is reversible — the row stays in DB and `restore` brings it back. Hard-delete is blocked when MCAs / API keys / transactions still reference the channel; the response is 409 with a `references` array enumerating the blockers. The default channel cannot be deleted at all.

### POST /v1/channels/{id}/promote-default
**Make this channel the default**
Tags: `Channels`
Operation ID: `promoteChannelDefault`

Demotes the previous default channel in the same call. The new default automatically inherits any unscoped requests.

### POST /v1/channels/{id}/pause
**Pause a channel**
Tags: `Channels`
Operation ID: `pauseChannel`

Temporarily hides the channel from routing without losing any history. The default channel cannot be paused.

### POST /v1/channels/{id}/resume
**Resume a paused channel**
Tags: `Channels`
Operation ID: `resumeChannel`

### POST /v1/channels/{id}/restore
**Restore a soft-deleted channel**
Tags: `Channels`
Operation ID: `restoreChannel`

### GET /v2/health
**Service health**
Tags: `Health`
Operation ID: `health`

### GET /auth/me
**Authenticated session profile (now includes counterparty_role_codes)**
Tags: `Auth`
Operation ID: `authMe`

Returns the merchant-portal session profile. Since v3.0 the response includes `counterparty_role_codes` — the list of roles this counterparty currently holds in CRM. Merchant Portal access requires `merchant` to be in the list. During the rollout window tokens without the claim are accepted with a warning; once `MERCHANT_ROLE_STRICT=true` is set on the BFF the gate becomes hard.
