# QuickStart

This quickstart walks through two tiny programs: a paid Express API, and a client that pays to call it. Both run against `sui-testnet` so no real funds are involved.

### 1. Prerequisites

* Node.js 20+
* Two Sui addresses —  one for the server (receives payment), one for the client (sends payment).
* Both addresses funded with testnet SUI (for gas) and testnet USDC from the [Sui faucet](https://docs.sui.io/guides/developer/getting-started/get-coins).
* A Facilitator URL. For this quickstart we'll assume `https://facilitator.blockpay.gg`

### 2. Server: charge for `/weather`

Create a new project and install the server packages:

```bash
mkdir blockpay-demo-server && cd blockpay-demo-server
npm init -y
npm i express @blockpay402/express dotenv
```

Create `.env`:

```
BLOCKPAY_FACILITATOR_URL=https://facilitator.blockpay.gg
BLOCKPAY_NETWORK=sui-testnet
BLOCKPAY_RECEIVE_ADDRESS=0x<your-server-address>
```

Create `server.ts`:

```ts
import "dotenv/config";
import express from "express";
import { paymentMiddleware } from "@blockpay402/express";

const app = express();

app.use(
  paymentMiddleware({
    facilitatorUrl: process.env.BLOCKPAY_FACILITATOR_URL!,
    network: "sui-testnet",
    payTo: process.env.BLOCKPAY_RECEIVE_ADDRESS! as `0x${string}`,
    routes: {
      "GET /weather": {
        price: { amount: "1000", asset: "USDC" }, // 0.001 USDC
        description: "Current weather for a given city",
      },
    },
  }),
);

app.get("/weather", (req, res) => {
  res.json({ city: req.query.city ?? "Newyork", tempC: 31 });
});

app.listen(3000, () => console.log("listening on :3000"));
```

Run it:

```bash
npx tsx server.ts
```

A plain `curl` without payment returns `402`:

```bash
curl -i http://localhost:3000/weather?city=Newyork
# HTTP/1.1 402 Payment Required
# { "x402Version": 1, "accepts": [ { "scheme": "sui-exact", ... } ] }
```

### 3. Client: pay for `/weather`

In a second project:

```bash
mkdir blockpay-demo-client && cd blockpay-demo-client
npm init -y
npm i @blockpay402/client dotenv
```

`.env`:

```
BLOCKPAY_FACILITATOR_URL=https://facilitator.blockpay.gg
BLOCKPAY_NETWORK=sui-testnet
BLOCKPAY_PRIVATE_KEY=suiprivkey1<your-client-key>
```

`client.ts`:

```ts
import "dotenv/config";
import { createPayingFetch } from "@blockpay402/client";

const fetchWithPay = createPayingFetch({
  network: "sui-testnet",
  privateKey: process.env.BLOCKPAY_PRIVATE_KEY!,
  maxPerRequest: { amount: "5000", asset: "USDC" }, // cap each call at 0.005 USDC
});

const res = await fetchWithPay("http://localhost:3000/weather?city=Newyork");
console.log(res.status, await res.json());
console.log("tx:", res.headers.get("X-PAYMENT-RESPONSE"));
```

Run:

```bash
npx tsx client.ts
# 200 { city: 'Newyork', tempC: 31 }
# tx: eyJ0eERpZ2VzdCI6IjB4...
```

`createPayingFetch` transparently handled the `402`, signed a payment, retried, and surfaced the on-chain transaction digest in `X-PAYMENT-RESPONSE`.

### 4. What just happened

1. The client made a plain `GET /weather` request.
2. The server's middleware saw no `X-PAYMENT` header, responded with `402` and `PaymentRequirements` for `0.001` USDC on `sui-testnet`.
3. The client read the requirements, signed a `sui-exact` payload with its Sui key, and retried with the payload in the `X-PAYMENT` header.
4. The middleware called the Facilitator's `/verify` endpoint, got `isValid: true`, and ran the handler.
5. After the handler returned, the middleware called `/settle`, which broadcast a PTB on Sui moving `1000` USDC units from client to server and emitting a receipt.
6. The response went back to the client with the transaction digest in `X-PAYMENT-RESPONSE`.

### 5. Next steps

* Replace `sui-testnet` with `sui-mainnet` only after you have tested thoroughly and read the Disclaimer.
* If you are building an AI agent rather than a simple script, look at `@blockpay402/agent` for budget controls.
* If you want to operate your own verification and settlement infrastructure, see the [Facilitator SDK](/integration/faciliator-sdk.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.blockpay.gg/integration/quickstart.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
