Installation

npm install @opusprotocol/sdk

OpusProtocolProvider

import { OpusProtocolProvider } from "@opusprotocol/sdk";

const opusprotocol = new OpusProtocolProvider(config: OpusProtocolProviderConfig);

OpusProtocolProviderConfig

Option Type Required Description
wallet Signer Yes The provider’s own wallet, as a viem account, an ethers wallet, or any compatible signer
apiKey string Yes Your key from the Opus Protocol Dashboard
network "mainnet" \| "testnet" Yes Which Robinhood Chain network to target
rpcUrl string No Override the Robinhood Chain RPC endpoint
facilitatorUrl string No Point at a different Facilitator
webhookSecret string No Shared secret used to check the signature on incoming webhooks

Methods

opusprotocol.createPlan()

Writes a new plan to the Opus Protocol Plan Registry. Once the plan is on-chain, nothing about it can change.

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

CreatePlanOptions

Option Type Required Description
name string Yes Human-readable name shown for the plan
amount number Yes Amount charged each billing cycle, expressed in token base units
interval BillingInterval Yes "MONTHLY" \| "WEEKLY" \| "DAILY" \| "PER_REQUEST"
token string No Address of the token subscribers are billed in (defaults to USDG)
trialPeriodDays number No How many days the free trial lasts
meteredOverage MeteredOverage No Settings for usage-based charges on top of the base price
const plan = await opusprotocol.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

opusprotocol.deprecatePlan()

Flags a plan as deprecated. Nobody new can subscribe to it, but current subscribers are not affected.

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

opusprotocol.paymentGate()

Middleware for Express and Node.js that puts routes behind a paywall. Requests arriving with no credentials get a 402. Requests carrying a valid payment proof, or coming from a wallet with an active subscription, are allowed through.

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

PaymentGateOptions

Option Type Required Description
pricing PricingRule[] Yes The ways a caller is allowed to pay
onSuccess function No Called once verification passes, receiving (req, paymentInfo)
onFailure function No Called when a request fails verification

Two forms of PricingRule exist:

{ type: "subscription"; plan: string }
{ type: "one-time"; amount: number; token?: string }
app.use("/api/v1", opusprotocol.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
  },
}));

When a request passes the gate, the middleware populates req.payment with details of the payment: the subscription ID, the wallet address, the payment proof, and associated fields.


opusprotocol.verifySubscription()

Checks whether a particular wallet currently holds an active subscription to a plan.

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

opusprotocol.verifyPaymentProof()

Checks a payment proof taken from the X-PAYMENT header.

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

PaymentProofResult

Field Type Description
valid boolean true if the proof checked out
txHash string The on-chain transaction’s hash
amount number How much was paid, in base units
payer string Wallet address of the party that paid
memo string The memo from the original payment request, passed through

opusprotocol.buildPaymentRequired()

Builds the body of a 402 Payment Required response that follows the spec.

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

Reach for this when a route does not sit behind the paymentGate middleware:

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

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

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

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

opusprotocol.collectAll()

Runs collection for every active subscriber on a plan in one pass. Most services call it from a cron job or a similar scheduler.

const result = await opusprotocol.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 Sum of USDG collected, in base units
failures CollectFailure[] One entry per failed collection

opusprotocol.collect()

Runs collection for one subscription.

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

opusprotocol.listSubscribers()

Lists the subscribers on a plan, optionally filtered by status.

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

opusprotocol.deductAllowance()

Spends part of a subscriber’s allowance. Metered billing is built on top of this call.

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

opusprotocol.parseWebhookPayload()

Verifies the signature on an incoming webhook and decodes its payload. The Webhooks page has the full details.

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