npm package: @payweave/fastify
Description: Fastify plugin for PayWeave - accept per-request USD micropayments on any Fastify route.
Latest version: 0.0.3

# @payweave/fastify

Fastify plugin for PayWeave - accept per-request USD micropayments on any Fastify route.

## Install

```bash
npm install @payweave/fastify
```

## Quick Start

```typescript
import { Payweave } from '@payweave/fastify';
import Fastify from 'fastify';

const app = Fastify();
const payweave = new Payweave(
  process.env.PAYWEAVE_APP_ID!,
  process.env.PAYWEAVE_APP_SECRET!
);

app.get(
  '/api/weather',
  { preHandler: payweave.charge({ price: '0.001', description: 'Weather API' }) },
  (req, reply) => {
    reply.send({ temp: 72, unit: 'F' });
  }
);

app.listen({ port: 3000 });
```

## API

### `new Payweave(appId, appSecret, baseUrl?)`

| Parameter | Type | Description |
|-----------|------|-------------|
| `appId` | `string` | Your app key ID |
| `appSecret` | `string` | Your app secret |
| `baseUrl` | `string?` | API base URL (defaults to `https://api.payweave.app`) |

### `payweave.charge(options)`

Returns a Fastify preHandler hook `(req: FastifyRequest, reply: FastifyReply) => Promise<void>`.

| Option | Type | Description |
|--------|------|-------------|
| `price` | `string \| (req: FastifyRequest) => string \| Promise<string>` | USD price per request |
| `description` | `string?` | Human-readable description |
| `meta` | `Record<string, string>?` | API metadata for agent discovery |

> Note: Use `payweave.charge()` as a `preHandler` in Fastify's route options.

## Examples

### Static pricing

```typescript
app.get(
  '/api/search',
  { preHandler: payweave.charge({ price: '0.01' }) },
  (req, reply) => {
    reply.send({ results: [] });
  }
);
```

### Dynamic pricing

```typescript
app.post(
  '/api/generate',
  {
    preHandler: payweave.charge({
      price: (req) => {
        const body = req.body as { premium?: boolean };
        return body.premium ? '0.05' : '0.01';
      },
      description: 'Text generation',
    }),
  },
  (req, reply) => {
    reply.send({ text: 'generated content' });
  }
);
```

### Multiple preHandlers

```typescript
app.post(
  '/api/data',
  {
    preHandler: [
      authenticate,
      payweave.charge({ price: '0.01' }),
    ],
  },
  (req, reply) => {
    reply.send({ data: 'paid content' });
  }
);
```

### With metadata for agent discovery

```typescript
app.post(
  '/api/sentiment',
  {
    preHandler: payweave.charge({
      price: '0.005',
      description: 'Sentiment analysis',
      meta: {
        'method': 'POST',
        'input.content-type': 'application/json',
        'input.schema': '{"type":"object","properties":{"text":{"type":"string"}}}',
        'output.schema': '{"type":"object","properties":{"score":{"type":"number"}}}',
      },
    }),
  },
  (req, reply) => {
    reply.send({ score: 0.85 });
  }
);
```

### Multiple routes

```typescript
app.get('/api/weather', { preHandler: payweave.charge({ price: '0.001' }) }, weatherHandler);
app.get('/api/forecast', { preHandler: payweave.charge({ price: '0.005' }) }, forecastHandler);
app.post('/api/analyze', { preHandler: payweave.charge({ price: '0.01' }) }, analyzeHandler);
```

## How It Works

1. A request hits your route without a payment header
2. The preHandler responds with `402 Payment Required` and pricing info
3. The agent submits payment on Tempo and retries with `Authorization: Payment <credential>`
4. PayWeave verifies the payment and sets a `Payment-Receipt` header
5. Your handler executes normally

## License

MIT