> ## 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.

# Checkout

> Bill a payer a fixed amount.

Create the session server-side, send the payer to the returned URL, then read
the session back when you hear about it.

```ts theme={"system"}
import { createCheckout } from "@hypermid/sdk";

const session = await createCheckout(
  {
    chain: 8453,
    token: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    amount: "10000000",
    recipient: "0xYourTreasuryAddress",
    orderId: invoice.id,
    metadata: { invoiceId: invoice.id },
    successUrl: "https://shop.example/thanks",
    cancelUrl: "https://shop.example/cart",
  },
  { secretKey: process.env.HYPERMID_SECRET_KEY! },
);

redirect(session.url!);
```

## Set up in the portal

Before creating a Checkout, an operator should:

1. Add the merchant's self-custody payout address in **Payout addresses** and
   complete the emailed verification-code step. Checkout destinations are
   allowlisted because they receive merchant funds; an exchange deposit address
   cannot be used.
2. Keep the `sk_` key in the server's secret store. Checkout creation is a
   server operation, not a browser operation.
3. Create a small test Checkout, open its returned URL, and confirm the session
   reaches `completed` from a server-side read before fulfilling anything.

Payer choices and the publishable-key customer-wallet path do not configure a
Checkout. For a no-backend fixed-price flow, use a payment link instead.

See [Payments](/guides/payments) for the method comparison and Checkout flow.
For the no-backend path, use the [payment links guide](/guides/payment-links);
the [payment-links SDK reference](/sdk/payment-links) documents the server-side
CRUD signatures.

## What the payer sees

They choose any token they hold on any supported chain. You still receive
exactly `token` on `chain` — the swap and any bridge happen on our side.

<Warning>
  For a checkout, `recipient` must be on your **payout allowlist** — a checkout
  pays the merchant, so the destination is not payer-owned. An un-allowlisted
  address is refused at creation with `403 RECIPIENT_NOT_ALLOWLISTED`; add it in
  the partner portal first.
</Warning>

## Fees

`GET /v1/payments/fee-config` returns two fee legs: Hypermid's fee and your
optional developer fee. The developer fee defaults to 0, is limited to 0–100
basis points, and is added to Hypermid's fee on the same payer-input amount. A
partner-specific Hypermid override replaces the global rate; it is never added
to or clamped by that global.

The figure quoted for the session is snapshotted, so a later config change never
retroactively alters a payment already opened. A same-token EVM transfer quotes
a zero fee because a plain transfer cannot collect one. On EVM routes your
developer earnings are held by Hypermid and settled periodically by manual
transfer; on the Near deposit-address rail they are paid directly by the
provider, which keeps half of every declared app fee.

## Reading the result

```ts theme={"system"}
import { getPayment } from "@hypermid/sdk";

const s = await getPayment(session.id, { secretKey: process.env.HYPERMID_SECRET_KEY! });
if (s.status === "completed") fulfil(invoice);
```

<Warning>
  Release goods on the **session read**, not on the webhook body. A webhook tells
  you when to look; the read tells you what is true.
</Warning>
