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

# Seller Quickstart: Accept Agent Payments

> Charge for a route in an Express service with the official x402 middleware, settle through Metal's facilitator, and receive a paid request

Add a route to an Express service that charges in `*USDZ`, and have it
paid by the agent from [Pay for an API](https://docs.metalntwx.com/agents/quickstart-pay.md). The
official x402 middleware answers unpaid requests with the `402` and hands
each payment to Metal's [facilitator](https://docs.metalntwx.com/agents/facilitator.md), which verifies
it, settles it and pays the gas.

## 1. Add the middleware

```bash theme={null}
npm install @metalntwx/metal-pay @x402/core @x402/evm @x402/fetch @x402/express express viem
```

Save this as `server.ts`:

```typescript theme={null}
import express from "express";
import { HTTPFacilitatorClient, x402ResourceServer } from "@x402/core/server";
import { paymentMiddleware } from "@x402/express";
import { METAL_NETWORKS, registerMetalScheme } from "@metalntwx/metal-pay";

const facilitator = new HTTPFacilitatorClient({ url: METAL_NETWORKS.testnet.facilitatorUrl });
const server = registerMetalScheme(new x402ResourceServer(facilitator), { networks: ["testnet"] });

const app = express();
app.use(
  paymentMiddleware(
    {
      "GET /quote": {
        accepts: {
          scheme: "exact",
          network: "eip155:63825",
          payTo: "<your Metal address>",
          price: "0.01",
        },
        description: "One quote, paid per request",
      },
    },
    server,
  ),
);
app.get("/quote", (_req, res) => res.json({ quote: "…" }));

app.listen(4021);
```

For Hono, `paymentMiddleware` from `@x402/hono` takes the same routes and
server. Always pass the facilitator URL: with none, `HTTPFacilitatorClient`
settles through `x402.org`, which does not serve Metal. `price` is a
dollar amount in `*USDZ`, and `payTo` any Metal address you control.
`registerMetalScheme` registers x402's `exact` scheme on Metal's networks,
so the middleware quotes and settles Metal payments.

## 2. Receive a paid request

Start the server, then pay it from a second terminal:

```bash theme={null}
npx -y tsx server.ts
```

```bash theme={null}
metal-agent pay http://127.0.0.1:4021/quote --network testnet
```

```text theme={null}
nonce <payment nonce>
status 200
payer <agent address>
payee <your Metal address>
amount 0.01 *USDZ
network eip155:63825
transaction <settlement transaction hash>
explorer https://testnet.metalntwx.com/tx/<settlement transaction hash>
header x-powered-by: Express
body {"quote":"…"}
```

For an `exact` payment the middleware verifies it, runs your handler, then
settles, and the paid response carries the transaction hash in
`PAYMENT-RESPONSE`. A refused payment gets a `402` naming the
[reason](https://docs.metalntwx.com/agents/facilitator.md#refusal-reasons).

> [!WARNING]
>
> A handler that returns a status of `400` or above cancels the payment;
> nothing moves on chain. An `exact` payment refused at settlement, for
> example because the payer's balance or mandate limit was spent in the
> meantime, leaves the handler's work unpaid, so a handler that spends
> irreversibly should do it after settlement. `server.onSettleFailure`
> reports a failed settlement. A [clearing](https://docs.metalntwx.com/agents/clearing.md) payment is
> not cancelled: it settles before the handler runs, so the payer is
> charged whatever the handler returns and you owe the delivery.

To hand something out once per payment, do it when the settle answer says
this request was the first to claim it:

```typescript theme={null}
server.onAfterSettle(async ({ result }) => {
  const settlement = result.extra?.settlement as { id: string; first: boolean } | undefined;
  if (result.success && settlement?.first) {
    // Deliver, keyed by settlement.id.
  }
});
```

If a settle answer is lost, the facilitator's
[`/settlements`](https://docs.metalntwx.com/agents/facilitator#get-settlements) lists what settled to
your address.

A payment proves the agent paid you, not that it agreed to this order at
this price. Where a dispute could turn on that, you can require the agent's
signature over the order itself; see
[require a signed order](https://docs.metalntwx.com/agents/require-signed-order.md). To charge per call
without a transaction each time, see [clearing](https://docs.metalntwx.com/agents/clearing.md).

> [card] [Require a signed order](https://docs.metalntwx.com/agents/require-signed-order.md)
>
> A second signature over the order, as proof of what the agent agreed to buy.

> [card] [Facilitator](https://docs.metalntwx.com/agents/facilitator.md)
>
> Endpoints, limits, refusal reasons and retries.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.