APM

>Agent Skill

@adrianwedd/create-discount-code

skilldevelopment

Create discount codes for promotions, launches, beta readers, or giveaways. Supports percentage/fixed discounts, usage limits, expiry dates, and product restrictions. Triggers on "create discount", "promo code", "coupon", "launch code", or similar queries.

apm::install
$apm install @adrianwedd/create-discount-code
apm::allowed-tools
BashRead
apm::skill.md
---
name: create-discount-code
description: Create discount codes for promotions, launches, beta readers, or giveaways. Supports percentage/fixed discounts, usage limits, expiry dates, and product restrictions. Triggers on "create discount", "promo code", "coupon", "launch code", or similar queries.
allowed-tools: Bash, Read
---

# Create Discount Code Skill

**Purpose:** Fast discount code creation for marketing and promotions

## What This Skill Does

Creates discount codes in Lemon Squeezy with:
1. Code name (e.g., LAUNCH50, BETA2026)
2. Discount type (percentage or fixed amount)
3. Discount amount (e.g., 50% off or $5 off)
4. Usage limits (total redemptions, per-customer limit)
5. Expiry date (optional)
6. Product restrictions (all products or specific ones)

## When to Use This Skill

**Common use cases:**
- Launch promotions: "Create LAUNCH50 for 50% off"
- Beta reader rewards: "Create BETA100 for 100% off, limit 20"
- Podcast appearances: "Create PODCAST30 for 30% off"
- Social media giveaways: "Create GIVEAWAY for free access"
- Seasonal sales: "Create HOLIDAY25 for 25% off"
- Affiliate codes: "Create PARTNER20 for 20% off"

## API Authentication

Uses `LEMON_SQUEEZY_API_KEY` and `LEMON_SQUEEZY_STORE_ID` environment variables.

## Usage Examples

**Example 1: Launch promotion**
```
User: Create a 50% off code called LAUNCH50, limit 100 uses, expires in 7 days
Assistant: [Uses create-discount-code skill]
```

**Example 2: Beta reader reward**
```
User: Create BETA2026 for 100% off, limit to 20 people
Assistant: [Creates free code with redemption limit]
```

**Example 3: Podcast appearance**
```
User: I'm on a podcast next week. Create a 30% discount code
Assistant: [Creates PODCAST30 code, suggests expiry date]
```

## Implementation

### Create Discount Code API

**Endpoint:** `POST https://api.lemonsqueezy.com/v1/discounts`

**Required fields:**
- `store_id` - Your store ID
- `name` - Internal name (e.g., "Launch 50% Off")
- `code` - The actual code users type (e.g., "LAUNCH50")
- `amount` - Discount amount (percentage: 1-100, or cents for fixed)
- `amount_type` - "percent" or "fixed"

**Optional fields:**
- `duration` - "once", "repeating", or "forever"
- `duration_in_months` - How many months (for repeating)
- `starts_at` - When code becomes active (ISO 8601)
- `expires_at` - When code expires (ISO 8601)
- `max_redemptions` - Total usage limit (null = unlimited)
- `limit_redemptions_per_customer` - Per-customer limit
- `is_limited_to_products` - true/false
- `product_ids` - Array of product IDs (if limited)

**Example request (50% off, 7 days, 100 uses):**
```bash
curl -X POST "https://api.lemonsqueezy.com/v1/discounts" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Authorization: Bearer $LEMON_SQUEEZY_API_KEY" \
  -d '{
    "data": {
      "type": "discounts",
      "attributes": {
        "store_id": YOUR_STORE_ID,
        "name": "Launch Week Promotion",
        "code": "LAUNCH50",
        "amount": 50,
        "amount_type": "percent",
        "duration": "once",
        "max_redemptions": 100,
        "expires_at": "2026-01-12T23:59:59Z"
      }
    }
  }'
```

**Example request (100% off, beta readers):**
```bash
curl -X POST "https://api.lemonsqueezy.com/v1/discounts" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Authorization: Bearer $LEMON_SQUEEZY_API_KEY" \
  -d '{
    "data": {
      "type": "discounts",
      "attributes": {
        "store_id": YOUR_STORE_ID,
        "name": "Beta Reader Reward",
        "code": "BETA2026",
        "amount": 100,
        "amount_type": "percent",
        "duration": "once",
        "max_redemptions": 20
      }
    }
  }'
```

**Example request ($5 off, fixed amount):**
```bash
curl -X POST "https://api.lemonsqueezy.com/v1/discounts" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Authorization: Bearer $LEMON_SQUEEZY_API_KEY" \
  -d '{
    "data": {
      "type": "discounts",
      "attributes": {
        "store_id": YOUR_STORE_ID,
        "name": "Five Dollar Discount",
        "code": "SAVE5",
        "amount": 500,
        "amount_type": "fixed",
        "duration": "once"
      }
    }
  }'
```

**Response structure:**
```json
{
  "data": {
    "type": "discounts",
    "id": "12345",
    "attributes": {
      "store_id": 12345,
      "name": "Launch Week Promotion",
      "code": "LAUNCH50",
      "amount": 50,
      "amount_type": "percent",
      "status": "published",
      "status_formatted": "Published",
      "duration": "once",
      "duration_in_months": null,
      "is_limited_redemptions": true,
      "max_redemptions": 100,
      "redemptions_count": 0,
      "is_limited_to_products": false,
      "starts_at": null,
      "expires_at": "2026-01-12T23:59:59.000000Z",
      "test_mode": false,
      "created_at": "2026-01-05T10:00:00.000000Z",
      "updated_at": "2026-01-05T10:00:00.000000Z"
    }
  }
}
```

## Discount Code Templates

### Template 1: Launch Promotion
```json
{
  "name": "Launch Week - 50% Off",
  "code": "LAUNCH50",
  "amount": 50,
  "amount_type": "percent",
  "duration": "once",
  "max_redemptions": 100,
  "expires_at": "+7 days"
}
```

**Use case:** Product launch, podcast appearance, press coverage

### Template 2: Beta Reader / Reviewer
```json
{
  "name": "Beta Reader Reward",
  "code": "BETA100",
  "amount": 100,
  "amount_type": "percent",
  "duration": "once",
  "max_redemptions": 20,
  "expires_at": null
}
```

**Use case:** Beta readers, reviewers, influencers
**Cost:** $0 (100% discount codes are free)

### Template 3: Early Bird
```json
{
  "name": "Early Bird Special",
  "code": "EARLYBIRD",
  "amount": 30,
  "amount_type": "percent",
  "duration": "once",
  "max_redemptions": 500,
  "expires_at": "+30 days"
}
```

**Use case:** Pre-launch list, early supporters

### Template 4: Seasonal Sale
```json
{
  "name": "End of Financial Year Sale",
  "code": "EOFY25",
  "amount": 25,
  "amount_type": "percent",
  "duration": "once",
  "max_redemptions": null,
  "starts_at": "2026-06-01T00:00:00Z",
  "expires_at": "2026-06-30T23:59:59Z"
}
```

**Use case:** Holiday sales, seasonal promotions

### Template 5: Affiliate / Partner
```json
{
  "name": "Partner Discount",
  "code": "PARTNER20",
  "amount": 20,
  "amount_type": "percent",
  "duration": "once",
  "max_redemptions": null,
  "expires_at": null
}
```

**Use case:** Ongoing affiliate codes (track with unique codes per partner)

### Template 6: First-Time Customer
```json
{
  "name": "Welcome Discount",
  "code": "WELCOME10",
  "amount": 10,
  "amount_type": "percent",
  "duration": "once",
  "limit_redemptions_per_customer": 1
}
```

**Use case:** Email capture, welcome series

### Template 7: Fixed Amount Off
```json
{
  "name": "Five Dollar Discount",
  "code": "SAVE5",
  "amount": 500,
  "amount_type": "fixed",
  "duration": "once"
}
```

**Note:** Amount is in cents (500 = $5.00)

## Output Format

After creating a discount code, present results like this:

```markdown
# ✅ Discount Code Created

## Code Details

**Code:** `LAUNCH50`
**Type:** 50% off
**Status:** Active ✅

## Usage

**Share this with customers:**
> Use code **LAUNCH50** at checkout for 50% off!
> Valid until January 12, 2026
> Limited to first 100 customers

**Checkout URL with code:**
https://your-store.lemonsqueezy.com/checkout/buy/PRODUCT_ID?checkout[discount_code]=LAUNCH50

## Limits

- **Max uses:** 100
- **Uses so far:** 0
- **Expires:** January 12, 2026 at 11:59 PM
- **Per-customer limit:** Unlimited

## Tracking

View redemptions: https://app.lemonsqueezy.com/discounts/12345

## Update/Delete

- Edit code: Use Lemon Squeezy dashboard
- Delete code: `DELETE /v1/discounts/12345`
- Disable code: Change status to "draft"

---

## 🎯 Marketing Copy (Ready to Use)

**Social media:**
```
🎉 Launch Week Special! Get 50% off with code LAUNCH50
Limited to first 100 customers. Ends Jan 12.
[Your checkout link]
```

**Email:**
```
Subject: [Launch Week] 50% Off Inside 🚀

Hi there,

To celebrate our launch, I'm offering 50% off to the first 100 customers.

Use code LAUNCH50 at checkout.

This offer expires January 12, so don't miss out!

[CTA Button: Get 50% Off]
```

**Podcast/Video mention:**
```
"If you want to grab a copy, I've created a special code for listeners:
LAUNCH50 - that's L-A-U-N-C-H-5-0 for 50% off.
It's good for the first 100 people and expires next week."
```
```

## Date/Time Helpers

**Common expiry patterns:**

```bash
# 7 days from now
expires_at=$(date -u -d "+7 days" +"%Y-%m-%dT23:59:59Z")

# End of month
expires_at=$(date -u -d "$(date +%Y-%m-01) +1 month -1 day" +"%Y-%m-%dT23:59:59Z")

# Specific date
expires_at="2026-06-30T23:59:59Z"

# No expiry
expires_at=null
```

**Common start dates:**

```bash
# Start immediately
starts_at=null

# Start tomorrow
starts_at=$(date -u -d "+1 day" +"%Y-%m-%dT00:00:00Z")

# Start specific date
starts_at="2026-06-01T00:00:00Z"
```

## Validation Rules

**Code format:**
- 2-256 characters
- Letters, numbers, hyphens, underscores
- Case-insensitive (LAUNCH50 = launch50)
- No spaces

**Amount limits:**
- Percentage: 1-100
- Fixed: Any positive integer (in cents)

**Redemption limits:**
- `null` = unlimited
- Must be positive integer

**Product restrictions:**
```json
{
  "is_limited_to_products": true,
  "product_ids": [123, 456]
}
```

## Error Handling

**Code already exists:**
```markdown
❌ Error: Code "LAUNCH50" already exists

Existing code details:
- Created: January 1, 2026
- Uses: 45/100
- Status: Active

Options:
1. Choose different code (e.g., LAUNCH50B)
2. Delete old code and recreate
3. Edit existing code in dashboard
```

**Invalid amount:**
```markdown
❌ Error: Invalid discount amount

For percentage: Must be 1-100
For fixed: Must be positive integer in cents (e.g., 500 = $5)

You provided: 150% (invalid)
Did you mean: 50% off?
```

**Store ID missing:**
```markdown
❌ Error: LEMON_SQUEEZY_STORE_ID not configured

Set in Cloudflare:
npx wrangler pages secret put LEMON_SQUEEZY_STORE_ID
```

## Security Considerations

**Don't create codes that:**
- Give >90% off publicly (reserve 100% for targeted use)
- Have no expiry and no limit (cost control)
- Are too generic (CODE, DISCOUNT, SALE)

**Do:**
- Set reasonable limits (100-500 uses)
- Use expiry dates for time-bound promos
- Track usage regularly
- Use unique codes per channel (track which works)

## Bulk Creation

**Create multiple codes at once:**

```bash
# Example: Create 10 unique affiliate codes
for i in {1..10}; do
  curl -X POST "https://api.lemonsqueezy.com/v1/discounts" \
    -H "Authorization: Bearer $API_KEY" \
    -d '{
      "data": {
        "type": "discounts",
        "attributes": {
          "store_id": STORE_ID,
          "name": "Affiliate Code '$i'",
          "code": "AFFILIATE'$i'",
          "amount": 20,
          "amount_type": "percent"
        }
      }
    }'
done
```

## Analytics Integration

**Track code performance:**

1. Create unique codes per channel:
   - PODCAST30 (podcast)
   - TWITTER30 (Twitter)
   - EMAIL30 (email list)

2. Compare redemptions:
```markdown
Channel Performance (30% off codes):
- PODCAST30: 45 uses
- TWITTER30: 23 uses
- EMAIL30: 67 uses

Winner: Email (67 conversions)
```

## Related Skills

- `/sales-dashboard` - See discount usage in revenue reports
- `/customer-lookup` - Check if customer used discount
- List all discounts: `GET /v1/discounts?filter[store_id]=STORE_ID`

## API Documentation

Full Lemon Squeezy Discounts API:
- Create: https://docs.lemonsqueezy.com/api/discounts#create-a-discount
- Update: https://docs.lemonsqueezy.com/api/discounts#update-a-discount
- Delete: https://docs.lemonsqueezy.com/api/discounts#delete-a-discount
- List: https://docs.lemonsqueezy.com/api/discounts#list-all-discounts

## Testing

**Test discount codes:**

1. Create code in test mode:
```json
{
  "test_mode": true,
  "code": "TEST50",
  "amount": 50,
  "amount_type": "percent"
}
```

2. Use in checkout with test card:
   - Card: 4242 4242 4242 4242
   - Expiry: Any future date
   - CVC: Any 3 digits

3. Verify discount applied correctly

4. Check redemption count increased