curl -X GET https://www.wiseyield.co/api/billing/subscription \
-H "Authorization: Bearer wy_YOUR_API_KEY"
const response = await fetch(
'https://www.wiseyield.co/api/billing/subscription',
{
headers: {
'Authorization': 'Bearer wy_YOUR_API_KEY'
}
}
);
const { subscription } = await response.json();
if (subscription) {
console.log(`Plan: ${subscription.plan}`);
console.log(`Status: ${subscription.status}`);
} else {
console.log('No active subscription');
}
import requests
response = requests.get(
'https://www.wiseyield.co/api/billing/subscription',
headers={'Authorization': 'Bearer wy_YOUR_API_KEY'}
)
data = response.json()
subscription = data.get('subscription')
if subscription:
print(f"Plan: {subscription['plan']}")
print(f"Status: {subscription['status']}")
else:
print("No active subscription")
{
"subscription": {
"id": "sub_abc123",
"userId": "user_xyz789",
"subscriptionId": "sub_1234567890",
"customerId": "cus_9876543210",
"priceId": "price_harvest_monthly",
"plan": "harvest",
"status": "active",
"currentPeriodStart": "2025-11-01T00:00:00.000Z",
"currentPeriodEnd": "2025-12-01T00:00:00.000Z",
"cancelAtPeriodEnd": false,
"createdAt": "2025-10-01T10:00:00.000Z",
"updatedAt": "2025-11-01T00:00:00.000Z"
}
}
{
"subscription": null
}
{
"error": "Unauthorized"
}
{
"error": "Failed to fetch subscription"
}
Get Subscription
Get the current user’s subscription status and plan details
GET
/
api
/
billing
/
subscription
curl -X GET https://www.wiseyield.co/api/billing/subscription \
-H "Authorization: Bearer wy_YOUR_API_KEY"
const response = await fetch(
'https://www.wiseyield.co/api/billing/subscription',
{
headers: {
'Authorization': 'Bearer wy_YOUR_API_KEY'
}
}
);
const { subscription } = await response.json();
if (subscription) {
console.log(`Plan: ${subscription.plan}`);
console.log(`Status: ${subscription.status}`);
} else {
console.log('No active subscription');
}
import requests
response = requests.get(
'https://www.wiseyield.co/api/billing/subscription',
headers={'Authorization': 'Bearer wy_YOUR_API_KEY'}
)
data = response.json()
subscription = data.get('subscription')
if subscription:
print(f"Plan: {subscription['plan']}")
print(f"Status: {subscription['status']}")
else:
print("No active subscription")
{
"subscription": {
"id": "sub_abc123",
"userId": "user_xyz789",
"subscriptionId": "sub_1234567890",
"customerId": "cus_9876543210",
"priceId": "price_harvest_monthly",
"plan": "harvest",
"status": "active",
"currentPeriodStart": "2025-11-01T00:00:00.000Z",
"currentPeriodEnd": "2025-12-01T00:00:00.000Z",
"cancelAtPeriodEnd": false,
"createdAt": "2025-10-01T10:00:00.000Z",
"updatedAt": "2025-11-01T00:00:00.000Z"
}
}
{
"subscription": null
}
{
"error": "Unauthorized"
}
{
"error": "Failed to fetch subscription"
}
Endpoint
GET https://www.wiseyield.co/api/billing/subscription
Authentication
Requires a valid API key withbilling:read scope.
Response
Returns the user’s subscription object or null if no subscription exists.Show Subscription Object
Show Subscription Object
Unique subscription ID
User ID who owns this subscription
Dodo Payments subscription ID
Dodo Payments customer ID
Dodo Payments product ID for the subscription plan
Plan name:
seed, sprout, harvest, grove, summitSubscription status:
active, canceled, past_due, trialing, incompleteISO 8601 datetime when current billing period started
ISO 8601 datetime when current billing period ends
Whether subscription will cancel at period end
ISO 8601 datetime when subscription was created
ISO 8601 datetime when subscription was last modified
curl -X GET https://www.wiseyield.co/api/billing/subscription \
-H "Authorization: Bearer wy_YOUR_API_KEY"
const response = await fetch(
'https://www.wiseyield.co/api/billing/subscription',
{
headers: {
'Authorization': 'Bearer wy_YOUR_API_KEY'
}
}
);
const { subscription } = await response.json();
if (subscription) {
console.log(`Plan: ${subscription.plan}`);
console.log(`Status: ${subscription.status}`);
} else {
console.log('No active subscription');
}
import requests
response = requests.get(
'https://www.wiseyield.co/api/billing/subscription',
headers={'Authorization': 'Bearer wy_YOUR_API_KEY'}
)
data = response.json()
subscription = data.get('subscription')
if subscription:
print(f"Plan: {subscription['plan']}")
print(f"Status: {subscription['status']}")
else:
print("No active subscription")
{
"subscription": {
"id": "sub_abc123",
"userId": "user_xyz789",
"subscriptionId": "sub_1234567890",
"customerId": "cus_9876543210",
"priceId": "price_harvest_monthly",
"plan": "harvest",
"status": "active",
"currentPeriodStart": "2025-11-01T00:00:00.000Z",
"currentPeriodEnd": "2025-12-01T00:00:00.000Z",
"cancelAtPeriodEnd": false,
"createdAt": "2025-10-01T10:00:00.000Z",
"updatedAt": "2025-11-01T00:00:00.000Z"
}
}
{
"subscription": null
}
{
"error": "Unauthorized"
}
{
"error": "Failed to fetch subscription"
}
Errors
Unauthorized - Missing or invalid API key
Internal Server Error - Failed to fetch subscription
Subscription Plans
5 Plan Tiers with different feature limits:Seed (€22/month)
- 1 farm
- 50 AI requests/month
- 30 chat messages/month
- Basic analytics
- Email support
Sprout (€49/month)
- 3 farms
- 200 AI requests/month
- 100 chat messages/month
- Team collaboration (5 members)
- Farm budgeting
Harvest (€89/month) — Recommended
- 7 farms
- 500 AI requests/month
- 300 chat messages/month
- Vision AI Full (50 scans/mo)
- Market Intelligence (20 queries/mo)
- Task templates
Grove (€149/month)
- 15 farms
- 1,000 AI requests/month
- 1,000 chat messages/month
- Financial AI Insights
- P&L reports, invoices
- Priority support
Summit (€299+/month)
- Unlimited farms
- Unlimited AI requests
- Unlimited chat messages
- API access
- Dedicated support
- SLA guarantee
Subscription Statuses
Use Cases
Check Subscription Status
async function getSubscriptionStatus() {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
if (!subscription) {
return { hasSubscription: false, plan: 'expired' };
}
return {
hasSubscription: true,
plan: subscription.plan,
status: subscription.status,
isActive: subscription.status === 'active',
renewsAt: subscription.currentPeriodEnd
};
}
// Usage
const status = await getSubscriptionStatus();
if (!status.hasSubscription) {
showUpgradePrompt();
}
Check Feature Access
async function canAccessFeature(feature) {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
const plan = subscription?.plan || 'expired';
const features = {
expired: ['basic_analytics'],
seed: ['basic_analytics', 'single_farm'],
sprout: ['basic_analytics', 'multiple_farms', 'export', 'farm_budgeting'],
harvest: ['advanced_analytics', 'vision_ai', 'market_intelligence', 'task_templates'],
grove: ['advanced_analytics', 'financial_ai', 'pnl_reports', 'invoices'],
summit: ['advanced_analytics', 'api_access', 'dedicated_support', 'sla']
};
return features[plan]?.includes(feature) || false;
}
// Usage
if (await canAccessFeature('advanced_analytics')) {
showAdvancedAnalytics();
}
Check Renewal Date
async function getDaysUntilRenewal() {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
if (!subscription) return null;
const renewDate = new Date(subscription.currentPeriodEnd);
const now = new Date();
const daysRemaining = Math.ceil((renewDate - now) / (1000 * 60 * 60 * 24));
return {
renewDate,
daysRemaining,
willCancel: subscription.cancelAtPeriodEnd
};
}
Check Payment Status
async function isPaymentHealthy() {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
if (!subscription) return true; // No subscription (expired)
const healthyStatuses = ['active', 'trialing'];
return healthyStatuses.includes(subscription.status);
}
// Usage
const healthy = await isPaymentHealthy();
if (!healthy) {
showPaymentWarning();
}
Best Practices
Cache Subscription Data: Cache subscription status locally and refresh periodically to reduce API calls.
Handle Null Gracefully:
subscription: null means no active subscription (expired). Don’t treat it as an error.Check Before Paid Features: Always verify subscription status before showing paid features.
Show Renewal Dates: Display
currentPeriodEnd to users so they know when they’ll be charged.Past Due Status: Subscriptions with
status: "past_due" still have access but payment failed. Prompt user to update payment method.Cancel At Period End: If
cancelAtPeriodEnd: true, subscription will end at currentPeriodEnd. Show this clearly to user.Integration Examples
Subscription Status Card
function SubscriptionStatusCard() {
const [subscription, setSubscription] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadSubscription() {
try {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
setSubscription(subscription);
} finally {
setLoading(false);
}
}
loadSubscription();
}, []);
if (loading) return <div>Loading...</div>;
const plan = subscription?.plan || 'expired';
const status = subscription?.status || 'active';
return (
<div className="subscription-card">
<h2>Current Plan</h2>
<PlanBadge plan={plan} />
<StatusBadge status={status} />
{subscription && (
<>
<p>Renews: {new Date(subscription.currentPeriodEnd).toLocaleDateString()}</p>
{subscription.cancelAtPeriodEnd && (
<div className="warning">
Your subscription will end on {new Date(subscription.currentPeriodEnd).toLocaleDateString()}
</div>
)}
{status === 'past_due' && (
<div className="error">
Payment failed. Please update your payment method.
</div>
)}
</>
)}
{!subscription && (
<button onClick={() => router.push('/pricing')}>
Upgrade Plan
</button>
)}
</div>
);
}
Feature Gate Component
function FeatureGate({ feature, plan, children, fallback }) {
const [hasAccess, setHasAccess] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function checkAccess() {
try {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
const userPlan = subscription?.plan || 'expired';
const planHierarchy = ['expired', 'seed', 'sprout', 'harvest', 'grove', 'summit'];
const requiredIndex = planHierarchy.indexOf(plan);
const userIndex = planHierarchy.indexOf(userPlan);
setHasAccess(userIndex >= requiredIndex);
} finally {
setLoading(false);
}
}
checkAccess();
}, [plan]);
if (loading) return <div>Loading...</div>;
return hasAccess ? children : (fallback || <UpgradePrompt requiredPlan={plan} />);
}
// Usage
<FeatureGate feature="advanced_analytics" plan="grove">
<AdvancedAnalyticsDashboard />
</FeatureGate>
Plan Comparison Hook
function useSubscription() {
const [subscription, setSubscription] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchSubscription() {
try {
const response = await fetch('/api/billing/subscription', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const { subscription } = await response.json();
setSubscription(subscription);
} finally {
setLoading(false);
}
}
fetchSubscription();
}, []);
const plan = subscription?.plan || 'expired';
return {
subscription,
loading,
plan,
isPro: ['harvest', 'grove', 'summit'].includes(plan),
isEnterprise: plan === 'summit',
hasAccess: (requiredPlan) => {
const hierarchy = ['expired', 'seed', 'sprout', 'harvest', 'grove', 'summit'];
return hierarchy.indexOf(plan) >= hierarchy.indexOf(requiredPlan);
}
};
}
// Usage in component
function Dashboard() {
const { plan, isPro, hasAccess } = useSubscription();
return (
<div>
<h1>Dashboard - {plan} Plan</h1>
{hasAccess('grove') && <AdvancedFeatures />}
{isPro && <PrioritySupport />}
</div>
);
}
Related Endpoints
- Create Checkout Session - POST to start subscription purchase
- Create Portal Session - POST to manage subscription
- Get Invoices - GET payment history
- Get Usage - GET current usage metrics
⌘I