Provider SDK
The complete HoodLayerProvider reference, for anyone building a service that takes payments from agents.
Installation
npm install @hoodlayerorg/sdk
HoodLayerProvider
import { HoodLayerProvider } from "@hoodlayerorg/sdk";
const hoodlayer = new HoodLayerProvider(config: HoodLayerProviderConfig);
HoodLayerProviderConfig
| Option | Type | Required | Description |
|---|---|---|---|
wallet |
Signer |
Yes | The provider’s wallet: a viem account, ethers wallet, or compatible signer |
apiKey |
string |
Yes | API key issued in the HoodLayer Dashboard |
network |
"mainnet" \| "testnet" |
Yes | Which Robinhood Chain network to target |
rpcUrl |
string |
No | A custom RPC endpoint for Robinhood Chain |
facilitatorUrl |
string |
No | Override for the Facilitator URL |
webhookSecret |
string |
No | Secret used to check incoming webhook signatures |
Methods
hoodlayer.createPlan()
Writes a plan record to the HoodLayer Plan Registry. Once created, it can’t be changed.
const plan = await hoodlayer.createPlan(options: CreatePlanOptions): Promise<Plan>
CreatePlanOptions
| Option | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Name shown for the plan |
amount |
number |
Yes | What each billing cycle costs, in token base units |
interval |
BillingInterval |
Yes | "MONTHLY" \| "WEEKLY" \| "DAILY" \| "PER_REQUEST" |
token |
string |
No | Token address to bill in (default: USDC) |
trialPeriodDays |
number |
No | How many days the free trial lasts |
meteredOverage |
MeteredOverage |
No | Config for usage-based overage billing |
const plan = await hoodlayer.createPlan({
name: "API Pro",
amount: 49_000_000, // 49 USDC
interval: "MONTHLY",
trialPeriodDays: 7,
meteredOverage: {
unit: "1000 tokens",
price: 2_000, // 0.002 USDC per 1k tokens
},
});
console.log(plan.id); // save it, this is your plan id
hoodlayer.deprecatePlan()
Flags a plan as deprecated, which blocks new subscriptions. Anyone already subscribed keeps going.
await hoodlayer.deprecatePlan(options: { planId: string }): Promise<void>
hoodlayer.paymentGate()
Middleware for Express/Node.js that puts routes behind a paywall. Unauthenticated requests get a 402 response back; requests carrying a valid payment proof or an active subscription go through.
app.use("/api/v1", hoodlayer.paymentGate(options: PaymentGateOptions))
PaymentGateOptions
| Option | Type | Required | Description |
|---|---|---|---|
pricing |
PricingRule[] |
Yes | The payment options you want to offer |
onSuccess |
function |
No | Runs after verification succeeds. Called with (req, paymentInfo). |
onFailure |
function |
No | Runs when a verification fails |
A PricingRule takes one of these shapes:
{ type: "subscription"; plan: string }
{ type: "one-time"; amount: number; token?: string }
app.use("/api/v1", hoodlayer.paymentGate({
pricing: [
{ type: "subscription", plan: plan.id },
{ type: "one-time", amount: 500_000 },
],
onSuccess: (req, info) => {
req.paymentInfo = info; // stash on the request so downstream handlers can read it
},
}));
On authenticated requests, the middleware attaches a req.payment object holding the payment details (subscription ID, wallet address, payment proof, and so on).
hoodlayer.verifySubscription()
Checks whether a wallet holds an active subscription to a plan.
const valid = await hoodlayer.verifySubscription(options: {
subscriber: string;
plan: string;
}): Promise<boolean>
const isActive = await hoodlayer.verifySubscription({
subscriber: req.headers["x-wallet-address"],
plan: plan.id,
});
hoodlayer.verifyPaymentProof()
Checks a payment proof taken from the X-PAYMENT header.
const result = await hoodlayer.verifyPaymentProof(
proof: string
): Promise<PaymentProofResult>
PaymentProofResult
| Field | Type | Description |
|---|---|---|
valid |
boolean |
True if the proof checks out |
txHash |
string |
Hash of the on-chain transaction |
amount |
number |
How much was paid, in base units |
payer |
string |
Wallet address of the payer |
memo |
string |
The memo carried over from the original payment request |
hoodlayer.buildPaymentRequired()
Builds a correctly shaped 402 Payment Required response body.
const body = hoodlayer.buildPaymentRequired(options: {
pricing: PricingRule[];
memo?: string;
}): PaymentRequiredResponse
Handy when you’re not using the paymentGate middleware:
app.get("/api/v1/data", async (req, res) => {
const proof = req.headers["x-payment"];
if (!proof) {
return res.status(402).json(hoodlayer.buildPaymentRequired({
pricing: [{ type: "subscription", plan: plan.id }],
}));
}
const result = await hoodlayer.verifyPaymentProof(proof);
if (!result.valid) {
return res.status(402).json(hoodlayer.buildPaymentRequired({
pricing: [{ type: "subscription", plan: plan.id }],
}));
}
res.json({ data: "..." });
});
hoodlayer.collectAll()
Kicks off collection for every active subscriber on a plan. Usually run from a cron job or some other scheduled task.
const result = await hoodlayer.collectAll(options: {
plan: string;
dryRun?: boolean;
}): Promise<CollectResult>
CollectResult
| Field | Type | Description |
|---|---|---|
collected |
number |
How many collections succeeded |
failed |
number |
How many collections failed |
totalAmount |
number |
USDC collected in total, in base units |
failures |
CollectFailure[] |
Per-failure details |
hoodlayer.collect()
Runs collection for one specific subscription.
await hoodlayer.collect(options: { subscriptionId: string }): Promise<CollectResult>
hoodlayer.listSubscribers()
Fetches everyone subscribed to a plan.
const subscribers = await hoodlayer.listSubscribers(options: {
plan: string;
status?: SubscriptionStatus;
}): Promise<Subscription[]>
hoodlayer.deductAllowance()
Debits a subscriber’s allowance. This is the building block for metered billing.
const result = await hoodlayer.deductAllowance(options: {
allowanceId: string;
amount: number;
memo?: string;
}): Promise<{ remaining: number; txHash: string }>
hoodlayer.parseWebhookPayload()
Verifies and parses an incoming webhook payload. More in Webhooks.
const event = hoodlayer.parseWebhookPayload(options: {
payload: string;
signature: string;
}): WebhookEvent