# Example

Patterns for common integrations. Each example assumes you've worked through the Quickstart and have a Facilitator URL plus funded wallets on `sui-testnet`.

### 1. Pay-per-call LLM proxy

A thin service that forwards requests to an upstream LLM and charges `0.005` USDC per call.

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

const app = express();
app.use(express.json());

app.use(
  paymentMiddleware({
    facilitatorUrl: process.env.BLOCKPAY_FACILITATOR_URL!,
    network: "sui-mainnet",
    payTo: process.env.BLOCKPAY_RECEIVE_ADDRESS! as `0x${string}`,
    routes: {
      "POST /complete": {
        price: { amount: "5000", asset: "USDC" },
        description: "Text completion",
        maxTimeoutSeconds: 60,
      },
    },
  }),
);

app.post("/complete", async (req, res) => {
  const upstream = await fetch("https://api.llm-provider.example/v1/complete", {
    method: "POST",
    headers: {
      "content-type": "application/json",
      authorization: `Bearer ${process.env.UPSTREAM_KEY}`,
    },
    body: JSON.stringify(req.body),
  });
  const data = await upstream.json();
  res.json(data);
});

app.listen(3000);
```

The middleware settles after the handler returns, so a failing upstream call does not charge the caller.

### 2. Per-dataset download, price list published in `accepts`

An endpoint that serves one of many datasets, each priced differently:

```ts
"GET /datasets/:id": {
  price: (req) => {
    const d = DATASETS[req.params.id];
    if (!d) return null; // signals "no price → pass through / 404"
    return { amount: d.priceCents * 100, asset: "USDC" };
  },
  description: (req) => `Dataset ${req.params.id}`,
},
```

The `price` and `description` fields accept a function of the request, letting you dispatch on path params or query strings.

### 3. AI agent with budget and human-in-the-loop approval

```ts
import { createAgentWallet } from "@blockpay402/agent";

const wallet = createAgentWallet({
  network: "sui-mainnet",
  privateKey: process.env.AGENT_KEY!,
  budgets: {
    perRequest: { amount: "50000", asset: "USDC" },     // 0.05 USDC per call
    perDay:     { amount: "2000000", asset: "USDC" },   // 2 USDC/day
  },
  softThreshold: { amount: "10000", asset: "USDC" },    // >0.01 USDC → ask
  approve: async ({ amount, asset, payTo, resource }) => {
    return askUser(`Pay ${amount} of ${asset} to ${payTo} for ${resource}?`);
  },
  onSettled: (record) => auditLog.append(record),
});

// Your agent loop
while (hasWork()) {
  const task = nextTask();
  const res = await wallet.fetch(task.url, { method: "POST", body: task.body });
  // ...
}
```

Hard budgets are enforced in the SDK and cannot be overridden by the model.

### 4. Monetized MCP tool

Expose a paid tool over [MCP](https://modelcontextprotocol.io) so any MCP client (including paying agents) can call it:

```ts
import { createMcpServer } from "@some-mcp-framework/server";
import { paymentMiddleware } from "@blockpay402/server";

const mcp = createMcpServer({ /* ... */ });

mcp.tool("fetch_weather", {
  description: "Get the current weather for a city. Paid: 0.001 USDC.",
  inputSchema: { type: "object", properties: { city: { type: "string" } } },
  handler: async (input, ctx) => {
    // Wrap the tool in BlockPay middleware at the HTTP transport layer:
    const ok = await ctx.requirePayment({ amount: "1000", asset: "USDC" });
    if (!ok) throw new Error("payment required");
    return { city: input.city, tempC: 31 };
  },
});
```

An agent calling the tool with a `@blockpay402/agent` wallet will pay transparently; an agent without one will see the `402` propagated in the MCP response and can decide to acquire payment capability.

### 5. Marketplace split: platform + provider

For a marketplace that takes a cut, use two requirements in `accepts`:

```ts
"POST /ask-expert": {
  price: [
    {
      // Option A: single payment to the platform, which settles out-of-band with the expert.
      amount: "100000",
      asset: "USDC",
      payTo: PLATFORM_ADDRESS,
    },
    // Option B is reserved for when `sui-split` ships; see "Future schemes" in
    // Schemes & Networks. Until then, stick with (A) and reconcile off-chain.
  ],
},
```

When `sui-split` is available, the marketplace will be able to advertise a single atomic on-chain split so the buyer's transaction pays both parties in one PTB.

### 6. Testing with a mock Facilitator

For unit and CI tests you don't want to hit Sui at all. The SDK ships an in-memory Facilitator you can point at in tests:

```ts
import { createMockFacilitator } from "@blockpay402/facilitator/mock";

const mock = createMockFacilitator();
// `mock.url` is a locally-served HTTP URL — point both client and server at it.

const server = startServerWith({ facilitatorUrl: mock.url });
const fetch = createPayingFetch({ facilitatorUrl: mock.url, /* ... */ });

const res = await fetch(server.url + "/weather");
expect(res.status).toBe(200);
expect(mock.settlements).toHaveLength(1);
expect(mock.settlements[0].amount).toBe("1000");
```

The mock never touches Sui; it records payloads and returns synthetic transaction digests.

### 7. Reading `X-PAYMENT-RESPONSE`

Any paying client can verify settlement independently:

```ts
import { decodePaymentResponse } from "@blockpay402/client";

const res = await fetch("https://api.example.com/weather");
const header = res.headers.get("X-PAYMENT-RESPONSE");
if (header) {
  const settlement = decodePaymentResponse(header);
  console.log(settlement.transaction); // 0x... — Sui transaction digest
  // Independently confirm it on-chain via the Sui RPC of your choice
}
```

***

More examples, including full repositories, live in the `examples/` directory of the [BlockPay GitHub ](https://github.com/BlockPay402)organization. If you build something interesting, open a PR.


---

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