> ## 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.

# Get Subscription

> Get the current user's subscription status and plan details

## Endpoint

```
GET https://www.wiseyield.co/api/billing/subscription
```

## Authentication

Requires a valid API key with `billing:read` scope.

## Response

Returns the user's subscription object or null if no subscription exists.

<ResponseField name="subscription" type="object | null">
  <Expandable title="Subscription Object">
    <ResponseField name="id" type="string">
      Unique subscription ID
    </ResponseField>

    <ResponseField name="userId" type="string">
      User ID who owns this subscription
    </ResponseField>

    <ResponseField name="subscriptionId" type="string">
      Dodo Payments subscription ID
    </ResponseField>

    <ResponseField name="customerId" type="string">
      Dodo Payments customer ID
    </ResponseField>

    <ResponseField name="productId" type="string">
      Dodo Payments product ID for the subscription plan
    </ResponseField>

    <ResponseField name="plan" type="string">
      Plan name: `seed`, `sprout`, `harvest`, `grove`, `summit`
    </ResponseField>

    <ResponseField name="status" type="string">
      Subscription status: `active`, `canceled`, `past_due`, `trialing`, `incomplete`
    </ResponseField>

    <ResponseField name="currentPeriodStart" type="string">
      ISO 8601 datetime when current billing period started
    </ResponseField>

    <ResponseField name="currentPeriodEnd" type="string">
      ISO 8601 datetime when current billing period ends
    </ResponseField>

    <ResponseField name="cancelAtPeriodEnd" type="boolean">
      Whether subscription will cancel at period end
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO 8601 datetime when subscription was created
    </ResponseField>

    <ResponseField name="updatedAt" type="string">
      ISO 8601 datetime when subscription was last modified
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET https://www.wiseyield.co/api/billing/subscription \
    -H "Authorization: Bearer wy_YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  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');
  }
  ```

  ```python Python theme={null}
  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")
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Success (Active Subscription) theme={null}
  {
    "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"
    }
  }
  ```

  ```json 200 Success (No Subscription) theme={null}
  {
    "subscription": null
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": "Unauthorized"
  }
  ```

  ```json 500 Internal Server Error theme={null}
  {
    "error": "Failed to fetch subscription"
  }
  ```
</ResponseExample>

## Errors

<ResponseField name="401" type="error">
  Unauthorized - Missing or invalid API key
</ResponseField>

<ResponseField name="500" type="error">
  Internal Server Error - Failed to fetch subscription
</ResponseField>

## 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

<ParamField name="active" type="status">
  Subscription is active and in good standing
</ParamField>

<ParamField name="trialing" type="status">
  In trial period (no payment required yet)
</ParamField>

<ParamField name="past_due" type="status">
  Payment failed, subscription still active with grace period
</ParamField>

<ParamField name="canceled" type="status">
  Subscription has been canceled
</ParamField>

<ParamField name="incomplete" type="status">
  First payment attempt failed, awaiting retry
</ParamField>

## Use Cases

### Check Subscription Status

```javascript theme={null}
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

```javascript theme={null}
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

```javascript theme={null}
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

```javascript theme={null}
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

<Tip>
  **Cache Subscription Data**: Cache subscription status locally and refresh periodically to reduce API calls.
</Tip>

<Tip>
  **Handle Null Gracefully**: `subscription: null` means no active subscription (expired). Don't treat it as an error.
</Tip>

<Tip>
  **Check Before Paid Features**: Always verify subscription status before showing paid features.
</Tip>

<Tip>
  **Show Renewal Dates**: Display `currentPeriodEnd` to users so they know when they'll be charged.
</Tip>

<Warning>
  **Past Due Status**: Subscriptions with `status: "past_due"` still have access but payment failed. Prompt user to update payment method.
</Warning>

<Warning>
  **Cancel At Period End**: If `cancelAtPeriodEnd: true`, subscription will end at `currentPeriodEnd`. Show this clearly to user.
</Warning>

## Integration Examples

### Subscription Status Card

```javascript theme={null}
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

```javascript theme={null}
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

```javascript theme={null}
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](/api-reference/billing/create-checkout-session) - POST to start subscription purchase
* [Create Portal Session](/api-reference/billing/create-portal-session) - POST to manage subscription
* [Get Invoices](/api-reference/billing/get-invoices) - GET payment history
* [Get Usage](/api-reference/billing/get-usage) - GET current usage metrics
