Overview
The /check endpoint verifies whether a customer has access to a specific feature or product. Use it to:
Gate features behind paywalls
Display remaining usage limits
Show upgrade prompts when limits are reached
Combine check + track in a single atomic operation
Quick Start
React Frontend
Backend (Node.js)
Python
import { useCustomer } from '@useautumn/autumn-js/react' ;
function FeatureButton () {
const { check } = useCustomer ();
const handleClick = () => {
const result = check ({ featureId: "ai_tokens" });
if ( ! result . allowed ) {
alert ( `AI limit reached. ${ result . balance ?. remaining || 0 } tokens left.` );
return ;
}
// Proceed with feature
generateAIContent ();
};
return < button onClick = { handleClick } > Generate AI Content </ button > ;
}
Parameters
The ID of the customer to check access for.
The ID of the feature to check. Use either featureId or productId.
The ID of the product to check. Use either featureId or productId.
The ID of the entity for entity-scoped checks (e.g., per-seat limits).
Minimum balance required for access. Returns allowed: false if the customer’s balance is below this value. // Check if customer has at least 500 tokens
check ({ featureId: "api_calls" , requiredBalance: 500 })
If true, atomically records a usage event while checking access. Combines check + track in one call. // Check AND consume 100 tokens in one atomic operation
check ({
featureId: "ai_tokens" ,
requiredBalance: 100 ,
sendEvent: true // Deducts 100 tokens if allowed
})
If true, includes upgrade/upsell information when access is denied. Useful for displaying paywalls. const result = check ({
featureId: "advanced_analytics" ,
withPreview: true
});
if ( ! result . allowed && result . preview ) {
// Show upgrade modal with result.preview.products
}
Additional properties to attach to the usage event (only used if sendEvent: true).
Response
interface CheckResponse {
allowed : boolean ; // Whether customer has access
customerId : string ; // The customer ID
entityId ?: string ; // The entity ID (if entity-scoped)
requiredBalance ?: number ; // The required balance checked
balance : Balance | null ; // Customer's balance details
preview ?: { // Upgrade info (if withPreview: true and !allowed)
scenario : "usage_limit" | "feature_flag" ;
title : string ;
message : string ;
featureId : string ;
featureName : string ;
products : Product []; // Products that grant access
};
}
interface Balance {
featureId : string ;
granted : number ; // Total balance granted
remaining : number ; // Balance remaining
usage : number ; // Current usage
unlimited : boolean ; // Whether feature is unlimited
overageAllowed : boolean ; // Whether overage is allowed
nextResetAt : number | null ; // Timestamp of next reset
breakdown ?: BalanceBreakdown []; // Detailed balance sources
}
Common Use Cases
Simple Feature Gate
function ExportButton () {
const { check } = useCustomer ();
const handleExport = () => {
const { allowed } = check ({ featureId: "pdf_export" });
if ( ! allowed ) {
showUpgradeModal ();
return ;
}
exportToPDF ();
};
return < button onClick = { handleExport } > Export to PDF </ button > ;
}
Display Remaining Usage
function UsageMeter () {
const { check } = useCustomer ();
const result = check ({ featureId: "api_calls" });
if ( ! result . balance ) return null ;
const { remaining , granted , unlimited } = result . balance ;
if ( unlimited ) {
return < div > Unlimited API calls </ div > ;
}
return (
< div >
{ remaining } / { granted } API calls remaining
{ remaining < granted * 0.1 && (
< button onClick = { () => upgradePlan () } > Upgrade for more </ button >
) }
</ div >
);
}
Atomic Check + Track
Use sendEvent: true to check access and record usage in a single atomic operation:
// Check if customer has 1000 tokens AND consume them atomically
const result = await autumn . balances . check ({
customerId: "cus_123" ,
featureId: "ai_tokens" ,
requiredBalance: 1000 ,
sendEvent: true , // Atomically deduct tokens if allowed
properties: {
model: "gpt-4" ,
requestId: "req_xyz"
}
});
if ( ! result . allowed ) {
return res . status ( 403 ). json ({ error: "Insufficient tokens" });
}
// Tokens already deducted, proceed with AI generation
await generateAI ();
Show Upgrade Options on Limit
function AnalyticsPage () {
const { check } = useCustomer ();
const result = check ({
featureId: "advanced_analytics" ,
withPreview: true
});
if ( ! result . allowed && result . preview ) {
return (
< UpgradePrompt
title = { result . preview . title }
message = { result . preview . message }
plans = { result . preview . products }
/>
);
}
return < AdvancedAnalyticsDashboard /> ;
}
Entity-Scoped Checks (Per-Seat Limits)
// Check if a specific workspace has access
const result = await autumn . balances . check ({
customerId: "cus_123" ,
entityId: "workspace_abc" , // Check specific workspace
featureId: "team_members" ,
requiredBalance: 1 // Check if they can add 1 more member
});
if ( ! result . allowed ) {
return res . status ( 403 ). json ({
error: "Team member limit reached for this workspace"
});
}
await addTeamMember ( workspaceId , newMemberId );
Error Handling
import { AutumnClientError } from '@useautumn/autumn-js/react' ;
try {
const result = check ({ featureId: "api_calls" });
if ( ! result . allowed ) {
console . log ( "Access denied" , result . balance ?. remaining );
}
} catch ( error ) {
// Note: check() in React is local and doesn't throw
// It uses cached customer data from useCustomer()
}
Balance Breakdown
When a customer has multiple sources of balance (multiple plans, top-ups, rollovers), the breakdown array shows where each portion comes from:
const result = await autumn . balances . check ({
customerId: "cus_123" ,
featureId: "api_calls"
});
result . balance ?. breakdown ?. forEach ( item => {
console . log ( `Plan ${ item . planId } : ${ item . remaining } of ${ item . includedGrant } remaining` );
if ( item . reset ) {
console . log ( `Resets at: ${ new Date ( item . reset . resetsAt ) } ` );
}
});
Query Parameters
Bypass cache and fetch fresh data from the database.
Expand related objects. Supports: "balance.feature" // Include full feature object in response
await autumn . balances . check (
{ customerId: "cus_123" , featureId: "api_calls" },
{ expand: [ "balance.feature" ] }
);
Next Steps
Track Usage Learn how to record usage events
Handle Upgrades Upgrade customers when they hit limits