Check and spend in your app
Everything your server does with the SDK: put users on a plan, check or spend before each action, and what happens if something goes wrong. TypeScript; other languages use the HTTP API.
Install
// npm install @usagegate/sdk
import { GateClient } from "@usagegate/sdk";
// Server only. Create the key in Dashboard → API keys.
export const gate = new GateClient(process.env.USAGEGATE_KEY!);Put users on a plan
New users have no plan until you give them one. Call grantPlan after sign-up with your user's id and a free plan id from Access rules. Their allowance refills every month on its own.
await gate.grantPlan(user.id, "plan_free");It is safe to call on every login: a user who already has a plan, free or paid, keeps it. Paid plans are never set here; they come from Stripe or your payment provider.
Check before each action
Monthly amounts and limits (credits, API calls, seats): spend with consume. It checks and spends in one step, so two requests at the same moment can never both use the last credit.
const spent = await gate.consume(user.id, "ai_credits", 1);
if (!spent.success) {
return Response.json({ error: "Upgrade to keep going" }, { status: 402 });
}
// ...do the workOn/off features (PDF export, SSO): ask with canAccess. It spends nothing, so you can also use it to show or hide an upgrade button.
if (!(await gate.canAccess(user.id, "export_pdf"))) {
return Response.json({ error: "Pro feature" }, { status: 402 });
}“No” is a normal answer, not an error. What your route returns is up to you; 402 with an upgrade link is a good default.
If something goes wrong
| Situation | What happens | What to do |
|---|---|---|
| UsageGate is down or slow (over 800 ms) | The request is allowed, with a warning in your logs, so your product stays up. | Nothing. To block instead, pass { failOpen: false }. |
| Wrong API key, unknown feature key, or a bad request | The answer is no, with a [usagegate] error in your server logs. | Fix the key or the feature key. The log says which. |
| Your own UsageGate plan has used its monthly quota | The request is allowed, with a warning. | Upgrade in Dashboard → Billing. |
The other methods (grantPlan, reportSubscription, grant, rules) throw an error instead, so you know nothing was saved.
Reference
| Method | What it does |
|---|---|
| canAccess(userId, featureKey) | true or false. Spends nothing. |
| consume(userId, featureKey, amount = 1) | Spends atomically. Returns { success, remaining }; success is false when there is not enough. |
| grantPlan(userId, planId) | Puts a user on a free plan that refills monthly. Safe to repeat (alreadyEnrolled: true). |
| reportSubscription({ eventId, userId, planId, status, periodEnd }) | Paid plan from a provider other than Stripe. See Other payment providers. |
| grant(userId, featureKey, { balance, resetAt? }) | Sets one balance by hand (support top-ups, one-off trials). Does not refill. |
| getRules() / putRules(table) | Read or replace your plan table from code. |
| configureStripe({ webhookSecret }) / getStripeConfig() | Save or check the Stripe connection from code. |
Options for new GateClient(key, options): timeoutMs (default 800), failOpen (default true), baseUrl (only if you host UsageGate yourself).

