Skip to main content

External Discount Codes

Overview

External Discount Codes allow you to create discounts dynamically through APIs without pre-configuring discount codes in the admin portal. This feature is perfect for programmatic discount management, API integrations, and dynamic pricing strategies.

Key Features

  • Dynamic Creation: No need to pre-create discount codes in the admin portal
  • API-Based: Create discounts programmatically via Merchant API or User API
  • Flexible Types: Support both fixed amount and percentage discounts
  • One-time or Recurring: Choose between single-use or recurring discounts
  • Automatic Code Generation: System automatically generates unique discount codes
  • Metadata Support: Attach custom metadata for tracking and analysis

When to Use External Discount Codes

Perfect for:
  • API Integrations: Third-party systems that need to apply discounts automatically
  • Dynamic Pricing: Real-time price adjustments based on user attributes or market conditions
  • Personalized Offers: Custom discounts for specific users without creating codes in advance
  • A/B Testing: Test different discount strategies programmatically
  • Promotion Automation: Automated discount creation based on business rules
Not suitable for:
  • Public Marketing Campaigns: Use Standard or Batch discount codes instead
  • Checkout Page: Checkout API doesn’t support external discounts (use pre-created codes)
  • Bulk Tracking: When you need to track usage across many customers

External vs Internal Discount Codes

Quick Comparison

FeatureInternal Discount CodesExternal Discount Codes
Creation MethodAdmin portalAPI only
Pre-configurationRequiredNot needed
Code FormatCustom nameAuto-generated (excode_*)
ReusabilityCan be reusedSingle-use (per user)
Usage LimitsSupportedNot supported
API SupportAll APIsMerchant & User API only

When to Choose Which

Use Internal Discount Codes when:
  • Creating public marketing campaigns
  • Need usage limits and restrictions
  • Want customers to enter codes manually
  • Need to track bulk usage
Use External Discount Codes when:
  • Integrating with third-party systems
  • Need programmatic discount creation
  • Providing personalized offers
  • Dynamic pricing requirements

API Support

Supported APIs

APIExternal Discount SupportNotes
Merchant API✅ Full supportComplete external discount functionality
User API✅ Full supportComplete external discount functionality
Checkout API❌ Not supportedOnly supports pre-created internal discount codes
⚠️ Important: Checkout API doesn’t support external discounts. If you need discounts on checkout pages, pre-create discount codes in the admin portal and use the discountCode parameter.

How External Discounts Work

Automatic Code Generation

When you create an external discount via API, the system automatically:
  1. Generates a unique discount code (format: excode_{merchantId}_{userId}_{source}_{timestamp}{random})
  2. Creates the discount with your specified rules
  3. Activates the discount immediately
  4. Applies it to the subscription or purchase
Example Generated Code:
excode_123_456_789_1704355200000Xy7k9mN3

Discount Parameters

When creating an external discount, you specify:
ParameterTypeDescriptionExample
recurringbooleanOne-time or recurring discountfalse = one-time
discountAmountintegerFixed discount amount (in cents)1000 = $10.00
discountPercentageintegerPercentage discount (100 = 1%)2000 = 20%
cycleLimitintegerNumber of billing cycles (recurring only)3 = 3 months
endTimeintegerExpiration time (Unix timestamp, recurring only)1767225599
metadataobjectCustom metadata for tracking{"campaign": "summer_sale"}

Usage Scenarios

Scenario 1: First Order Discount (One-time)

Give new customers a 20% discount on their first purchase. Example:
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": false,
    "discountPercentage": 2000,
    "metadata": {
      "campaign": "first_order_20_off"
    }
  }
}
Result: Customer gets 20% off first payment only.

Scenario 2: Recurring Discount (First 3 Months)

Offer 15% off for the first 3 billing cycles. Example:
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": true,
    "discountPercentage": 1500,
    "cycleLimit": 3,
    "metadata": {
      "campaign": "first_quarter_promotion"
    }
  }
}
Result: Customer gets 15% off for months 1-3, then pays full price.

Scenario 3: VIP Lifetime Discount

Provide permanent 10% discount for VIP customers. Example:
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": true,
    "discountPercentage": 1000,
    "cycleLimit": 0,
    "metadata": {
      "user_type": "vip",
      "reason": "lifetime_discount"
    }
  }
}
Result: Customer gets 10% off every billing cycle indefinitely.

Scenario 4: Time-Limited Campaign

Offer 25% discount until end of year. Example:
// Calculate end time (Dec 31, 2025 23:59:59 UTC)
const endTime = new Date('2025-12-31T23:59:59Z').getTime() / 1000;

{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": true,
    "discountPercentage": 2500,
    "endTime": endTime,
    "metadata": {
      "campaign": "year_end_sale_2025"
    }
  }
}
Result: Customer gets 25% off until Dec 31, 2025, then pays full price.

Creating External Discounts

Subscription Creation

When creating a subscription via API, include the discount parameter: Merchant API: POST /api/merchant/subscription/create_submit
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": false,
    "discountAmount": 1000
  },
  "confirmTotalAmount": 9000,
  "confirmCurrency": "USD"
}

Subscription Update

Apply discount when upgrading or downgrading a subscription: Merchant API: POST /api/merchant/subscription/update_submit
{
  "subscriptionId": "sub_xxxxx",
  "newPlanId": 789,
  "discount": {
    "recurring": true,
    "discountPercentage": 1500,
    "cycleLimit": 6
  },
  "confirmTotalAmount": 8500,
  "confirmCurrency": "USD"
}

Subscription Renewal

Apply discount during subscription renewal: Merchant API: POST /api/merchant/subscription/renew
{
  "subscriptionId": "sub_xxxxx",
  "discount": {
    "recurring": false,
    "discountAmount": 500
  }
}

Discount Parameters Explained

Fixed Amount vs Percentage

Fixed Amount (discountAmount):
  • Use when you want a specific dollar amount off
  • Example: “$10 off” regardless of order total
  • Best for: Consistent promotional offers
Percentage (discountPercentage):
  • Use when you want a percentage off
  • Format: 100 = 1%, 1000 = 10%, 10000 = 100%
  • Best for: Scaling discounts with order value
⚠️ Priority: If both are specified, discountAmount takes priority.

One-time vs Recurring

One-time (recurring: false):
  • Discount applies only to the first invoice
  • Perfect for: Welcome offers, sign-up bonuses
  • Cannot use cycleLimit or endTime
Recurring (recurring: true):
  • Discount applies to multiple billing cycles
  • Perfect for: Long-term promotions, VIP discounts
  • Can use cycleLimit or endTime to control duration

Cycle Limit

What it does: Limits how many billing cycles the discount applies Examples:
  • cycleLimit: 1 - First cycle only
  • cycleLimit: 3 - First 3 cycles
  • cycleLimit: 0 - No limit (until endTime or subscription ends)
Only works when: recurring: true

End Time

What it does: Sets expiration date for the discount Format: Unix timestamp (seconds since Jan 1, 1970) Example:
// Discount expires Dec 31, 2025 at 11:59:59 PM UTC
const endTime = new Date('2025-12-31T23:59:59Z').getTime() / 1000;
Only works when: recurring: true

Metadata

What it does: Stores custom information about the discount Use cases:
  • Track discount source
  • Store campaign information
  • Record business logic tags
  • Enable reporting and analytics
Example:
{
  "metadata": {
    "campaign": "summer_sale",
    "source": "partner_api",
    "reason": "vip_customer",
    "notes": "Special discount for premium users"
  }
}

Best Practices

1. Always Preview Before Submitting

Use the preview API to check discount calculations before finalizing:
// Step 1: Preview
const preview = await createSubscriptionPreview({
  planId: 123,
  discount: {
    recurring: true,
    discountPercentage: 2000
  }
});

// Step 2: Confirm with preview amount
const result = await createSubscription({
  planId: 123,
  discount: {
    recurring: true,
    discountPercentage: 2000
  },
  confirmTotalAmount: preview.totalAmount,
  confirmCurrency: preview.currency
});

2. Choose the Right Discount Type

Use Fixed Amount when:
  • Offering consistent dollar-off promotions
  • Order values vary significantly
  • Need precise control over discount amount
Use Percentage when:
  • Discount should scale with order value
  • Running percentage-based campaigns
  • Want simpler calculation

3. Set Appropriate Limits

Cycle Limit Guidelines:
  • Short-term: 1-3 cycles
  • Quarterly: 3 cycles
  • Semi-annual: 6 cycles
  • Annual: 12 cycles
  • Unlimited: 0 (use carefully)

4. Use Metadata Effectively

Track important information in metadata:
  • Campaign name
  • Discount source
  • User segment
  • Business reason
This helps with reporting and analysis later.

5. Handle Errors Properly

Common errors to handle:
  • Invalid discount percentage (must be 0-100%)
  • Missing required parameters
  • Invalid time settings
  • Conflicting discount types

Validation Rules

Required Parameters

You must specify at least one discount type:
  • discountAmount OR
  • discountPercentage

Discount Percentage

Valid range: Greater than 0 and less than or equal to 10000
  • 100 = 1%
  • 1000 = 10%
  • 10000 = 100%
Invalid examples:
  • 0 - Cannot be zero
  • 15000 - Cannot exceed 100%

Discount Amount

Must be: Greater than 0 (in cents) Automatically limited: System won’t allow discount to exceed order total

Recurring Discount Rules

cycleLimit:
  • Only valid when recurring: true
  • Must be greater than or equal to 0
  • 0 = unlimited (until endTime or subscription ends)
endTime:
  • Only valid when recurring: true
  • Must be a future time (Unix timestamp)
  • Must be greater than or equal to current time

Common Use Cases

Use Case 1: API Integration Discount

Third-party system automatically applies discount based on user tier:
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": true,
    "discountPercentage": 1500,
    "cycleLimit": 0,
    "metadata": {
      "source": "partner_api",
      "user_tier": "gold",
      "partner_id": "partner_123"
    }
  }
}

Use Case 2: Dynamic Pricing

Adjust price based on market conditions or user behavior:
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": false,
    "discountPercentage": 2500,
    "metadata": {
      "campaign": "dynamic_pricing",
      "discount_reason": "high_value_user",
      "market_condition": "competitive"
    }
  }
}

Use Case 3: Win-Back Campaign

Offer discount to win back churned customers:
{
  "planId": 123,
  "userId": 456,
  "discount": {
    "recurring": true,
    "discountPercentage": 3000,
    "cycleLimit": 3,
    "metadata": {
      "campaign": "win_back",
      "churn_reason": "price",
      "win_back_date": "2025-01-15"
    }
  }
}

Limitations and Considerations

Checkout API Restriction

Important: Checkout API does NOT support external discounts. If you need discounts on checkout pages:
  1. Option 1: Pre-create discount codes in admin portal, then use discountCode parameter
  2. Option 2: Use Merchant API or User API instead of Checkout API

Single User Only

External discounts are created per user/subscription:
  • Cannot be shared across multiple users
  • Cannot set usage limits (quantity limits)
  • Each discount is user-specific

Cannot Combine with Internal Codes

If both discountCode (internal) and discount (external) are provided:
  • External discount takes priority
  • Internal discount code is ignored

Troubleshooting

Error: “one of discountAmount or discountPercentage should specified”

Problem: Missing discount type specification Solution: Provide either discountAmount or discountPercentage
// ❌ Wrong
{
  "discount": {
    "recurring": true
  }
}

// ✅ Correct
{
  "discount": {
    "recurring": true,
    "discountPercentage": 2000
  }
}

Error: “invalid discountPercentage”

Problem: Percentage out of valid range (0-10000) Solution: Use valid percentage value
// ❌ Wrong (150% is invalid)
{
  "discountPercentage": 15000
}

// ✅ Correct (100% is maximum)
{
  "discountPercentage": 10000
}

Error: “cycleLimit not available as recurring not enable”

Problem: Trying to set cycle limit without enabling recurring Solution: Set recurring: true or remove cycleLimit
// ❌ Wrong
{
  "discount": {
    "recurring": false,
    "discountPercentage": 2000,
    "cycleLimit": 3
  }
}

// ✅ Correct
{
  "discount": {
    "recurring": true,
    "discountPercentage": 2000,
    "cycleLimit": 3
  }
}

Error: “endTime not available as recurring not enable”

Problem: Trying to set end time without enabling recurring Solution: Set recurring: true or remove endTime

API Reference

For detailed API documentation, see: