@nordsym/apiclaw 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/.github/ISSUE_TEMPLATE/add-api.yml +123 -0
  2. package/BRIEFING.md +30 -0
  3. package/CONCEPT.md +494 -0
  4. package/README.md +272 -0
  5. package/backend/convex/README.md +90 -0
  6. package/backend/convex/_generated/api.d.ts +55 -0
  7. package/backend/convex/_generated/api.js +23 -0
  8. package/backend/convex/_generated/dataModel.d.ts +60 -0
  9. package/backend/convex/_generated/server.d.ts +143 -0
  10. package/backend/convex/_generated/server.js +93 -0
  11. package/backend/convex/apiKeys.ts +75 -0
  12. package/backend/convex/purchases.ts +74 -0
  13. package/backend/convex/schema.ts +45 -0
  14. package/backend/convex/transactions.ts +57 -0
  15. package/backend/convex/tsconfig.json +25 -0
  16. package/backend/convex/users.ts +94 -0
  17. package/backend/package-lock.json +521 -0
  18. package/backend/package.json +15 -0
  19. package/dist/credits.d.ts +54 -0
  20. package/dist/credits.d.ts.map +1 -0
  21. package/dist/credits.js +209 -0
  22. package/dist/credits.js.map +1 -0
  23. package/dist/discovery.d.ts +37 -0
  24. package/dist/discovery.d.ts.map +1 -0
  25. package/dist/discovery.js +109 -0
  26. package/dist/discovery.js.map +1 -0
  27. package/dist/index.d.ts +13 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +355 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/registry/apis.json +20894 -0
  32. package/dist/registry/parse_apis.py +146 -0
  33. package/dist/revenuecat.d.ts +61 -0
  34. package/dist/revenuecat.d.ts.map +1 -0
  35. package/dist/revenuecat.js +166 -0
  36. package/dist/revenuecat.js.map +1 -0
  37. package/dist/test.d.ts +6 -0
  38. package/dist/test.d.ts.map +1 -0
  39. package/dist/test.js +81 -0
  40. package/dist/test.js.map +1 -0
  41. package/dist/types.d.ts +96 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +3 -0
  44. package/dist/types.js.map +1 -0
  45. package/dist/webhooks/revenuecat.d.ts +48 -0
  46. package/dist/webhooks/revenuecat.d.ts.map +1 -0
  47. package/dist/webhooks/revenuecat.js +119 -0
  48. package/dist/webhooks/revenuecat.js.map +1 -0
  49. package/docs/revenuecat-setup.md +89 -0
  50. package/landing/next-env.d.ts +5 -0
  51. package/landing/next.config.mjs +6 -0
  52. package/landing/package-lock.json +1666 -0
  53. package/landing/package.json +27 -0
  54. package/landing/postcss.config.js +6 -0
  55. package/landing/src/app/api/keys/route.ts +71 -0
  56. package/landing/src/app/api/log/route.ts +37 -0
  57. package/landing/src/app/api/stats/route.ts +37 -0
  58. package/landing/src/app/globals.css +261 -0
  59. package/landing/src/app/layout.tsx +37 -0
  60. package/landing/src/app/page.tsx +753 -0
  61. package/landing/src/app/page.tsx.bak +567 -0
  62. package/landing/src/components/AddKeyModal.tsx +159 -0
  63. package/landing/tailwind.config.ts +34 -0
  64. package/landing/tsconfig.json +20 -0
  65. package/newsletter-template.html +71 -0
  66. package/outreach/OUTREACH-SYSTEM.md +211 -0
  67. package/outreach/email-template.html +179 -0
  68. package/outreach/targets.md +133 -0
  69. package/package.json +39 -0
  70. package/src/credits.ts +261 -0
  71. package/src/discovery.ts +147 -0
  72. package/src/index.ts +396 -0
  73. package/src/registry/apis.json +20894 -0
  74. package/src/registry/parse_apis.py +146 -0
  75. package/src/revenuecat.ts +239 -0
  76. package/src/test.ts +97 -0
  77. package/src/types.ts +110 -0
  78. package/src/webhooks/revenuecat.ts +187 -0
  79. package/tsconfig.json +20 -0
@@ -0,0 +1,119 @@
1
+ // RevenueCat webhook handler for APIClaw
2
+ // Handles subscription lifecycle events and syncs to Convex
3
+ import { Hono } from 'hono';
4
+ const CONVEX_URL = process.env.CONVEX_URL || 'https://agile-crane-840.convex.cloud';
5
+ /**
6
+ * Update user subscription status in Convex
7
+ */
8
+ async function updateConvexUser(update) {
9
+ try {
10
+ const response = await fetch(`${CONVEX_URL}/api/mutation`, {
11
+ method: 'POST',
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ body: JSON.stringify({
16
+ path: 'users:updateSubscription',
17
+ args: update,
18
+ }),
19
+ });
20
+ if (!response.ok) {
21
+ console.error('Convex update failed:', await response.text());
22
+ return false;
23
+ }
24
+ return true;
25
+ }
26
+ catch (error) {
27
+ console.error('Error updating Convex:', error);
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Process webhook event and determine subscription state
33
+ */
34
+ function processEvent(event) {
35
+ const now = Date.now();
36
+ const expiresAt = event.expiration_at_ms;
37
+ const isExpired = expiresAt ? expiresAt < now : false;
38
+ let subscriptionStatus = 'active';
39
+ let isPro = true;
40
+ switch (event.type) {
41
+ case 'INITIAL_PURCHASE':
42
+ case 'RENEWAL':
43
+ case 'UNCANCELLATION':
44
+ case 'SUBSCRIPTION_EXTENDED':
45
+ subscriptionStatus = 'active';
46
+ isPro = true;
47
+ break;
48
+ case 'CANCELLATION':
49
+ // Still active until expiration
50
+ subscriptionStatus = 'cancelled';
51
+ isPro = !isExpired;
52
+ break;
53
+ case 'EXPIRATION':
54
+ subscriptionStatus = 'expired';
55
+ isPro = false;
56
+ break;
57
+ case 'SUBSCRIPTION_PAUSED':
58
+ subscriptionStatus = 'paused';
59
+ isPro = false;
60
+ break;
61
+ case 'BILLING_ISSUE':
62
+ subscriptionStatus = 'billing_issue';
63
+ // Keep Pro until grace period ends
64
+ isPro = !isExpired;
65
+ break;
66
+ case 'PRODUCT_CHANGE':
67
+ case 'TRANSFER':
68
+ subscriptionStatus = 'active';
69
+ isPro = event.entitlement_ids.includes('pro');
70
+ break;
71
+ default:
72
+ isPro = event.entitlement_ids.includes('pro') && !isExpired;
73
+ }
74
+ return {
75
+ userId: event.app_user_id,
76
+ isPro,
77
+ subscriptionStatus,
78
+ productId: event.product_id,
79
+ expiresAt: expiresAt,
80
+ updatedAt: now,
81
+ eventType: event.type,
82
+ };
83
+ }
84
+ /**
85
+ * Create Hono router for webhook handling
86
+ */
87
+ export function createWebhookRouter() {
88
+ const app = new Hono();
89
+ // Health check
90
+ app.get('/webhooks/revenuecat/health', (c) => {
91
+ return c.json({ status: 'ok', service: 'revenuecat-webhook' });
92
+ });
93
+ // RevenueCat webhook endpoint
94
+ app.post('/webhooks/revenuecat', async (c) => {
95
+ try {
96
+ const body = await c.req.json();
97
+ console.log(`[RevenueCat] Received ${body.event.type} for user ${body.event.app_user_id}`);
98
+ // Process the event
99
+ const update = processEvent(body.event);
100
+ // Update Convex
101
+ const success = await updateConvexUser(update);
102
+ if (success) {
103
+ console.log(`[RevenueCat] Updated user ${update.userId}: isPro=${update.isPro}`);
104
+ return c.json({ success: true });
105
+ }
106
+ else {
107
+ return c.json({ success: false, error: 'Failed to update database' }, 500);
108
+ }
109
+ }
110
+ catch (error) {
111
+ console.error('[RevenueCat] Webhook error:', error);
112
+ return c.json({ success: false, error: 'Internal error' }, 500);
113
+ }
114
+ });
115
+ return app;
116
+ }
117
+ // Export for testing
118
+ export { processEvent, updateConvexUser };
119
+ //# sourceMappingURL=revenuecat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revenuecat.js","sourceRoot":"","sources":["../../src/webhooks/revenuecat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ # APIClaw RevenueCat Setup
2
+
3
+ ## Current Status ✅
4
+
5
+ **Entitlement Created:**
6
+ - ID: `entl34d5186e73`
7
+ - Lookup Key: `pro`
8
+ - Display Name: "APIClaw Pro"
9
+
10
+ **Project ID:** `0d074df4`
11
+
12
+ ## Required Manual Setup
13
+
14
+ ### 1. Link Stripe Account
15
+
16
+ Go to RevenueCat Dashboard → Project Settings → Integrations → Stripe
17
+
18
+ Link your Stripe account to enable web subscriptions.
19
+
20
+ ### 2. Create Stripe Product
21
+
22
+ After linking Stripe, create:
23
+ - **Product ID:** `apiclaw_pro_monthly`
24
+ - **Price:** $99/month
25
+ - **Description:** APIClaw Pro - 2% transaction fees, priority support
26
+
27
+ ### 3. Attach Product to Entitlement
28
+
29
+ In RevenueCat Dashboard:
30
+ 1. Go to Products
31
+ 2. Create product pointing to Stripe product ID
32
+ 3. Attach to "pro" entitlement
33
+
34
+ ### 4. Configure Webhook
35
+
36
+ Add webhook URL in RevenueCat Dashboard → Webhooks:
37
+
38
+ ```
39
+ https://your-api-domain.com/webhooks/revenuecat
40
+ ```
41
+
42
+ Events to enable:
43
+ - INITIAL_PURCHASE
44
+ - RENEWAL
45
+ - CANCELLATION
46
+ - EXPIRATION
47
+ - BILLING_ISSUE
48
+
49
+ ## Environment Variables
50
+
51
+ ```bash
52
+ # Required in .env
53
+ REVENUECAT_SECRET_KEY=sk_TwFjVtmGbrgtULpWgHDYBHiZuQvlK
54
+ CONVEX_URL=https://agile-crane-840.convex.cloud
55
+ ```
56
+
57
+ ## API Usage
58
+
59
+ ```typescript
60
+ import { hasProSubscription, getFeePercentage, calculateFee } from './revenuecat';
61
+
62
+ // Check if user has Pro
63
+ const isPro = await hasProSubscription('user_123');
64
+
65
+ // Get fee percentage (2% Pro, 5% Free)
66
+ const fee = await getFeePercentage('user_123');
67
+
68
+ // Calculate fee for transaction
69
+ const { feeAmount, netAmount, isPro } = await calculateFee('user_123', 100);
70
+ // isPro: true → feeAmount: $2, netAmount: $98
71
+ // isPro: false → feeAmount: $5, netAmount: $95
72
+ ```
73
+
74
+ ## Pro Benefits
75
+
76
+ | Feature | Free | Pro ($99/mo) |
77
+ |---------|------|--------------|
78
+ | Transaction Fee | 5% | 2% |
79
+ | Support | Community | Priority |
80
+ | API Calls | Standard | Priority routing |
81
+ | Analytics | Basic | Advanced |
82
+
83
+ ## Break-even Analysis
84
+
85
+ Monthly API spend for Pro to pay off:
86
+ - Fee savings: 3% per transaction
87
+ - Break-even: $99 / 0.03 = $3,300/month in API spend
88
+
89
+ If spending >$3.3k/month on APIs → Pro saves money.
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ output: 'standalone',
4
+ };
5
+
6
+ export default nextConfig;