Installation

npm install @scribefinance/sdk

ScribeFinanceProvider

import { ScribeFinanceProvider } from "@scribefinance/sdk";

const scribefinance = new ScribeFinanceProvider(config: ScribeFinanceProviderConfig);

ScribeFinanceProviderConfig

Option Type Required Description
wallet Signer Yes The provider’s wallet: a viem account, ethers wallet, or compatible signer
apiKey string Yes API key from the Scribe Finance Dashboard
network "mainnet" \| "testnet" Yes The Robinhood Chain network to operate on
rpcUrl string No Custom Robinhood Chain RPC endpoint
facilitatorUrl string No Alternate Facilitator URL
webhookSecret string No Secret for verifying incoming webhook signatures

Methods

scribefinance.createPlan()

Publishes a plan to the Scribe Finance Plan Registry. A plan is immutable once written to the chain.

const plan = await scribefinance.createPlan(options: CreatePlanOptions): Promise<Plan>

CreatePlanOptions

Option Type Required Description
name string Yes Display name for the plan
amount number Yes Price per billing cycle, in token base units
interval BillingInterval Yes "MONTHLY" \| "WEEKLY" \| "DAILY" \| "PER_REQUEST"
token string No Billing token address (default: USDG)
trialPeriodDays number No Length of the free trial, in days
meteredOverage MeteredOverage No Configuration for usage-based overage billing
const plan = await scribefinance.createPlan({
  name: "API Pro",
  amount: 49_000_000,   // 49 USDG
  interval: "MONTHLY",
  trialPeriodDays: 7,
  meteredOverage: {
    unit: "1000 tokens",
    price: 2_000, // 0.002 USDG per 1k tokens
  },
});

console.log(plan.id); // keep this: it is your plan id

scribefinance.deprecatePlan()

Marks a plan deprecated. New subscriptions are refused; existing subscribers continue unaffected.

await scribefinance.deprecatePlan(options: { planId: string }): Promise<void>

scribefinance.paymentGate()

Express/Node.js middleware that gates routes behind payment. A request without credentials receives a 402; one bearing a valid payment proof or an active subscription passes through.

app.use("/api/v1", scribefinance.paymentGate(options: PaymentGateOptions))

PaymentGateOptions

Option Type Required Description
pricing PricingRule[] Yes The payment options offered to callers
onSuccess function No Invoked after successful verification, with (req, paymentInfo)
onFailure function No Invoked when verification fails

A PricingRule takes one of two shapes:

{ type: "subscription"; plan: string }
{ type: "one-time"; amount: number; token?: string }
app.use("/api/v1", scribefinance.paymentGate({
  pricing: [
    { type: "subscription", plan: plan.id },
    { type: "one-time", amount: 500_000 },
  ],
  onSuccess: (req, info) => {
    req.paymentInfo = info; // attach to the request for downstream handlers
  },
}));

For requests that clear the gate, the middleware sets req.payment with the payment details: subscription ID, wallet address, payment proof, and related fields.


scribefinance.verifySubscription()

Reports whether a wallet has an active subscription to a given plan.

const valid = await scribefinance.verifySubscription(options: {
  subscriber: string;
  plan: string;
}): Promise<boolean>
const isActive = await scribefinance.verifySubscription({
  subscriber: req.headers["x-wallet-address"],
  plan: plan.id,
});

scribefinance.verifyPaymentProof()

Validates a payment proof extracted from the X-PAYMENT header.

const result = await scribefinance.verifyPaymentProof(
  proof: string
): Promise<PaymentProofResult>

PaymentProofResult

Field Type Description
valid boolean Whether the proof verified
txHash string Hash of the on-chain transaction
amount number Amount paid, in base units
payer string The payer’s wallet address
memo string Memo carried forward from the original payment request

scribefinance.buildPaymentRequired()

Constructs a spec-compliant 402 Payment Required response body.

const body = scribefinance.buildPaymentRequired(options: {
  pricing: PricingRule[];
  memo?: string;
}): PaymentRequiredResponse

Useful when your routes bypass the paymentGate middleware:

app.get("/api/v1/data", async (req, res) => {
  const proof = req.headers["x-payment"];

  if (!proof) {
    return res.status(402).json(scribefinance.buildPaymentRequired({
      pricing: [{ type: "subscription", plan: plan.id }],
    }));
  }

  const result = await scribefinance.verifyPaymentProof(proof);
  if (!result.valid) {
    return res.status(402).json(scribefinance.buildPaymentRequired({
      pricing: [{ type: "subscription", plan: plan.id }],
    }));
  }

  res.json({ data: "..." });
});

scribefinance.collectAll()

Triggers collection across every active subscriber on a plan. The typical home for this call is a cron job or another scheduler.

const result = await scribefinance.collectAll(options: {
  plan: string;
  dryRun?: boolean;
}): Promise<CollectResult>

CollectResult

Field Type Description
collected number Count of successful collections
failed number Count of failed collections
totalAmount number Total USDG collected, in base units
failures CollectFailure[] Detail for each failure

scribefinance.collect()

Collects from a single subscription.

await scribefinance.collect(options: { subscriptionId: string }): Promise<CollectResult>

scribefinance.listSubscribers()

Returns every subscriber on a plan.

const subscribers = await scribefinance.listSubscribers(options: {
  plan: string;
  status?: SubscriptionStatus;
}): Promise<Subscription[]>

scribefinance.deductAllowance()

Draws down a subscriber’s allowance, the primitive that metered billing is built on.

const result = await scribefinance.deductAllowance(options: {
  allowanceId: string;
  amount: number;
  memo?: string;
}): Promise<{ remaining: number; txHash: string }>

scribefinance.parseWebhookPayload()

Authenticates and decodes an incoming webhook payload. Full coverage in Webhooks.

const event = scribefinance.parseWebhookPayload(options: {
  payload: string;
  signature: string;
}): WebhookEvent