# Ko-fi → Paper Dynasty Implementation Notes **Date:** 2025-11-13 **Status:** Working in pddev, ready for production **n8n Version:** Community (self-hosted) ## What We Actually Built This document captures the real implementation vs. the original plan, including all the gotchas we encountered. --- ## Key Differences from Original Plan ### 1. No Custom Variables (Enterprise Feature) **Original Plan:** Use n8n custom variable `KOFI_PRODUCT_MAP` for product mapping **Actual Implementation:** Hardcoded product mapping in "Map Products" Code node **Why:** Custom variables are enterprise-only in n8n **Product Mapping (Hardcoded in Code Node):** ```javascript const PRODUCT_MAP = { '61de350207': { // Ko-fi product ID from URL name: 'Premium Pack', pack_type_id: 3, packs_per_quantity: 1 }, '2bdb7a4916': { name: 'Standard Pack', pack_type_id: 1, packs_per_quantity: 1 }, '3d7a4935aa': { name: 'In-Game Currency', type: 'currency', needs_manual_review: true // Not implemented yet } }; ``` ### 2. Team Lookup Split into 3 Nodes **Original Plan:** Single "Lookup PD Team" Code node with `$http.request()` **Actual Implementation:** 3 separate nodes **Why:** `fetch()` and `$http` are not available in n8n Code nodes **The 3 Nodes:** 1. **Extract Team Abbrev** (Code) - Regex extraction only 2. **Lookup Team API** (HTTP Request) - API call to PD 3. **Process Team Result** (Code) - Parse API response ### 3. Ko-fi Product Codes **Original Plan:** Use Ko-fi's "direct_link_code" custom field **Actual Reality:** Ko-fi doesn't have custom product codes **Solution:** Using Ko-fi's internal product IDs from URLs: - `https://ko-fi.com/s/61de350207` → ID is `61de350207` - These IDs appear in webhook's `shop_items[].direct_link_code` ### 4. Webhook Domain Configuration **Issue:** n8n showed `https://n8n.yourdomain.com` by default **Solution:** Environment variables were set correctly, just needed n8n restart: ```bash ssh root@10.10.0.210 "cd /opt/n8n && docker compose down && docker compose up -d" ``` ### 5. API Request Body Formatting **Issue:** Paper Dynasty API rejected stringified JSON **Solution:** Use `{{ $json.pack_requests }}` without `JSON.stringify()` or `=` prefix **Wrong:** `={{ JSON.stringify({"packs": $json.pack_requests}) }}` **Right:** `{{ $json.pack_requests }}` ### 6. Discord Notifications **Issue:** Empty body caused "Cannot send an empty message" **Solution:** Always include `content` field even when using embeds **Minimum working Discord message:** ```json { "content": "Message text here", "embeds": [...] } ``` ### 7. Added Donation Support **Extension:** Added Switch node to route by transaction type **Routes:** - Output 0: Shop Order → Grant Packs flow - Output 1: Donation → Thank you notification - Output 2: Subscription → (Future implementation) - Fallback: Unknown types → Return 200 OK --- ## Final Working Architecture ``` Ko-fi Webhook POST ↓ [Webhook: Ko-fi Webhook] Path: /kofi-pd-purchase ↓ [Code: Parse & Validate] - Parse form data JSON - Validate Ko-fi token (hardcoded) ↓ [Switch: Route by Type] Value: {{ $json.type }} ├─ Output 0: "Shop Order" │ ↓ │ [Code: Extract Team Abbrev] │ - Regex: /\b([A-Z]{2,4})\b/ │ ↓ │ [HTTP: Lookup Team API] │ - URL: pddev.manticorum.com/api/v2/teams?abbrev=... │ - Auth: Paper Dynasty API credential │ ↓ │ [Code: Process Team Result] │ - Extract team ID and abbrev │ ↓ │ [IF: Team Found?] │ ├─ True → [Code: Map Products] │ │ - Hardcoded product map │ │ - Create pack_requests array │ │ ↓ │ │ [HTTP: Grant Packs] │ │ - POST /packs with array │ │ ↓ │ │ [IF: API Success?] │ │ ├─ True → [HTTP: Discord Success] │ │ └─ False → [HTTP: Discord Error] │ │ │ └─ False → [HTTP: Discord Manual Review] │ ├─ Output 1: "Donation" │ ↓ │ [HTTP: Discord Thank You] │ - Notification for manual thanks │ └─ Fallback: Other types ↓ [Return 200 OK] ``` --- ## Current Configuration ### Environment - **Testing:** pddev.manticorum.com (Paper Dynasty Dev) - **Production:** pd.manticorum.com (not yet deployed) ### Credentials Created 1. **Paper Dynasty API** (Header Auth) - Header: `Authorization` - Value: `Bearer Tp3aO3jhYve5NJF1IqOmJTmk` 2. **Discord Webhook** (not used as credential) - URL hardcoded in HTTP Request nodes - Webhook: `1438578498108133488/MGx1zyAa1ewzVy3RqCsH50ZJUiVvT5J5Vl2jExGIkIsu6v0x8A9J3-ruRftClPEq91ej` ### Ko-fi Settings - **Verification Token:** `44d1f957-ac15-497e-8306-4dc667de55d1` - **Webhook URL (test):** `https://n8n.manticorum.com/webhook-test/kofi-pd-purchase` - **Webhook URL (prod):** `https://n8n.manticorum.com/webhook/kofi-pd-purchase` ### Products Configured | Ko-fi ID | Name | PD Pack Type | Quantity | |----------|------|--------------|----------| | 61de350207 | Premium Pack | 3 | 1 per qty | | 2bdb7a4916 | Standard Pack | 1 | 1 per qty | | 3d7a4935aa | In-Game Currency | N/A | Manual review | --- ## Testing Results ### Successful Test (2025-11-13) - ✅ Webhook received and parsed - ✅ Token validated - ✅ Team "SKB" found via message extraction - ✅ Product mapped (2bdb7a4916 → 5 standard packs) - ✅ API call succeeded (201 Created) - ✅ 5 packs granted to team SKB in pddev - ✅ Discord success notification sent ### Test Command Used ```bash curl -X POST 'https://n8n.manticorum.com/webhook-test/kofi-pd-purchase' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'data={ "verification_token": "44d1f957-ac15-497e-8306-4dc667de55d1", "message_id": "test-001", "timestamp": "2025-11-13T12:00:00Z", "type": "Shop Order", "from_name": "Test Customer", "message": "SKB", "amount": "5.00", "email": "test@example.com", "currency": "USD", "kofi_transaction_id": "test-001", "shop_items": [ { "direct_link_code": "2bdb7a4916", "variation_name": "Standard Pack", "quantity": 5 } ], "discord_userid": null }' ``` --- ## Known Limitations ### 1. No Discord User ID Support Yet **Status:** Code is in place but untested **Why:** Test payload used `discord_userid: null` **Todo:** Test with real Discord-linked Ko-fi account ### 2. Currency Product Not Implemented **Status:** Routed to manual review **Reason:** Paper Dynasty doesn't have currency system yet **Todo:** Implement currency granting when PD adds support ### 3. Subscription Type Not Handled **Status:** Returns 200 OK but does nothing **Reason:** Decided to implement shop orders and donations first **Todo:** Add subscription tier handling ### 4. Single Discord Channel **Status:** All notifications go to "cals-hidey-hole" **Todo:** Consider separate channels for success/errors/reviews ### 5. Hardcoded Configuration **Status:** All settings hardcoded in Code nodes **Why:** Community edition limitations **Impact:** Must edit code nodes to change products, tokens, or URLs **Mitigation:** Well-documented code with clear comments --- ## Production Deployment Checklist Before going live with production: - [ ] **Update all API URLs from pddev to prod:** - [ ] "Lookup Team API" node URL - [ ] "Grant Packs" node URL - [ ] **Update Ko-fi webhook URL:** - [ ] Change from `/webhook-test/` to `/webhook/` - [ ] Configure in Ko-fi dashboard - [ ] **Activate workflow:** - [ ] Toggle "Active" switch in n8n - [ ] **Test with real Ko-fi purchase:** - [ ] Create $0.01 test product - [ ] Make test purchase - [ ] Verify packs granted in production - [ ] Verify Discord notification - [ ] **Monitor first 10 transactions:** - [ ] Watch Discord for notifications - [ ] Check n8n execution logs - [ ] Verify pack distribution accuracy - [ ] **Document any issues encountered** --- ## Troubleshooting Guide ### Webhook Not Triggering **Symptoms:** n8n shows "Waiting for trigger event" but nothing happens **Solutions:** 1. Verify workflow is Active (green toggle) 2. Check webhook path matches Ko-fi configuration 3. Test with cURL to isolate issue 4. Check n8n logs: `ssh root@10.10.0.210 "cd /opt/n8n && docker compose logs -f n8n"` ### Token Validation Failing **Symptoms:** Workflow stops at "Parse & Validate" with error **Solutions:** 1. Verify token in Code node matches Ko-fi dashboard exactly 2. Check for extra spaces or quotes 3. Re-copy token from Ko-fi ### Team Not Found **Symptoms:** Workflow takes "Team Found? False" path **Solutions:** 1. Check message field has valid team abbrev (2-4 uppercase letters) 2. Test API directly: `curl -H "Authorization: Bearer TOKEN" "URL/teams?abbrev=SKB"` 3. Verify team exists in target environment (pddev vs prod) ### API Call Failing **Symptoms:** "API Success?" takes False path **Solutions:** 1. Check HTTP Request body format (no JSON.stringify, no = prefix) 2. Verify `pack_requests` is an array in "Map Products" output 3. Check API credentials are correct 4. Review full error in node execution data ### Discord Notification Not Sending **Symptoms:** No Discord message received **Solutions:** 1. Verify webhook URL is correct 2. Test webhook directly with cURL 3. Check body has `content` field (required even with embeds) 4. Verify Discord channel hasn't deleted the webhook ### Unknown Product Code **Symptoms:** `unknown_products` array has items, takes manual review path **Solutions:** 1. Check Ko-fi product ID matches `PRODUCT_MAP` keys 2. Get product ID from Ko-fi product URL: `/s/{ID}` 3. Add new product to PRODUCT_MAP in "Map Products" code --- ## Maintenance Tasks ### Adding New Products 1. Get Ko-fi product ID from product URL 2. Edit "Map Products" Code node 3. Add entry to `PRODUCT_MAP`: ```javascript 'new-product-id': { name: 'Product Name', pack_type_id: 1, // 1=Standard, 3=Premium, 8=Team Choice packs_per_quantity: 1 } ``` 4. Save and test ### Changing API Endpoints 1. Edit "Lookup Team API" HTTP Request URL 2. Edit "Grant Packs" HTTP Request URL 3. Update "Parse & Validate" API_TOKEN if needed 4. Test thoroughly before activating ### Updating Discord Webhooks 1. Create new webhook in Discord 2. Update all Discord HTTP Request node URLs: - Discord Success - Discord Error - Discord Manual Review - Discord Thank You 3. Test each notification type ### Rotating Credentials **Ko-fi Token:** 1. Get new token from Ko-fi dashboard 2. Update in "Parse & Validate" Code node 3. Test with cURL **Paper Dynasty API Key:** 1. Generate new key in PD admin 2. Update "Paper Dynasty API" credential in n8n 3. Test API calls --- ## Future Enhancements ### Priority 1 (Next Session) - [ ] Test Discord user ID → gmid lookup - [ ] Add Subscription handling - [ ] Implement currency product logic - [ ] Test with real Ko-fi purchases ### Priority 2 (Nice to Have) - [ ] Separate Discord channels for different notification types - [ ] Email notifications for manual reviews - [ ] Transaction history logging (database or file) - [ ] Analytics dashboard for pack distributions ### Priority 3 (Optimization) - [ ] Retry logic for failed transactions - [ ] Batch processing for multiple purchases - [ ] Scheduled reconciliation job - [ ] Admin UI for product mapping --- ## Lessons Learned ### 1. n8n Community vs Enterprise Community edition is powerful but limited: - No custom variables (use hardcoded values in Code nodes) - Code nodes can't make HTTP requests (use HTTP Request nodes) - Works great for our use case with workarounds ### 2. Ko-fi Webhook Structure - Form-urlencoded with JSON in `data` field - Product codes are internal Ko-fi IDs, not custom - `shop_items` can have multiple items in single order - Always validate `verification_token` ### 3. Paper Dynasty API Integration - Straightforward REST API - Expects JSON arrays, not stringified - Good error messages - Dev environment perfect for testing ### 4. Discord Webhook Best Practices - Always include `content` field - Embeds are great for rich notifications - @here mentions work for urgent alerts - Test webhooks fail silently if deleted ### 5. Workflow Development Process - Start simple, add complexity gradually - Test each node individually - Use debug fields (like `debug_info`) during development - Document as you go --- ## Resources **Documentation Created:** - `/productivity/n8n/workflows/kofi-paper-dynasty.md` - Original detailed guide - `/productivity/n8n/workflows/QUICK-START.md` - 30-minute setup guide - `/productivity/n8n/workflows/kofi-testing-guide.md` - Testing procedures - `/productivity/n8n/workflows/kofi-product-mapping-template.json` - Product config - `/productivity/n8n/workflows/kofi-implementation-notes.md` - This file **External References:** - Ko-fi Webhook Docs: https://help.ko-fi.com/hc/en-us/articles/360004162298 - n8n Documentation: https://docs.n8n.io/ - Paper Dynasty API: See `/home/cal/.claude/skills/paper-dynasty/SKILL.md` **Test Files:** - Ko-fi payload structure: `/home/cal/Desktop/kofi-integration.md` --- ## Change Log ### 2025-11-13 - Initial Implementation - Created complete Ko-fi → Paper Dynasty workflow - Working in pddev environment - Shop orders fully functional - Donation notifications implemented - Team identification via message extraction tested - Discord notifications for all paths - Ready for production deployment --- **Next Session Goals:** 1. Test Discord user ID lookup 2. Deploy to production 3. Make first real Ko-fi purchase 4. Monitor and iterate **Status:** ✅ Ready for production deployment