OpenPermit Docs
SDK

Seller SDK

Protect paid resources and verify payment credentials with seller middleware.

Use createSellerMiddleware for Fetch-compatible runtimes and createHonoSellerMiddleware for Hono.

Dashboard-managed resources only need the seller and resource IDs:

import { createOpenPermitClient } from '@openpermit/sdk/client';
import { createSellerMiddleware } from '@openpermit/sdk/seller';

const openpermit = createOpenPermitClient({
	baseUrl: 'https://api.openpermit.ai',
	apiKey: process.env.OPENPERMIT_API_KEY,
});

const requirePayment = createSellerMiddleware({
	client: openpermit,
	sellerId: 'seller_...',
	resourceId: 'resource_...',
	paymentMethod: 'x402',
});

export default {
	fetch: (request: Request) =>
		requirePayment(request, async (_request, context) => {
			return Response.json({
				ok: true,
				intentId: context.intentId,
			});
		}),
};

When credentials are missing or invalid, middleware returns a 402 challenge response. When verification succeeds, it calls your handler with a context containing the verification result, intent ID, payment credential, and optional onchain settlement reference.

Typed builders

defineSeller and defineSellerResource are typed identity helpers. They return their input unchanged but give your editor full autocomplete and per-field hover docs for the middleware config — no need to import types from @openpermit/types.

import { defineSeller, defineSellerResource } from '@openpermit/sdk/seller';

const seller = defineSeller({
	name: 'Example Data API',
	domain: 'api.example.com',
});

const quotesResource = defineSellerResource({
	resourceId: 'quotes:v1',
	method: 'GET',
	pathTemplate: '/v1/quotes/{symbol}',
	acceptedPaymentMethods: ['x402'],
	pricing: { type: 'fixed', amount: '0.04', asset: 'USDC' },
});

Code-managed fixed resources can be declared next to the route. The middleware lazily upserts the seller and resource before the first challenge:

const requirePayment = createSellerMiddleware({
	client: openpermit,
	seller,
	resource: quotesResource,
	paymentMethod: 'x402',
});

Dynamic resources declare pricing bounds and return a runtime quote per request:

const requirePayment = createSellerMiddleware({
	client: openpermit,
	seller,
	resource: defineSellerResource({
		resourceId: 'quotes:dynamic',
		method: 'GET',
		pathTemplate: '/v1/quotes/{symbol}',
		acceptedPaymentMethods: ['x402'],
		pricing: { type: 'dynamic', asset: 'USDC', minAmount: '0.01', maxAmount: '0.25', displayAmount: '0.05' },
	}),
	paymentMethod: 'x402',
	quote: async (request) => {
		const url = new URL(request.url);
		return {
			amount: url.searchParams.get('tier') === 'realtime' ? '0.12' : '0.03',
			quoteId: crypto.randomUUID(),
			expiresAt: new Date(Date.now() + 30_000).toISOString(),
			metadata: { tier: url.searchParams.get('tier') ?? 'standard' },
		};
	},
});

Use syncSellerResources to apply a deploy manifest:

import { defineSellerResource, syncSellerResources } from '@openpermit/sdk/seller';

await syncSellerResources({
	client: openpermit,
	sellerId: 'seller_...',
	resources: [
		defineSellerResource({
			resourceId: 'quotes:v1',
			method: 'GET',
			pathTemplate: '/v1/quotes/{symbol}',
			acceptedPaymentMethods: ['x402'],
			pricing: { type: 'fixed', amount: '0.04', asset: 'USDC' },
		}),
	],
});

Hono usage:

import { createHonoSellerMiddleware } from '@openpermit/sdk/seller';

app.use('/paid/*', createHonoSellerMiddleware(requirePaymentConfig));

On this page