Apps
Fastify SDK
The @payweave/fastify package plugs into Fastify's preHandler hook. The recommended entry point is payweave.route(), which bundles validation, charging, auto-refund, and marketplace registration.
Installation
Terminal
npm install @payweave/fastify zodFull example
TypeScript
import Fastify from 'fastify';
import { Payweave } from '@payweave/fastify';
import { z } from 'zod';
const app = Fastify();
const payweave = new Payweave(
process.env.PAYWEAVE_APP_ID!,
process.env.PAYWEAVE_APP_SECRET!
);
payweave.assertConfigured(); // fail early on missing env
const WeatherInput = z.object({ city: z.string() });
payweave.route(app, 'post', '/api/weather', {
price: '0.001',
description: 'Current weather for a city',
inputSchema: WeatherInput,
handler: async (_req, body) => {
// body: { city: string } — typed from Zod
const res = await fetch(`https://api.weather/?q=${body.city}`);
if (!res.ok) throw new Error('weather_upstream_error');
return await res.json();
},
});
payweave.mountSync(app);
await app.listen({ port: 3000 });Dynamic pricing
TypeScript
payweave.route(app, 'post', '/api/summarize', {
price: async (req) => {
const body = req.body as { text: string };
return body.text.length > 5000 ? '0.01' : '0.002';
},
inputSchema: z.object({ text: z.string() }),
handler: async (_req, body) => summarize(body.text),
});Accessing payment metadata
TypeScript
handler: async (req, body) => {
const txHash = (req as any).payweaveTransactionHash;
const payer = (req as any).payweavePayer;
const receipt = (req as any).payweaveReceipt;
return { txHash, payer };
}Manual refund
TypeScript
payweave.route(app, 'post', '/api/weather', {
price: '0.001',
refundOnError: false,
inputSchema: WeatherInput,
handler: async (req, body, reply) => {
try {
return await fetchWeather(body.city);
} catch (err: any) {
if (err.status === 429) {
await payweave.refund({
transactionHash: (req as any).payweaveTransactionHash!,
reason: 'upstream_rate_limited',
});
reply.status(429).send({ error: 'rate_limited', retry_after: 60 });
return;
}
throw err;
}
},
});Low-level: payweave.charge()
TypeScript
app.get(
'/api/custom',
{ preHandler: payweave.charge({ price: '0.001', description: 'Custom' }) },
async (_req, reply) => reply.send({ ok: true })
);Fastify parses JSON bodies automatically, so no extra middleware is needed. Just declare your routes with
payweave.route() and call mountSync(app) once.