Provider SDK
Full reference for OpusProtocolProvider, the class on the collecting side: plans, the payment gate, verification, and collection.
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