Documentation Index
Fetch the complete documentation index at: https://docs.wiseyield.co/llms.txt
Use this file to discover all available pages before exploring further.
Endpoint
GET https://www.wiseyield.co/api/billing/usage
Authentication
Requires a valid API key with billing:read scope.
Response
Returns usage statistics object.
Number of active farms owned by user
Number of successful AI requests made this billing period (current month)
curl -X GET https://www.wiseyield.co/api/billing/usage \
-H "Authorization: Bearer wy_YOUR_API_KEY"
{
"farmsCount": 3,
"aiRequestsThisMonth": 127
}
Errors
Unauthorized - Missing or invalid API key
Internal Server Error - Failed to fetch usage statistics
Usage Metrics Explained
farmsCount
- Definition: Number of active farms user owns (not deleted)
- Excludes: Soft-deleted farms, farms user is member of but doesn’t own
- Updates: Real-time (reflects current database state)
aiRequestsThisMonth
- Definition: Count of successful AI requests made since billing period start
- Billing Period: Calendar month (resets on 1st of month)
- Includes: Only completed/successful requests
- Excludes: Failed requests, pending requests, requests from previous months
Plan Limits
Usage limits by plan tier:
Seed Plan (€22/month)
- Farms: 1 farm
- AI Requests: 50/month
Sprout Plan (€49/month)
- Farms: 3 farms
- AI Requests: 200/month
Harvest Plan (€89/month) ⭐
- Farms: 7 farms
- AI Requests: 500/month
Grove Plan (€149/month)
- Farms: 15 farms
- AI Requests: 1,000/month
Summit Plan (€299+/month)
- Farms: Unlimited
- AI Requests: Unlimited
Use Cases
Check Usage Against Limits
async function checkUsageLimits() {
const [usageResponse, subscriptionResponse] = await Promise.all([
fetch('/api/billing/usage', {
headers: { 'Authorization': `Bearer ${apiKey}` }
}),
fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
})
]);
const usage = await usageResponse.json();
const { subscription } = await subscriptionResponse.json();
const plan = subscription?.plan || 'expired';
const limits = {
expired: { farms: 1, aiRequests: 50 },
seed: { farms: 1, aiRequests: 50 },
sprout: { farms: 3, aiRequests: 200 },
harvest: { farms: 7, aiRequests: 500 },
grove: { farms: 15, aiRequests: 1000 },
summit: { farms: Infinity, aiRequests: Infinity }
};
const planLimits = limits[plan];
return {
farms: {
used: usage.farmsCount,
limit: planLimits.farms,
percentage: (usage.farmsCount / planLimits.farms) * 100,
remaining: planLimits.farms - usage.farmsCount
},
aiRequests: {
used: usage.aiRequestsThisMonth,
limit: planLimits.aiRequests,
percentage: (usage.aiRequestsThisMonth / planLimits.aiRequests) * 100,
remaining: planLimits.aiRequests - usage.aiRequestsThisMonth
}
};
}
// Usage
const limits = await checkUsageLimits();
if (limits.farms.percentage >= 80) {
showUpgradePrompt('farms');
}
Show Usage Dashboard
async function getUsageDashboard() {
const response = await fetch('/api/billing/usage', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const usage = await response.json();
return {
farmsCount: usage.farmsCount,
aiRequestsThisMonth: usage.aiRequestsThisMonth,
aiRequestsRemaining: 500 - usage.aiRequestsThisMonth, // For harvest plan
resetDate: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 1)
};
}
Check Before Creating Resource
async function canCreateFarm() {
const [usageResponse, subscriptionResponse] = await Promise.all([
fetch('/api/billing/usage', {
headers: { 'Authorization': `Bearer ${apiKey}` }
}),
fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
})
]);
const usage = await usageResponse.json();
const { subscription } = await subscriptionResponse.json();
const plan = subscription?.plan || 'expired';
const farmLimits = {
expired: 1,
seed: 1,
sprout: 3,
harvest: 7,
grove: 15,
summit: Infinity
};
const limit = farmLimits[plan];
const canCreate = usage.farmsCount < limit;
if (!canCreate) {
return {
allowed: false,
reason: `You've reached the ${plan} plan limit of ${limit} farm(s). Upgrade to create more farms.`,
currentUsage: usage.farmsCount,
limit
};
}
return { allowed: true };
}
// Usage
const canCreate = await canCreateFarm();
if (!canCreate.allowed) {
toast.error(canCreate.reason);
showUpgradeDialog();
}
Monitor AI Request Usage
async function checkAiRequestQuota() {
const response = await fetch('/api/billing/usage', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const usage = await response.json();
const limit = 500; // Harvest plan
const used = usage.aiRequestsThisMonth;
const percentage = (used / limit) * 100;
return {
used,
limit,
remaining: limit - used,
percentage,
willResetOn: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 1),
isNearLimit: percentage >= 80,
isOverLimit: used >= limit
};
}
// Usage
const quota = await checkAiRequestQuota();
if (quota.isNearLimit) {
toast.warning(`You've used ${quota.percentage.toFixed(0)}% of your AI requests`);
}
Best Practices
Check Before Actions: Verify usage limits before allowing users to create farms or make AI requests.
Show Progress Bars: Display usage as percentage of limit with visual progress bars.
Warn at 80%: Alert users when they reach 80% of any limit to avoid surprises.
Display Reset Date: Show when AI request counter resets (1st of next month).
Monthly Reset: AI request count resets on 1st of each month, not on subscription anniversary.
Real-Time Data: Usage numbers are real-time. Cache carefully to avoid stale data blocking actions.
Soft Limits: Exceeding limits may trigger soft blocks. Always check before resource-intensive operations.
Integration Examples
Usage Dashboard Card
function UsageDashboardCard() {
const [usage, setUsage] = useState(null);
const [subscription, setSubscription] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadData() {
try {
const [usageRes, subRes] = await Promise.all([
fetch('/api/billing/usage', {
headers: { 'Authorization': `Bearer ${apiKey}` }
}),
fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
})
]);
const usageData = await usageRes.json();
const { subscription } = await subRes.json();
setUsage(usageData);
setSubscription(subscription);
} finally {
setLoading(false);
}
}
loadData();
}, []);
if (loading) return <div>Loading...</div>;
const plan = subscription?.plan || 'expired';
const limits = {
expired: { farms: 1, aiRequests: 50 },
seed: { farms: 1, aiRequests: 50 },
sprout: { farms: 3, aiRequests: 200 },
harvest: { farms: 7, aiRequests: 500 },
grove: { farms: 15, aiRequests: 1000 },
summit: { farms: Infinity, aiRequests: Infinity }
};
const planLimits = limits[plan];
return (
<div className="usage-card">
<h3>Usage This Month</h3>
<div className="usage-metric">
<label>Farms</label>
<ProgressBar
value={usage.farmsCount}
max={planLimits.farms}
label={`${usage.farmsCount} / ${planLimits.farms === Infinity ? '∞' : planLimits.farms}`}
/>
</div>
<div className="usage-metric">
<label>AI Requests</label>
<ProgressBar
value={usage.aiRequestsThisMonth}
max={planLimits.aiRequests}
label={`${usage.aiRequestsThisMonth} / ${planLimits.aiRequests === Infinity ? '∞' : planLimits.aiRequests}`}
/>
<p className="reset-info">
Resets: {new Date(new Date().getFullYear(), new Date().getMonth() + 1, 1).toLocaleDateString()}
</p>
</div>
{(usage.farmsCount >= planLimits.farms || usage.aiRequestsThisMonth >= planLimits.aiRequests) && (
<div className="upgrade-prompt">
<p>You've reached your plan limits</p>
<button onClick={() => router.push('/pricing')}>
Upgrade Plan
</button>
</div>
)}
</div>
);
}
Usage Progress Bar
function UsageProgressBar({ used, limit, label }) {
const percentage = limit === Infinity ? 0 : (used / limit) * 100;
const getColor = () => {
if (percentage >= 100) return 'red';
if (percentage >= 80) return 'orange';
return 'green';
};
return (
<div className="progress-bar">
<div className="progress-label">
<span>{label}</span>
<span>{used} / {limit === Infinity ? '∞' : limit}</span>
</div>
<div className="progress-track">
<div
className={`progress-fill bg-${getColor()}`}
style={{ width: `${Math.min(percentage, 100)}%` }}
/>
</div>
<div className="progress-percentage">
{limit === Infinity ? 'Unlimited' : `${percentage.toFixed(0)}%`}
</div>
</div>
);
}
Usage Guard Hook
function useUsageGuard(resourceType) {
const [canCreate, setCanCreate] = useState(false);
const [loading, setLoading] = useState(true);
const [reason, setReason] = useState(null);
useEffect(() => {
async function checkUsage() {
const [usageRes, subRes] = await Promise.all([
fetch('/api/billing/usage', {
headers: { 'Authorization': `Bearer ${apiKey}` }
}),
fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
})
]);
const usage = await usageRes.json();
const { subscription } = await subRes.json();
const plan = subscription?.plan || 'expired';
const limits = {
expired: { farms: 1, aiRequests: 50 },
seed: { farms: 1, aiRequests: 50 },
sprout: { farms: 3, aiRequests: 200 },
harvest: { farms: 7, aiRequests: 500 },
grove: { farms: 15, aiRequests: 1000 },
summit: { farms: Infinity, aiRequests: Infinity }
};
const limit = resourceType === 'farm'
? limits[plan].farms
: limits[plan].aiRequests;
const current = resourceType === 'farm'
? usage.farmsCount
: usage.aiRequestsThisMonth;
const allowed = current < limit;
setCanCreate(allowed);
setReason(allowed ? null : `${plan} plan limit reached (${current}/${limit})`);
setLoading(false);
}
checkUsage();
}, [resourceType]);
return { canCreate, loading, reason };
}
// Usage in component
function CreateFarmButton() {
const { canCreate, loading, reason } = useUsageGuard('farm');
if (loading) return <button disabled>Loading...</button>;
return (
<button
onClick={handleCreateFarm}
disabled={!canCreate}
title={reason}
>
{canCreate ? 'Create Farm' : `Limit Reached - Upgrade to Create More`}
</button>
);
}