SDK Plugins: Give Buyers Free API Calls Before Payment Kicks In

RelAI Team
Mar 16, 2026 · 4 min read
SDK Plugins: Give Buyers Free API Calls Before Payment Kicks In

Your API is live, protected by x402, and every call costs money. But new users don't know if the data is worth paying for. You need a way to let them try it first.

The @relai-fi/x402 SDK now has a plugin system. The first built-in plugin — Free Tier — gives every buyer a configurable number of free API calls before payment kicks in. No billing system, no usage database, no extra infrastructure. Three lines of code.

It works in two modes: cloud (with a service key — synced to the RelAI dashboard) or local (no key needed — in-memory tracking with exportable data).


The Problem

Paid-first APIs have a cold start problem. A developer evaluating your endpoint has to connect a wallet, fund it, and sign a payment before seeing a single response. Most won't bother.

Free tiers solve this, but building one means:

  • Tracking per-user usage
  • Handling reset periods (daily, monthly, lifetime)
  • Storing counters somewhere reliable
  • Adding middleware that checks counters before your payment layer
That's a lot of code for "let them try it five times."

Three Lines of Code

import Relai from '@relai-fi/x402/server'
import { freeTier } from '@relai-fi/x402/plugins'

const relai = new Relai({
network: 'base',
plugins: [
freeTier({
serviceKey: process.env.RELAI_SERVICE_KEY!,
perBuyerLimit: 5,
resetPeriod: 'daily',
}),
],
})

app.get('/api/data', relai.protect({
payTo: '0xYourWallet',
price: 0.01,
}), (req, res) => {
if (req.x402Free) {
console.log('Free call — remaining:', req.pluginMeta?.remaining)
}
res.json({ data: 'content' })
})

That's it. The first five calls per buyer per day are free. Call six triggers the normal 402 payment flow.


How It Works

  1. A request arrives without a payment header.
  2. The freeTier plugin calls the RelAI backend to check the buyer's usage.
  3. If the buyer has free calls left → the request skips payment, your handler runs, and the call is recorded.
  4. If free calls are exhausted → normal 402 Payment Required response.
If the request already has a payment header (client is paying), plugins are skipped entirely. Payment always works.

The plugin resolves buyer identity automatically:

PrioritySourceExample
1JWT Bearer token (sub claim)user:abc123
2X-Wallet-Address headerwallet:0x1234...
3IP address fallbackip:192.168.1.1

Configuration Options

freeTier({
  serviceKey: 'sk_live_...',   // Optional — omit for local in-memory mode
  perBuyerLimit: 10,           // Required — free calls per buyer per period
  resetPeriod: 'daily',        // 'none' | 'daily' | 'monthly'
  globalCap: 1000,             // Optional — cap across all buyers
  paths: ['/api/data'],        // Optional — default: '*' (all paths)
})

With a serviceKey, state is stored server-side by RelAI and visible in the dashboard. Without a key, the plugin runs locally in-memory — same logic, but resets on restart.

Local Mode (no service key)

const ft = freeTier({ perBuyerLimit: 10, resetPeriod: 'daily' })

const relai = new Relai({ network: 'base', plugins: [ft] })

// Export usage data at any time
app.get('/admin/usage', (req, res) => {
res.json(ft.getUsageData()) // { mode: 'local', usage: [...], globalCount, ... }
})

You can check which mode is active via ft.mode ('local' or 'cloud'). In cloud mode, getUsageData() returns null — use the dashboard instead.


Response Headers

Free tier responses include headers so clients know where they stand:

X-Free-Calls-Remaining: 4
X-Free-Calls-Total: 5

Your handler can also check req.x402Free (boolean) and req.pluginMeta (object with remaining, total, buyerId) to differentiate free vs paid calls.


Dashboard Management

The SDK Plugins dashboard lets you:

  • View active plugin configurations per service key
  • Monitor per-buyer usage in real time
  • Reset usage counters (useful for support)
  • Update limits, reset periods, and paths — changes take effect immediately
Configuration set via the SDK syncs automatically to the dashboard on first request. You can override settings from either side.

Works Everywhere

The plugin system works with Express, Fastify, Next.js, or any framework that adapts to Express-like middleware. For Next.js App Router:

import Relai from '@relai-fi/x402/server'
import { freeTier } from '@relai-fi/x402/plugins'

const relai = new Relai({
network: 'base',
plugins: [
freeTier({
serviceKey: process.env.RELAI_SERVICE_KEY!,
perBuyerLimit: 5,
resetPeriod: 'daily',
}),
],
})

export async function GET(req: NextRequest) {
const middleware = relai.protect({ payTo, price: 0.01 })
// Adapt NextRequest → Express-like req and run middleware
}


Build Your Own Plugins

The plugin system is extensible. Any object implementing RelaiPlugin can hook into beforePaymentCheck (run before 402) and afterSettled (run after payment). Plugins are non-blocking — if one throws, the request falls through to the normal flow.

import type { RelaiPlugin } from '@relai-fi/x402/plugins'

const myPlugin: RelaiPlugin = {
name: 'my-plugin',
async beforePaymentCheck(req, ctx) {
// Return { skip: true } to bypass payment
return {}
},
async afterSettled(req, result, ctx) {
// Analytics, logging, webhooks
},
}


Get Started

  1. Install @relai-fi/x402@0.5.39 or later
  2. Add the freeTier plugin to your Relai instance (service key optional)
  3. Deploy — your first five callers per day get free access
  4. Optionally, add a service key to sync usage to the Dashboard
Read the full documentation at relai.fi/documentation/sdk-plugins.
Written by the RelAI Team.

Understand x402 before you implement

This guide uses payment primitives from the x402 standard. Read the protocol overview for a complete flow, terminology, and integration FAQ.