> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withgale.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Subscription

> Create a recurring payment subscription

# Create Subscription

Create a new subscription for recurring payments. Subscriptions are typically created after a customer completes checkout via a payment link with `payment_type: "subscription"`.

## Authentication

```bash theme={null}
Authorization: Bearer glm_test_YOUR_API_KEY
```

## Request Body

```json theme={null}
{
  "customer_id": "cus_xyz789",
  "product_id": 12345,
  "amount_cents": 9900,
  "currency": "USD",
  "interval": "monthly",
  "interval_count": 1,
  "trial_period_days": 7,
  "payment_method_id": "pm_abc123",
  "metadata": {
    "tier": "premium",
    "source": "website"
  }
}
```

## Parameters

| Parameter             | Type    | Required | Description                               |
| --------------------- | ------- | -------- | ----------------------------------------- |
| `customer_id`         | string  | Yes      | Customer ID                               |
| `product_id`          | integer | No       | Associated product ID                     |
| `merchant_product_id` | string  | No       | Your product reference ID                 |
| `amount_cents`        | integer | Yes      | Recurring charge amount in cents          |
| `currency`            | string  | Yes      | ISO 4217 currency code (e.g., "USD")      |
| `interval`            | enum    | Yes      | `daily`, `weekly`, `monthly`, or `yearly` |
| `interval_count`      | integer | No       | Number of intervals (default: 1)          |
| `trial_period_days`   | integer | No       | Free trial duration in days               |
| `payment_method_id`   | string  | Yes      | ID of stored payment method               |
| `metadata`            | object  | No       | Custom key-value pairs                    |

## Response

```json theme={null}
{
  "id": "sub_abc123xyz",
  "customer_id": "cus_xyz789",
  "status": "trialing",
  "product_id": 12345,
  "merchant_product_id": "MEMBERSHIP-PREMIUM",
  "amount_cents": 9900,
  "currency": "USD",
  "interval": "monthly",
  "interval_count": 1,
  "trial_period_days": 7,
  "trial_end": "2025-10-25T14:30:00Z",
  "current_period_start": "2025-10-18T14:30:00Z",
  "current_period_end": "2025-11-18T14:30:00Z",
  "next_billing_date": "2025-10-25T14:30:00Z",
  "cancel_at_period_end": false,
  "payment_method": {
    "type": "hsa_fsa_card",
    "last4": "1111",
    "brand": "visa"
  },
  "metadata": {
    "tier": "premium",
    "source": "website"
  },
  "created_at": "2025-10-18T14:30:00Z",
  "updated_at": "2025-10-18T14:30:00Z"
}
```

See [Subscription Object](/api-reference/objects/subscription) for complete field descriptions.

## Examples

### Monthly Subscription with Trial

```bash theme={null}
curl -X POST https://api.withgale.com/api/v2/subscriptions \
  -H "Authorization: Bearer glm_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_xyz789",
    "product_id": 12345,
    "amount_cents": 9900,
    "currency": "USD",
    "interval": "monthly",
    "trial_period_days": 14,
    "payment_method_id": "pm_abc123"
  }'
```

### Annual Subscription

```bash theme={null}
curl -X POST https://api.withgale.com/api/v2/subscriptions \
  -H "Authorization: Bearer glm_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_xyz789",
    "product_id": 12346,
    "amount_cents": 99900,
    "currency": "USD",
    "interval": "yearly",
    "payment_method_id": "pm_abc123"
  }'
```

### Bi-weekly Subscription

```bash theme={null}
curl -X POST https://api.withgale.com/api/v2/subscriptions \
  -H "Authorization: Bearer glm_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cus_xyz789",
    "merchant_product_id": "COACHING-BIWEEKLY",
    "amount_cents": 4900,
    "currency": "USD",
    "interval": "weekly",
    "interval_count": 2,
    "payment_method_id": "pm_abc123"
  }'
```

### With JavaScript

```javascript theme={null}
const createSubscription = async (customerId, planDetails) => {
  const response = await fetch('https://api.withgale.com/api/v2/subscriptions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GALE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      customer_id: customerId,
      product_id: planDetails.productId,
      amount_cents: planDetails.price * 100,
      currency: 'USD',
      interval: planDetails.interval,
      trial_period_days: planDetails.trialDays,
      payment_method_id: planDetails.paymentMethodId,
      metadata: {
        tier: planDetails.tier,
        source: 'web_app'
      }
    })
  });

  if (!response.ok) {
    throw new Error('Failed to create subscription');
  }

  const subscription = await response.json();
  console.log(`Subscription created: ${subscription.id}`);
  console.log(`Status: ${subscription.status}`);
  console.log(`Next billing: ${subscription.next_billing_date}`);
  return subscription;
};

// Usage
const subscription = await createSubscription('cus_xyz789', {
  productId: 12345,
  price: 99,
  interval: 'monthly',
  trialDays: 7,
  paymentMethodId: 'pm_abc123',
  tier: 'premium'
});
```

## Use Cases

### Membership Tiers

```javascript theme={null}
// Create subscription based on selected tier
const membershipTiers = {
  basic: {
    productId: 12345,
    amount_cents: 4900,
    features: 'basic_access'
  },
  premium: {
    productId: 12346,
    amount_cents: 9900,
    features: 'unlimited_access,priority_support'
  },
  elite: {
    productId: 12347,
    amount_cents: 19900,
    features: 'unlimited_access,priority_support,1on1_coaching'
  }
};

const subscribeMember = async (customerId, tier, paymentMethodId) => {
  const plan = membershipTiers[tier];

  return await createSubscription({
    customer_id: customerId,
    product_id: plan.productId,
    amount_cents: plan.amount_cents,
    currency: 'USD',
    interval: 'monthly',
    trial_period_days: 14,
    payment_method_id: paymentMethodId,
    metadata: {
      tier: tier,
      features: plan.features
    }
  });
};
```

### Post-Checkout Subscription Creation

```javascript theme={null}
// Create subscription after payment link is paid
app.post('/webhooks/gale', async (req, res) => {
  const event = req.body;

  if (event.type === 'payment_link.paid') {
    const { payment_link, customer, payment_method } = event.data;

    // Check if this was a subscription payment link
    if (payment_link.payment_type === 'subscription') {
      const subscription = await createSubscription({
        customer_id: customer.id,
        product_id: payment_link.product_id,
        amount_cents: payment_link.amount_cents,
        currency: payment_link.currency,
        interval: payment_link.subscription.interval,
        interval_count: payment_link.subscription.interval_count,
        trial_period_days: payment_link.subscription.trial_period_days,
        payment_method_id: payment_method.id
      });

      console.log(`Subscription ${subscription.id} created for customer ${customer.email}`);
    }
  }

  res.status(200).send('OK');
});
```

### Upgrade/Downgrade Flow

```javascript theme={null}
// Cancel old subscription and create new one
const changeSubscriptionTier = async (customerId, oldSubId, newTier) => {
  // Cancel existing subscription at period end
  await cancelSubscription(oldSubId, {
    cancel_at_period_end: true
  });

  // Create new subscription
  const newSub = await subscribeMember(
    customerId,
    newTier,
    paymentMethodId
  );

  return {
    oldSubscription: oldSubId,
    newSubscription: newSub.id,
    effectiveDate: newSub.current_period_start
  };
};
```

## Webhooks

Subscription creation triggers the following webhook event:

```json theme={null}
{
  "type": "subscription.created",
  "data": {
    "id": "sub_abc123xyz",
    "customer_id": "cus_xyz789",
    "status": "trialing",
    "amount_cents": 9900,
    "interval": "monthly",
    "trial_end": "2025-10-25T14:30:00Z"
  }
}
```

See [Webhooks Reference](/developer-manual/webhooks) for all subscription events.

## Errors

| Status Code | Error Code               | Description                   |
| ----------- | ------------------------ | ----------------------------- |
| 400         | `invalid_request`        | Missing or invalid parameters |
| 400         | `invalid_payment_method` | Payment method not valid      |
| 401         | `unauthorized`           | Invalid or missing API key    |
| 404         | `customer_not_found`     | Customer ID not found         |
| 422         | `validation_error`       | Field validation failed       |
| 429         | `rate_limit_exceeded`    | Too many requests             |

Example error:

```json theme={null}
{
  "error": {
    "code": "validation_error",
    "message": "Invalid subscription parameters",
    "details": [
      {
        "field": "amount_cents",
        "message": "Amount must be a positive integer"
      }
    ]
  }
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Offer Trial Periods" icon="gift">
    Use trials to reduce friction for new subscribers
  </Card>

  <Card title="Store Payment Method" icon="credit-card">
    Collect and verify payment method before trial ends
  </Card>

  <Card title="Handle Webhooks" icon="bell">
    Listen for subscription events for lifecycle management
  </Card>

  <Card title="Use Metadata" icon="tag">
    Track features and tiers in metadata
  </Card>
</CardGroup>

## Important Notes

<Info>
  **Payment method required.** Even with a trial period, a valid payment method must be provided and will be verified during subscription creation.
</Info>

<Warning>
  **HSA/FSA subscriptions.** Ensure recurring charges are for eligible products/services. Some HSA/FSA administrators restrict recurring charges.
</Warning>

## Related Endpoints

* [Get Subscription](/api-reference/endpoint/get-subscription) - GET /api/v2/subscriptions/{id}
* [List Subscriptions](/api-reference/endpoint/list-subscriptions) - GET /api/v2/subscriptions
* [Update Subscription](/api-reference/endpoint/update-subscription) - PUT /api/v2/subscriptions/{id}
* [Cancel Subscription](/api-reference/endpoint/cancel-subscription) - POST /api/v2/subscriptions/{id}/cancel

## Related Resources

* [Subscription Object](/api-reference/objects/subscription)
* [Webhooks Reference](/developer-manual/webhooks)
* [Payment Links](/api-reference/endpoint/create-payment-link)
