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

# Payments

> One Payments product with three modes and two integration methods.

Hypermid has one Payments product with three modes. Choose the mode by where
the money is going; choose the integration method by whether you can keep a
secret on a server.

> **Register the price server-side whenever you are charging one — via your backend (`sk_`) or a
> payment link. Use the publishable key only when the destination is one the payer has proven they
> own, or one you have registered (backend or dashboard).**

## Start with the money

| Mode           | Money flows                                   | Typical use                              |
| -------------- | --------------------------------------------- | ---------------------------------------- |
| **Checkout**   | customer → merchant                           | selling something at a fixed price       |
| **Deposit**    | customer → customer's own account in your app | funding a balance or topping up a wallet |
| **Withdrawal** | merchant → customer                           | paying a user out                        |

These are payment sessions with the same lifecycle and reads. The mode is a
business decision, not an integration setting.

## One fee rule for all three modes

Checkout, Deposit, and Withdrawal resolve the same two fees on the same payer
input: Hypermid's fee plus an optional developer fee. A partner-specific
Hypermid override replaces the global rate outright. The developer fee defaults
to 0, is limited to 0–100 basis points, and requires a configured recipient
when it is positive.

The quote's `feeBreakdown` reports `hypermidBps`, `partnerBps`, and their
`totalBps`. A same-token EVM transfer is the explicit zero fee exception: a
plain transfer has no fee-taking route. On the Near deposit-address rail, the
provider keeps half of each declared app fee, so it sees twice each net leg.
EVM developer earnings are held by Hypermid and settled periodically by manual
transfer; Near-rail developer earnings are paid directly by the provider.

## Then choose how to integrate

|                | Method 1: `sk_` on a server                                 | Method 2: `pk_` in the browser                                                                                                       |
| -------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Checkout**   | Supported — [server-created Checkout](/guides/checkout)     | Not supported. For no-backend fixed prices, use [payment links](/guides/payment-links).                                              |
| **Deposit**    | Supported — [server-created Deposit](/guides/deposit)       | Available when you configure an origin and Hypermid enables the partner — see [publishable-key reference](/sdk/publishable-deposit). |
| **Withdrawal** | Supported — [server-created Withdrawal](/guides/withdrawal) | Not supported                                                                                                                        |

Method 1 gives you full control over all three modes. It needs a backend that
can keep the secret key. Method 2 needs no merchant backend for its
`candidateId` path, but it needs origin configuration and a
server-authored destination-binding artifact. It cannot create Checkout or
Withdrawal.

Most readers in the last column should start there only if they are funding a
user's balance and the publishable Deposit capability has been enabled. A
payment link is the no-backend path for a fixed-price Checkout.

<Warning>
  Method 2 is available in production when you configure an allowed origin for
  the publishable key and Hypermid enables publishable Deposits for the partner.
  The key-creation flow requires at least one origin, so a new key does not hit
  `403 ORIGIN_NOT_CONFIGURED`; that error is for a legacy key with no origins.
  After the origin is configured, a partner that Hypermid has not enabled
  receives `403 PUBLISHABLE_DEPOSIT_NOT_ENABLED`. Configure the origin yourself
  when creating the key, then ask Hypermid to enable the partner. The path fails
  closed until both conditions hold.
</Warning>

## A short decision path

1. Are you **selling something**? Choose Checkout. If you have no backend,
   choose a [payment link](/guides/payment-links) immediately.
2. Are you **funding a user's own balance**? Choose Deposit.
3. Are you **paying a user out**? Choose Withdrawal.
4. Can you keep a secret on a server? Use Method 1 for any mode. If not, the
   only Method 2 choice is Deposit. You configure the key's origin; ask
   Hypermid to enable the partner. Its `candidateId` path needs no payer
   signature and no merchant backend at runtime.

## Method 1: server-created sessions

The server supplies the session's destination, amount and mode using the
secret key. The browser renders the returned session, while the server remains
the authority for fulfilment.

### Checkout

```mermaid theme={"system"}
sequenceDiagram
  participant M as Merchant server
  participant P as Payer browser
  participant H as Hypermid
  participant C as Chain
  M->>H: POST /v1/payments/checkout with sk_
  Note over M,H: Server supplies fixed amount and merchant-controlled destination
  H-->>M: Payment session URL and id
  M->>P: Redirect or embed the session
  P->>H: Open session and choose a payment route
  P->>C: Sign and broadcast payment
  C-->>H: On-chain confirmation
  H-->>M: Signed webhook prompt
  M->>H: Read session status
  H-->>M: Confirmed session, if settlement is verified
```

See the [Checkout guide](/guides/checkout) and the
[`@hypermid/sdk` Payments reference](/sdk/payments).

### Deposit

```mermaid theme={"system"}
sequenceDiagram
  participant M as Merchant server
  participant P as Payer browser
  participant H as Hypermid
  participant C as Chain
  M->>H: POST /v1/payments/deposit with sk_
  Note over M,H: Server supplies the managed recipient or server-authored candidates
  H-->>M: Payment session URL and id
  M->>P: Redirect or embed the session
  P->>H: Choose an amount and payment route
  P->>C: Sign and broadcast payment
  C-->>H: On-chain confirmation
  H-->>M: Signed webhook prompt
  M->>H: Read session status
  H-->>M: Confirmed deposit, if settlement is verified
```

See the [Deposit guide](/guides/deposit).

### Withdrawal

```mermaid theme={"system"}
sequenceDiagram
  participant M as Merchant server
  participant P as Payer browser
  participant H as Hypermid
  participant C as Chain
  M->>H: POST /v1/payments/withdrawal with sk_
  Note over M,H: Server supplies the per-session recipient and amount
  H-->>M: Payment session URL and id
  M->>P: Send the session to the payer
  P->>H: Open the withdrawal session
  P->>C: Connected source wallet signs and broadcasts
  C-->>H: On-chain confirmation
  H-->>M: Signed webhook prompt
  M->>H: Read session status and recipient
  H-->>M: Confirmed withdrawal, if settlement is verified
```

See the [Withdrawal guide](/guides/withdrawal).

## Method 2: publishable-key Deposit

This method is browser-facing and accepts a `pk_` key. The browser never names
an arbitrary destination. It presents exactly one artifact, and Hypermid
resolves the destination from that artifact:

* **`candidateId`** — an opaque, server-authored destination candidate. It
  needs no payer signature and no merchant backend at runtime.
* **`challenge`** — a payer signature over a server-issued SIWE message. It is
  EVM-only.
* **`grant`** — a single-use JWS minted by your server. This is **not a no-backend path**, even though
  creation is submitted from the browser.

The browser calls `createPublishableDeposit`; the exact request union and
branchable errors are in the [publishable-key SDK reference](/sdk/publishable-deposit).

```mermaid theme={"system"}
sequenceDiagram
  participant M as Merchant server
  participant P as Payer browser
  participant H as Hypermid
  participant C as Chain
  alt candidateId
    P->>H: POST publishable Deposit with pk_ and candidateId
    Note over H: Resolve the server-authored candidate destination
  else SIWE challenge
    P->>H: Request challenge for the payer address
    H-->>P: Challenge message
    P->>P: Payer signs the message
    P->>H: POST publishable Deposit with pk_ and proof
    Note over H: Verify proof and bind the proven destination
  else grant
    M->>H: Mint a single-use destination grant
    M-->>P: Pass the grant to the browser
    P->>H: POST publishable Deposit with pk_ and grant
    Note over H: Consume the server-minted grant and bind its destination
  end
  H-->>P: Payment session
  P->>C: Sign and broadcast payment
  C-->>H: On-chain confirmation
  Note over M,H: A session is not payment proof; use a server read or dashboard
```

The [publishable-key SDK reference](/sdk/publishable-deposit) has the exact
request types and branchable errors. It returns a session, not proof that money
arrived.

## Payment links: no-backend Checkout

Payment links are a no-backend path for fixed-price Checkout. They are not a
fourth mode and they are not Method 2: a merchant creates or manages the link
through the Dashboard or the server SDK, then shares the hosted URL.

```mermaid theme={"system"}
sequenceDiagram
  participant M as Merchant server / dashboard
  participant P as Payer browser
  participant H as Hypermid
  participant C as Chain
  M->>H: Create a fixed-price payment link
  Note over M,H: No merchant server is needed after the link is created
  M-->>P: Share /link/{id}
  P->>H: Open the link
  H-->>P: Fresh Checkout session
  P->>C: Sign and broadcast payment
  C-->>H: On-chain confirmation
  Note over M,H: Check the Dashboard or server read before fulfilling
```

Read the [payment links guide](/guides/payment-links) and the
[payment-links SDK reference](/sdk/payment-links) for the lifecycle and exact
CRUD signatures.

## Never fulfil from the browser

Never fulfil from `onSuccess`, a redirect, a session id, a requested amount, or
a payer-claimed transaction hash. Use a **signed webhook** as a prompt and a
**server-side status read** as the authority. A no-backend merchant uses the
Dashboard's payment-confirmed view; an email is only a prompt to check it.

The exception states `duplicate`, `late`, and `out-of-bounds` can mean funds
moved, but none is a normal payment to fulfil automatically.

The SDK's payments.\* API sends a secret key and, when `window` exists, throws;
that runtime boundary is part of the method choice, not just a documentation
recommendation.

## What is not a promise

This is a capability boundary, not a routing statement. The publishable-key
path being gated says nothing about which chains Hypermid can route for a
server-created session. The rule remains: *any wallet provider works on chains where Hypermid supports that wallet's signing standard.*
