---
title: "Ko-fi Integration Testing Guide"
description: "Testing procedures for the Ko-fi to Paper Dynasty n8n workflow with 8 cURL test scenarios, validation scripts, checklists for security/performance/edge cases, and production monitoring guidelines."
type: runbook
domain: productivity
tags: [n8n, ko-fi, paper-dynasty, testing, webhook, curl, validation]
---

# Ko-fi → Paper Dynasty Testing Guide

Comprehensive testing guide for the Ko-fi integration workflow.

## Testing Phases

### Phase 1: Local Development Testing

Test n8n workflow logic without involving Ko-fi.

**Objective:** Validate workflow nodes process data correctly

**Method:** Manual execution in n8n UI

**Steps:**
1. Open workflow in n8n
2. Click "Execute Workflow" button
3. Workflow will wait at Webhook node
4. Use cURL or Postman to send test payload
5. Review execution results node-by-node

---

### Phase 2: Webhook Testing with cURL

Test webhook endpoint with simulated Ko-fi payloads.

**Objective:** Verify webhook receives and parses Ko-fi data

**Test URL:** `https://n8n.manticorum.com/webhook-test/kofi-paperdy`

---

### Phase 3: Ko-fi Test Webhook

Use Ko-fi's built-in webhook tester.

**Objective:** Validate integration with Ko-fi's actual webhook system

**Steps:**
1. Ko-fi → Settings → API → Webhooks
2. Set webhook URL to test path
3. Click "Test Webhook" button
4. Review n8n execution logs

---

### Phase 4: Test Purchases

Make real purchases with test products.

**Objective:** End-to-end validation with real Ko-fi data

**Steps:**
1. Create test products in Ko-fi shop ($0.01 minimum)
2. Make test purchases
3. Verify packs granted in Paper Dynasty
4. Check Discord notifications

---

### Phase 5: Production Deployment

Switch to production webhook path and monitor.

**Objective:** Deploy to production with confidence

**Steps:**
1. Switch webhook path from `/webhook-test/` to `/webhook/`
2. Update Ko-fi webhook URL
3. Monitor first 10 transactions manually
4. Verify all flows working correctly

---

## Test Payloads

### Test 1: Basic Order with Discord User ID

**Scenario:** User with linked Discord account purchases 5 standard packs

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-001-discord",
    "timestamp": "2025-11-13T12:00:00Z",
    "type": "Shop Order",
    "is_public": true,
    "from_name": "Test Customer Discord",
    "message": "Thanks for the packs!",
    "amount": "5.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-001",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": false,
    "is_first_subscription_payment": false,
    "kofi_transaction_id": "test-001-discord-userid",
    "shop_items": [
      {
        "direct_link_code": "pack-standard-5",
        "variation_name": "5-Pack Standard",
        "quantity": 1
      }
    ],
    "tier_name": null,
    "shipping": null,
    "discord_username": "TestUser#1234",
    "discord_userid": "012345678901234567"
  }'
```

**Expected Result:**
- ✅ Token validated
- ✅ Team found via discord_userid → gmid lookup
- ✅ 5 standard packs granted to team
- ✅ Success Discord notification sent

---

### Test 2: Order with Team Abbrev in Message

**Scenario:** User without Discord link includes team abbreviation in message

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-002-abbrev",
    "timestamp": "2025-11-13T12:05:00Z",
    "type": "Shop Order",
    "is_public": true,
    "from_name": "Test Customer Abbrev",
    "message": "Team: SKB - Thanks!",
    "amount": "10.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-002",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": false,
    "is_first_subscription_payment": false,
    "kofi_transaction_id": "test-002-team-abbrev",
    "shop_items": [
      {
        "direct_link_code": "pack-premium-10",
        "variation_name": "10-Pack Premium",
        "quantity": 1
      }
    ],
    "tier_name": null,
    "shipping": null,
    "discord_username": null,
    "discord_userid": null
  }'
```

**Expected Result:**
- ✅ Token validated
- ✅ Team "SKB" extracted from message
- ✅ Team found via abbrev lookup
- ✅ 10 premium packs granted to team
- ✅ Success Discord notification sent

---

### Test 3: Multiple Items in Single Order

**Scenario:** User purchases multiple product types in one transaction

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-003-multi",
    "timestamp": "2025-11-13T12:10:00Z",
    "type": "Shop Order",
    "is_public": true,
    "from_name": "Test Customer Multi",
    "message": "CAR",
    "amount": "25.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-003",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": false,
    "is_first_subscription_payment": false,
    "kofi_transaction_id": "test-003-multiple-items",
    "shop_items": [
      {
        "direct_link_code": "pack-standard-5",
        "variation_name": "5-Pack Standard",
        "quantity": 2
      },
      {
        "direct_link_code": "pack-premium-5",
        "variation_name": "5-Pack Premium",
        "quantity": 1
      },
      {
        "direct_link_code": "pack-team-choice",
        "variation_name": "Team Choice Pack",
        "quantity": 1
      }
    ],
    "tier_name": null,
    "shipping": null,
    "discord_username": null,
    "discord_userid": null
  }'
```

**Expected Result:**
- ✅ Token validated
- ✅ Team "CAR" found via abbrev
- ✅ 15 total packs granted (10 standard + 5 premium + 1 team choice)
- ✅ Success Discord notification with itemized list

---

### Test 4: Team Not Found (Manual Review)

**Scenario:** User provides neither Discord ID nor valid team abbrev

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-004-unknown",
    "timestamp": "2025-11-13T12:15:00Z",
    "type": "Shop Order",
    "is_public": true,
    "from_name": "Unknown User",
    "message": "I love Paper Dynasty!",
    "amount": "5.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-004",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": false,
    "is_first_subscription_payment": false,
    "kofi_transaction_id": "test-004-manual-review",
    "shop_items": [
      {
        "direct_link_code": "pack-standard-5",
        "variation_name": "5-Pack Standard",
        "quantity": 1
      }
    ],
    "tier_name": null,
    "shipping": null,
    "discord_username": null,
    "discord_userid": null
  }'
```

**Expected Result:**
- ✅ Token validated
- ❌ No team identified
- ⚠️ Manual review Discord notification sent with @here mention
- ⚠️ Admin grants packs manually after identifying user

---

### Test 5: Unknown Product Code

**Scenario:** Ko-fi product code not in mapping

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-005-unknown-product",
    "timestamp": "2025-11-13T12:20:00Z",
    "type": "Shop Order",
    "is_public": true,
    "from_name": "Test Unknown Product",
    "message": "SKB",
    "amount": "99.99",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-005",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": false,
    "is_first_subscription_payment": false,
    "kofi_transaction_id": "test-005-unknown-product",
    "shop_items": [
      {
        "direct_link_code": "pack-does-not-exist",
        "variation_name": "Mystery Pack",
        "quantity": 1
      }
    ],
    "tier_name": null,
    "shipping": null,
    "discord_username": null,
    "discord_userid": null
  }'
```

**Expected Result:**
- ✅ Token validated
- ✅ Team "SKB" found
- ❌ Product code "pack-does-not-exist" not in mapping
- ⚠️ Manual review Discord notification
- ⚠️ Admin adds product to mapping or processes manually

---

### Test 6: Invalid Verification Token

**Scenario:** Test security - invalid Ko-fi token

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "INVALID-TOKEN-12345",
    "message_id": "test-006-invalid",
    "timestamp": "2025-11-13T12:25:00Z",
    "type": "Shop Order",
    "is_public": true,
    "from_name": "Hacker Attempt",
    "message": "SKB",
    "amount": "1000.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-006",
    "email": "[email protected]",
    "currency": "USD",
    "kofi_transaction_id": "test-006-security",
    "shop_items": [
      {
        "direct_link_code": "pack-standard-5",
        "variation_name": "5-Pack Standard",
        "quantity": 100
      }
    ],
    "discord_userid": null
  }'
```

**Expected Result:**
- ❌ Token validation fails
- ⛔ Workflow stops at validation node
- ⛔ NO packs granted
- ⛔ NO Discord notification (security - don't reveal valid tokens)

---

### Test 7: Non-Shop Order Type

**Scenario:** Ko-fi sends donation (not shop order)

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-007-donation",
    "timestamp": "2025-11-13T12:30:00Z",
    "type": "Donation",
    "is_public": true,
    "from_name": "Generous Donor",
    "message": "Keep up the great work!",
    "amount": "10.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-007",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": false,
    "kofi_transaction_id": "test-007-donation",
    "shop_items": null,
    "discord_userid": null
  }'
```

**Expected Result:**
- ✅ Token validated
- ℹ️ Type is "Donation" not "Shop Order"
- ⏭️ Workflow skips processing (no packs to grant)
- ✅ Returns 200 OK to Ko-fi

---

### Test 8: Monthly Subscription Payment

**Scenario:** Recurring subscription payment

**cURL Command:**
```bash
curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-paperdy' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'data={
    "verification_token": "YOUR_KOFI_TOKEN_HERE",
    "message_id": "test-008-subscription",
    "timestamp": "2025-11-13T12:35:00Z",
    "type": "Subscription",
    "is_public": true,
    "from_name": "Monthly Subscriber",
    "message": "PPD",
    "amount": "5.00",
    "url": "https://ko-fi.com/Home/CoffeeShop?txid=test-008",
    "email": "[email protected]",
    "currency": "USD",
    "is_subscription_payment": true,
    "is_first_subscription_payment": false,
    "kofi_transaction_id": "test-008-subscription",
    "shop_items": [
      {
        "direct_link_code": "sub-monthly-standard",
        "variation_name": "Monthly Standard Subscription",
        "quantity": 1
      }
    ],
    "tier_name": "Standard Member",
    "discord_username": "Subscriber#5678",
    "discord_userid": "987654321098765432"
  }'
```

**Expected Result:**
- ✅ Token validated
- ✅ Subscription payment processed as shop order
- ✅ 5 standard packs granted
- ✅ Success notification includes subscription tier

---

## Testing Checklist

### Pre-Deployment Testing

- [ ] **Test 1:** Basic order with Discord user ID ✅
- [ ] **Test 2:** Order with team abbrev in message ✅
- [ ] **Test 3:** Multiple items in single order ✅
- [ ] **Test 4:** Team not found (manual review) ⚠️
- [ ] **Test 5:** Unknown product code ⚠️
- [ ] **Test 6:** Invalid verification token ❌
- [ ] **Test 7:** Non-shop order type (donation) ⏭️
- [ ] **Test 8:** Monthly subscription payment ✅

### Integration Testing

- [ ] Ko-fi webhook test button works
- [ ] Discord notifications received in correct channel
- [ ] Discord @here mentions work for errors
- [ ] Paper Dynasty API grants packs correctly
- [ ] API retry logic works (simulate timeout)
- [ ] Multiple webhooks handled concurrently

### Security Testing

- [ ] Invalid tokens rejected
- [ ] No sensitive data in Discord notifications
- [ ] Webhook accessible only via HTTPS
- [ ] n8n basic auth required for UI access
- [ ] Credentials encrypted in n8n database

### Performance Testing

- [ ] Webhook responds within 5 seconds
- [ ] Paper Dynasty API calls timeout correctly
- [ ] Large orders (20+ items) process successfully
- [ ] Concurrent webhooks don't cause issues

### Edge Cases

- [ ] Empty shop_items array
- [ ] Null discord_userid and message fields
- [ ] Special characters in team abbrev
- [ ] Very large quantity (100+ packs)
- [ ] Product with quantity: 0
- [ ] Duplicate message_id (Ko-fi retry)

### Monitoring & Alerts

- [ ] Success notifications readable
- [ ] Error notifications actionable
- [ ] Manual review requests clear
- [ ] n8n execution logs captured
- [ ] Failed executions visible in n8n UI

---

## Validation Scripts

### Verify Ko-fi Webhook Format

**Script:** `validate-kofi-payload.js`

```javascript
// Run in n8n Code node or standalone Node.js

function validateKofiPayload(payload) {
  const required = [
    'verification_token',
    'message_id',
    'timestamp',
    'type',
    'from_name',
    'amount',
    'email',
    'currency',
    'kofi_transaction_id'
  ];

  const missing = required.filter(field => !payload[field]);

  if (missing.length > 0) {
    throw new Error(`Missing required fields: ${missing.join(', ')}`);
  }

  if (payload.type === 'Shop Order' && !payload.shop_items) {
    throw new Error('Shop Order missing shop_items array');
  }

  console.log('✅ Payload valid');
  return true;
}

// Test
const testPayload = JSON.parse($json.body.data);
validateKofiPayload(testPayload);
```

### Verify Paper Dynasty Pack Grant

**Script:** `verify-pack-grant.py`

```python
#!/usr/bin/env python3
"""Verify packs were granted in Paper Dynasty"""

from api_client import PaperDynastyAPI
from datetime import datetime, timezone

api = PaperDynastyAPI(environment='prod', verbose=True)

# Get packs created in last hour
recent_packs = api.list_packs(opened=False, new_to_old=True, limit=100)

# Filter by timestamp
one_hour_ago = datetime.now(timezone.utc).timestamp() - 3600

for pack in recent_packs:
    pack_time = pack.get('created_at', 0) / 1000
    if pack_time > one_hour_ago:
        team = api.get_team(team_id=pack['team'])
        print(f"✅ Pack {pack['id']} granted to {team['abbrev']} at {datetime.fromtimestamp(pack_time)}")
```

---

## Common Issues During Testing

### Issue: Webhook 404 Not Found

**Cause:** Workflow not active or wrong webhook path

**Fix:**
```bash
# Check workflow is active in n8n UI
# Verify webhook path: n8n → Workflow → Webhook node → Path

# Test webhook accessibility
curl -I https://n8n.manticorum.com/webhook-test/kofi-paperdy
# Should return: 200 OK or 400 Bad Request (not 404)
```

### Issue: Token Validation Failing

**Cause:** Token mismatch or credential not configured

**Fix:**
1. Copy token exactly from Ko-fi dashboard
2. Check n8n credential name matches IF node reference
3. No extra spaces or quotes in token value
4. Re-create credential if needed

### Issue: Team Not Found

**Cause:** Discord user ID or team abbrev doesn't exist in PD

**Fix:**
```python
# Check if discord_userid exists in PD
api.get('teams', params={'gmid': '012345678901234567'})

# Check if team abbrev exists
api.get('teams', params={'abbrev': 'SKB'})

# If not found, update user's PD profile or use manual review
```

### Issue: Packs Not Granted

**Cause:** API request succeeded but packs not visible

**Fix:**
1. Check API response body in n8n execution log
2. Verify team_id is correct
3. Check pack_type_id is valid
4. Query PD database directly:
   ```python
   api.list_packs(team_id=69, opened=False, limit=20)
   ```

### Issue: Discord Notification Not Sent

**Cause:** Discord webhook URL invalid or permissions issue

**Fix:**
1. Test Discord webhook directly:
   ```bash
   curl -X POST 'DISCORD_WEBHOOK_URL' \
     -H 'Content-Type: application/json' \
     -d '{"content": "Test notification"}'
   ```
2. Regenerate webhook in Discord if needed
3. Update n8n credential with new URL

---

## Production Monitoring

### Daily Checks

- [ ] Review n8n execution logs (filter by workflow)
- [ ] Check for failed executions
- [ ] Review manual review Discord notifications
- [ ] Verify all orders processed successfully

### Weekly Checks

- [ ] Review unknown product codes
- [ ] Update product mapping for new Ko-fi products
- [ ] Check Paper Dynasty pack distribution accuracy
- [ ] Review API response times

### Monthly Checks

- [ ] Test disaster recovery procedure
- [ ] Backup n8n database
- [ ] Rotate Ko-fi verification token
- [ ] Update documentation with lessons learned

---

## References

- **Main Workflow Documentation:** `kofi-paper-dynasty.md`
- **Product Mapping Template:** `kofi-product-mapping-template.json`
- **Ko-fi Webhook Docs:** https://help.ko-fi.com/hc/en-us/articles/360004162298
- **Paper Dynasty API:** `/home/cal/.claude/skills/paper-dynasty/SKILL.md`

## Change Log

### 2025-11-13 - Initial Version
- Created comprehensive testing guide
- Defined 8 test scenarios with cURL commands
- Added validation scripts and troubleshooting
- Documented testing checklist and monitoring procedures
