@adityanair98/api-oracle 0.5.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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +216 -0
  3. package/dist/cli.d.ts +11 -0
  4. package/dist/cli.js +74 -0
  5. package/dist/dashboard/public/app.js +1004 -0
  6. package/dist/dashboard/public/index.html +142 -0
  7. package/dist/dashboard/public/public/app.js +1004 -0
  8. package/dist/dashboard/public/public/index.html +142 -0
  9. package/dist/dashboard/public/public/styles.css +1464 -0
  10. package/dist/dashboard/public/styles.css +1464 -0
  11. package/dist/dashboard/routes/api.d.ts +7 -0
  12. package/dist/dashboard/routes/api.js +245 -0
  13. package/dist/dashboard/server.d.ts +9 -0
  14. package/dist/dashboard/server.js +45 -0
  15. package/dist/index.d.ts +5 -0
  16. package/dist/index.js +23 -0
  17. package/dist/knowledge/db.d.ts +22 -0
  18. package/dist/knowledge/db.js +182 -0
  19. package/dist/knowledge/schema.d.ts +275 -0
  20. package/dist/knowledge/schema.js +135 -0
  21. package/dist/knowledge/scorer.d.ts +63 -0
  22. package/dist/knowledge/scorer.js +314 -0
  23. package/dist/knowledge/search.d.ts +37 -0
  24. package/dist/knowledge/search.js +111 -0
  25. package/dist/knowledge/synonyms.d.ts +36 -0
  26. package/dist/knowledge/synonyms.js +523 -0
  27. package/dist/knowledge/tfidf.d.ts +42 -0
  28. package/dist/knowledge/tfidf.js +138 -0
  29. package/dist/server.d.ts +9 -0
  30. package/dist/server.js +40 -0
  31. package/dist/tools/check-freshness.d.ts +9 -0
  32. package/dist/tools/check-freshness.js +95 -0
  33. package/dist/tools/compare-apis.d.ts +8 -0
  34. package/dist/tools/compare-apis.js +149 -0
  35. package/dist/tools/find-api.d.ts +9 -0
  36. package/dist/tools/find-api.js +120 -0
  37. package/dist/tools/get-setup-guide.d.ts +8 -0
  38. package/dist/tools/get-setup-guide.js +127 -0
  39. package/dist/updater/linter.d.ts +31 -0
  40. package/dist/updater/linter.js +219 -0
  41. package/dist/updater/report.d.ts +29 -0
  42. package/dist/updater/report.js +96 -0
  43. package/dist/updater/staleness.d.ts +39 -0
  44. package/dist/updater/staleness.js +66 -0
  45. package/dist/updater/version-tracker.d.ts +28 -0
  46. package/dist/updater/version-tracker.js +50 -0
  47. package/dist/utils/config.d.ts +11 -0
  48. package/dist/utils/config.js +13 -0
  49. package/dist/utils/logger.d.ts +20 -0
  50. package/dist/utils/logger.js +32 -0
  51. package/package.json +56 -0
  52. package/src/entries/ai/anthropic.json +95 -0
  53. package/src/entries/ai/eleven-labs.json +90 -0
  54. package/src/entries/ai/openai.json +95 -0
  55. package/src/entries/ai/replicate.json +87 -0
  56. package/src/entries/ai/resemble-ai.json +88 -0
  57. package/src/entries/ai/stability-ai.json +89 -0
  58. package/src/entries/analytics/posthog.json +88 -0
  59. package/src/entries/analytics/sentry.json +84 -0
  60. package/src/entries/auth/auth0.json +90 -0
  61. package/src/entries/auth/clerk.json +95 -0
  62. package/src/entries/cms/contentful.json +92 -0
  63. package/src/entries/cms/sanity.json +92 -0
  64. package/src/entries/cms/strapi.json +93 -0
  65. package/src/entries/commerce/medusa.json +91 -0
  66. package/src/entries/commerce/shopify-api.json +91 -0
  67. package/src/entries/communication/sendbird.json +85 -0
  68. package/src/entries/communication/stream-chat.json +94 -0
  69. package/src/entries/database/firebase.json +88 -0
  70. package/src/entries/database/neon.json +94 -0
  71. package/src/entries/database/planetscale.json +95 -0
  72. package/src/entries/database/supabase.json +94 -0
  73. package/src/entries/database/upstash.json +94 -0
  74. package/src/entries/devops/fly-io.json +90 -0
  75. package/src/entries/devops/netlify.json +90 -0
  76. package/src/entries/devops/railway.json +90 -0
  77. package/src/entries/devops/vercel.json +90 -0
  78. package/src/entries/email/mailgun.json +91 -0
  79. package/src/entries/email/postmark.json +91 -0
  80. package/src/entries/email/resend.json +89 -0
  81. package/src/entries/email/sendgrid.json +90 -0
  82. package/src/entries/forms/formspark.json +85 -0
  83. package/src/entries/forms/typeform.json +98 -0
  84. package/src/entries/infrastructure/aws-s3.json +104 -0
  85. package/src/entries/infrastructure/cloudflare-r2.json +92 -0
  86. package/src/entries/infrastructure/cloudflare-workers.json +92 -0
  87. package/src/entries/infrastructure/digital-ocean-spaces.json +87 -0
  88. package/src/entries/integration/nango.json +90 -0
  89. package/src/entries/integration/zapier.json +92 -0
  90. package/src/entries/maps/google-maps.json +89 -0
  91. package/src/entries/maps/mapbox.json +87 -0
  92. package/src/entries/media/deepgram.json +84 -0
  93. package/src/entries/media/imgix.json +84 -0
  94. package/src/entries/media/mux.json +94 -0
  95. package/src/entries/messaging/ably.json +94 -0
  96. package/src/entries/messaging/pusher.json +94 -0
  97. package/src/entries/messaging/twilio.json +94 -0
  98. package/src/entries/messaging/vonage.json +89 -0
  99. package/src/entries/notifications/knock.json +84 -0
  100. package/src/entries/notifications/novu.json +84 -0
  101. package/src/entries/notifications/onesignal.json +84 -0
  102. package/src/entries/payments/lemonsqueezy.json +91 -0
  103. package/src/entries/payments/paddle.json +90 -0
  104. package/src/entries/payments/paypal.json +91 -0
  105. package/src/entries/payments/razorpay.json +85 -0
  106. package/src/entries/payments/square.json +91 -0
  107. package/src/entries/payments/stripe.json +96 -0
  108. package/src/entries/scheduling/cal-com.json +90 -0
  109. package/src/entries/scheduling/calendly.json +90 -0
  110. package/src/entries/search/algolia.json +96 -0
  111. package/src/entries/security/arcjet.json +89 -0
  112. package/src/entries/security/snyk.json +90 -0
  113. package/src/entries/storage/cloudinary.json +93 -0
  114. package/src/entries/storage/uploadthing.json +90 -0
  115. package/src/entries/testing/browserstack.json +86 -0
  116. package/src/entries/testing/checkly.json +89 -0
  117. package/src/entries/workflow/inngest.json +88 -0
  118. package/src/entries/workflow/temporal.json +90 -0
  119. package/src/entries/workflow/trigger-dev.json +89 -0
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "Vonage",
3
+ "slug": "vonage",
4
+ "category": "messaging",
5
+ "subcategory": "sms-voice",
6
+ "website": "https://www.vonage.com/communications-apis",
7
+ "description": "Vonage (formerly Nexmo) is a cloud communications platform offering SMS, voice, video, and authentication APIs. It is Twilio's primary competitor with strong European coverage and a more developer-friendly pricing model, especially for international SMS.",
8
+ "useCases": [
9
+ {
10
+ "task": "Send SMS messages globally with competitive international rates",
11
+ "fit": "perfect"
12
+ },
13
+ {
14
+ "task": "Implement SMS-based two-factor authentication",
15
+ "fit": "perfect"
16
+ },
17
+ {
18
+ "task": "Make and receive programmatic voice calls",
19
+ "fit": "good"
20
+ },
21
+ {
22
+ "task": "Verify phone numbers with OTP",
23
+ "fit": "perfect"
24
+ }
25
+ ],
26
+ "auth": {
27
+ "method": "api_key",
28
+ "setupSteps": [
29
+ "Sign up at vonage.com",
30
+ "Go to your Dashboard to find your API Key and API Secret",
31
+ "Purchase a virtual number if needed for two-way SMS",
32
+ "Set VONAGE_API_KEY and VONAGE_API_SECRET environment variables"
33
+ ],
34
+ "envVarName": "VONAGE_API_SECRET",
35
+ "codeSnippet": "import Vonage from '@vonage/server-sdk';\nconst vonage = new Vonage({\n apiKey: process.env.VONAGE_API_KEY!,\n apiSecret: process.env.VONAGE_API_SECRET!,\n});"
36
+ },
37
+ "pricing": {
38
+ "model": "usage_based",
39
+ "freeTier": "€2 free credit on signup",
40
+ "startingPrice": "$0.0062 per SMS (US outbound)",
41
+ "costPer": "Varies by country; €0.0062/SMS outbound US; Voice from $0.013/min",
42
+ "pricingUrl": "https://www.vonage.com/communications-apis/sms/pricing"
43
+ },
44
+ "rateLimits": {
45
+ "tier": "default",
46
+ "limit": "30 messages/second (default); can be increased on request",
47
+ "notes": "Default throughput is higher than Twilio long codes. Rate limits can be increased for high-volume use cases.",
48
+ "retryStrategy": "Retry with exponential backoff on 429 responses; Vonage returns message-status in response for each sent message"
49
+ },
50
+ "sdk": {
51
+ "primaryLanguage": "typescript",
52
+ "installCommand": "npm install --save-exact @vonage/server-sdk",
53
+ "importStatement": "import Vonage from '@vonage/server-sdk';",
54
+ "otherLanguages": ["python", "java", "ruby", "php", "dotnet"]
55
+ },
56
+ "codeExamples": [
57
+ {
58
+ "title": "Send an SMS",
59
+ "language": "typescript",
60
+ "code": "import Vonage from '@vonage/server-sdk';\n\nconst vonage = new Vonage({\n apiKey: process.env.VONAGE_API_KEY!,\n apiSecret: process.env.VONAGE_API_SECRET!,\n});\n\nconst response = await vonage.sms.send({\n to: '14155551234',\n from: 'YourBrand', // Alphanumeric sender ID (not available in all countries)\n text: 'Your verification code is 382910. Expires in 10 minutes.',\n});\n\nconst result = response.messages[0];\nif (result?.status === '0') {\n console.log('SMS sent successfully, ID:', result['message-id']);\n} else {\n console.error('Failed to send SMS:', result?.['error-text']);\n}",
61
+ "notes": "Alphanumeric sender IDs (like 'YourBrand') are not supported in all countries, including the US. In the US, you must use a virtual number."
62
+ },
63
+ {
64
+ "title": "Phone number verification with Verify API",
65
+ "language": "typescript",
66
+ "code": "import Vonage from '@vonage/server-sdk';\n\nconst vonage = new Vonage({\n apiKey: process.env.VONAGE_API_KEY!,\n apiSecret: process.env.VONAGE_API_SECRET!,\n});\n\n// Start verification\nconst verifyResponse = await vonage.verify.start({\n number: '14155551234',\n brand: 'MyApp',\n});\nconst requestId = verifyResponse.request_id;\nconsole.log('Verification started, request ID:', requestId);\n\n// Later — check the code user entered\nconst checkResponse = await vonage.verify.check(requestId, '1234');\nif (checkResponse.status === '0') {\n console.log('Phone number verified successfully!');\n}",
67
+ "notes": "The Verify API handles the entire OTP flow — it sends the code, manages retries, and handles timeouts. Much simpler than building your own verification flow."
68
+ }
69
+ ],
70
+ "gotchas": [
71
+ "Vonage response objects use string status codes ('0' for success) not HTTP-style integers. Always check message.status === '0' rather than truthy checks, as error codes are also non-zero strings.",
72
+ "Alphanumeric sender IDs are banned in the US and several other countries. If you need to send from a recognizable name, you'll need to implement this per-country or use a short code.",
73
+ "The Vonage SDK has had significant breaking changes between major versions. Pin to the exact version you test against and review the changelog before upgrading.",
74
+ "International SMS prices vary wildly. A message that costs $0.006 in the US can cost $0.15+ in some countries. Always check country-specific pricing before rolling out globally."
75
+ ],
76
+ "reliability": {
77
+ "uptimeGuarantee": "99.999% uptime commitment on enterprise plans",
78
+ "statusPageUrl": "https://vonageapiservicestatus.com",
79
+ "notes": "Vonage has global carrier connections and data centers in multiple regions. Strong European infrastructure makes it a good choice for EU-focused applications."
80
+ },
81
+ "qualityScore": 7,
82
+ "qualityJustification": "Solid Twilio alternative with competitive international pricing and good European coverage. The TypeScript SDK is functional but not as polished as Twilio's. Verify API is genuinely excellent for OTP flows. Less community resources and documentation depth than Twilio.",
83
+ "alternatives": ["twilio"],
84
+ "complementary": ["resend", "clerk", "stripe"],
85
+ "bestFor": "SMS and voice communications with competitive international rates, especially for European markets or OTP verification flows",
86
+ "lastVerified": "2026-02-25",
87
+ "entryVersion": 1,
88
+ "addedBy": "claude-code-session-2"
89
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "Knock",
3
+ "slug": "knock",
4
+ "category": "notifications",
5
+ "subcategory": "notification-infrastructure",
6
+ "website": "https://knock.app",
7
+ "description": "Knock is a notification infrastructure platform that manages the entire notification workflow: routing users to the right channels (email, push, SMS, in-app), managing user preferences, handling notification templates, and tracking delivery — all in one place. It is built for product engineers who want to offload notification complexity.",
8
+ "useCases": [
9
+ {
10
+ "task": "Build a multi-channel notification system (email + push + in-app + SMS)",
11
+ "fit": "perfect"
12
+ },
13
+ {
14
+ "task": "Let users manage their own notification preferences",
15
+ "fit": "perfect"
16
+ },
17
+ {
18
+ "task": "Trigger notifications from workflows and digests",
19
+ "fit": "perfect"
20
+ },
21
+ {
22
+ "task": "Add an in-app notification feed to a web application",
23
+ "fit": "perfect"
24
+ }
25
+ ],
26
+ "auth": {
27
+ "method": "api_key",
28
+ "setupSteps": [
29
+ "Sign up at knock.app",
30
+ "Create a new environment (development and production are separate)",
31
+ "Go to Settings > API Keys to get your API key",
32
+ "Create users (Knock stores user preferences and notification history)",
33
+ "Set KNOCK_API_KEY environment variable"
34
+ ],
35
+ "envVarName": "KNOCK_API_KEY",
36
+ "codeSnippet": "import Knock from '@knocklabs/node';\nconst knock = new Knock(process.env.KNOCK_API_KEY!);"
37
+ },
38
+ "pricing": {
39
+ "model": "freemium",
40
+ "freeTier": "Up to 10,000 monthly notifications, 1 environment",
41
+ "startingPrice": "$100/month (Starter plan) for 100,000 notifications, 3 environments",
42
+ "costPer": "$1 per 1,000 notifications above plan limit",
43
+ "pricingUrl": "https://knock.app/pricing"
44
+ },
45
+ "rateLimits": {
46
+ "tier": "all tiers",
47
+ "limit": "500 requests/minute for the Workflows API (default)",
48
+ "notes": "Rate limits are per API key. Bulk workflow triggers and batch operations available. Contact support for higher limits.",
49
+ "retryStrategy": "Knock handles delivery retries internally per channel. Implement application-level retry with backoff for 429 API responses."
50
+ },
51
+ "sdk": {
52
+ "primaryLanguage": "typescript",
53
+ "installCommand": "npm install --save-exact @knocklabs/node",
54
+ "importStatement": "import Knock from '@knocklabs/node';",
55
+ "otherLanguages": ["python", "ruby", "go", "java", "elixir"]
56
+ },
57
+ "codeExamples": [
58
+ {
59
+ "title": "Trigger a notification workflow",
60
+ "language": "typescript",
61
+ "code": "import Knock from '@knocklabs/node';\n\nconst knock = new Knock(process.env.KNOCK_API_KEY!);\n\n// Identify the recipient (creates or updates the user in Knock)\nawait knock.users.identify('user-123', {\n name: 'Jane Smith',\n email: 'jane@example.com',\n phone_number: '+14155551234',\n});\n\n// Trigger a workflow\nconst result = await knock.workflows.trigger('new-comment', {\n recipients: ['user-123'],\n data: {\n commenter_name: 'Bob',\n post_title: 'My awesome post',\n comment_text: 'Great post, Jane!',\n post_url: 'https://app.com/posts/456',\n },\n actor: 'user-456', // Who triggered the action\n});\n\nconsole.log('Workflow triggered:', result.workflow_run_id);",
62
+ "notes": "Workflows are defined in the Knock dashboard with channel routing logic. The 'new-comment' key matches the workflow key you created. Data fields map to template variables in your notification templates."
63
+ }
64
+ ],
65
+ "gotchas": [
66
+ "Knock requires you to 'identify' users before triggering notifications. If you trigger a workflow for an unidentified user, the notification is silently dropped. Always call users.identify() when users sign up in your app.",
67
+ "Knock's pricing scales by notifications sent, not users. If your app sends frequent notifications (e.g., a busy collaboration tool), costs can grow quickly. The 10k/month free tier is limiting for high-activity apps.",
68
+ "Knock manages notification preferences, but your app still needs to register push tokens (APNs/FCM). You send the token to Knock, which stores it per user — but you still need to implement the mobile push registration flow.",
69
+ "Environments in Knock are completely isolated. Workflows, templates, and configurations in Development don't carry over to Production — you must recreate them. Use the dashboard export/import to migrate."
70
+ ],
71
+ "reliability": {
72
+ "uptimeGuarantee": "99.9% uptime on paid plans",
73
+ "statusPageUrl": "https://status.knock.app",
74
+ "notes": "Knock is a younger platform but has strong reliability track record. Used by Vercel, Linear, and other developer-focused companies."
75
+ },
76
+ "qualityScore": 8,
77
+ "qualityJustification": "Best developer experience for building complex notification systems. The workflow model, user preference management, and in-app feed components are genuinely excellent. Pricing is the main constraint — $100/month minimum for production use is steep for indie developers. Excellent TypeScript SDK.",
78
+ "alternatives": ["novu", "onesignal"],
79
+ "complementary": ["resend", "twilio", "clerk"],
80
+ "bestFor": "Multi-channel notification infrastructure with workflow routing, user preferences, and in-app notification feeds for SaaS products",
81
+ "lastVerified": "2026-02-25",
82
+ "entryVersion": 1,
83
+ "addedBy": "claude-code-session-2"
84
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "Novu",
3
+ "slug": "novu",
4
+ "category": "notifications",
5
+ "subcategory": "notification-infrastructure",
6
+ "website": "https://novu.co",
7
+ "description": "Novu is an open-source notification infrastructure platform supporting email, SMS, push, in-app, and chat notifications from a single API. As an open-source alternative to Knock and Courier, it can be self-hosted for full data control, or used as a managed cloud service with a generous free tier.",
8
+ "useCases": [
9
+ {
10
+ "task": "Build a multi-channel notification system with open-source flexibility",
11
+ "fit": "perfect"
12
+ },
13
+ {
14
+ "task": "Self-host notification infrastructure for data control",
15
+ "fit": "perfect"
16
+ },
17
+ {
18
+ "task": "Add an in-app notification bell/feed to a web app",
19
+ "fit": "perfect"
20
+ },
21
+ {
22
+ "task": "Send notifications via multiple providers with fallback logic",
23
+ "fit": "good"
24
+ }
25
+ ],
26
+ "auth": {
27
+ "method": "api_key",
28
+ "setupSteps": [
29
+ "Sign up at novu.co (or self-host via Docker)",
30
+ "Go to Settings > API Keys in the Novu dashboard",
31
+ "Copy your API Key",
32
+ "Set NOVU_API_KEY environment variable",
33
+ "Create notification workflows (called 'workflows' or 'notifications') in the dashboard"
34
+ ],
35
+ "envVarName": "NOVU_API_KEY",
36
+ "codeSnippet": "import { Novu } from '@novu/node';\nconst novu = new Novu(process.env.NOVU_API_KEY!);"
37
+ },
38
+ "pricing": {
39
+ "model": "freemium",
40
+ "freeTier": "30,000 events/month, unlimited subscribers (cloud)",
41
+ "startingPrice": "$250/month (Business plan) for 250,000 events/month",
42
+ "costPer": "Cloud: $0.01 per event above free tier; self-hosted is free",
43
+ "pricingUrl": "https://novu.co/pricing"
44
+ },
45
+ "rateLimits": {
46
+ "tier": "free tier (cloud)",
47
+ "limit": "30,000 events/month, 60 requests/minute API rate limit",
48
+ "notes": "Self-hosted has no limits beyond your infrastructure capacity. Cloud rate limits scale with paid plans.",
49
+ "retryStrategy": "Implement standard exponential backoff for 429 responses. Novu handles per-channel delivery retries automatically."
50
+ },
51
+ "sdk": {
52
+ "primaryLanguage": "typescript",
53
+ "installCommand": "npm install --save-exact @novu/node",
54
+ "importStatement": "import { Novu } from '@novu/node';",
55
+ "otherLanguages": ["python", "php", "ruby", "java", "go", "dotnet"]
56
+ },
57
+ "codeExamples": [
58
+ {
59
+ "title": "Trigger a notification",
60
+ "language": "typescript",
61
+ "code": "import { Novu } from '@novu/node';\n\nconst novu = new Novu(process.env.NOVU_API_KEY!);\n\n// Identify subscriber (creates if not exists)\nawait novu.subscribers.identify('user-123', {\n firstName: 'Jane',\n lastName: 'Smith',\n email: 'jane@example.com',\n phone: '+14155551234',\n});\n\n// Trigger workflow\nconst result = await novu.trigger('order-shipped', {\n to: { subscriberId: 'user-123' },\n payload: {\n orderId: 'order_456',\n trackingUrl: 'https://track.example.com/order_456',\n estimatedDelivery: 'Feb 28, 2026',\n },\n});\n\nconsole.log('Triggered:', result.data?.transactionId);",
62
+ "notes": "Workflows are defined in the Novu dashboard. The first argument to trigger() is the workflow trigger ID. Subscribers are automatically created if they don't exist."
63
+ }
64
+ ],
65
+ "gotchas": [
66
+ "Novu's open-source status means the self-hosted version can lag behind the cloud version in features. Check the GitHub releases before choosing self-hosting for production.",
67
+ "The jump from free tier (30k events) to paid ($250/month Business) is steep with no intermediate tier. For apps between 30k-250k events, consider whether the cost is justified versus simpler alternatives.",
68
+ "Novu's workflow builder in the dashboard is a visual editor — complex workflows with branching logic are harder to version-control than code-based approaches like Knock.",
69
+ "Subscriber management is separate from your user database. You must sync users to Novu (via identify()) on signup and keep them in sync. A missed identify call means notifications get dropped silently."
70
+ ],
71
+ "reliability": {
72
+ "uptimeGuarantee": "99.5% uptime on cloud; self-hosted depends on your infrastructure",
73
+ "statusPageUrl": "https://novustatus.com",
74
+ "notes": "Novu cloud is improving reliability. Self-hosted on your own infrastructure gives full control. The project is actively maintained with a large open-source community."
75
+ },
76
+ "qualityScore": 7,
77
+ "qualityJustification": "Best option if open-source and self-hosting are important. The 30k/month free cloud tier is the most generous in the notification infrastructure category. Dashboard UX is improving. Less polished than Knock for complex workflows, but the self-hosting option is a genuine differentiator.",
78
+ "alternatives": ["knock", "onesignal"],
79
+ "complementary": ["resend", "twilio", "supabase"],
80
+ "bestFor": "Multi-channel notification infrastructure with open-source flexibility and self-hosting option for data control",
81
+ "lastVerified": "2026-02-25",
82
+ "entryVersion": 1,
83
+ "addedBy": "claude-code-session-2"
84
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "OneSignal",
3
+ "slug": "onesignal",
4
+ "category": "notifications",
5
+ "subcategory": "push-notifications",
6
+ "website": "https://onesignal.com",
7
+ "description": "OneSignal is the most widely used push notification service, supporting web push, iOS, Android, email, and SMS from a single platform. It provides a free tier that is genuinely production-grade, making it the default choice for apps needing multi-channel notification delivery without infrastructure complexity.",
8
+ "useCases": [
9
+ {
10
+ "task": "Send push notifications to mobile app users (iOS and Android)",
11
+ "fit": "perfect"
12
+ },
13
+ {
14
+ "task": "Send web push notifications to browser users",
15
+ "fit": "perfect"
16
+ },
17
+ {
18
+ "task": "Send multi-channel notifications (push + email + SMS)",
19
+ "fit": "perfect"
20
+ },
21
+ {
22
+ "task": "Send targeted notifications based on user segments",
23
+ "fit": "perfect"
24
+ }
25
+ ],
26
+ "auth": {
27
+ "method": "api_key",
28
+ "setupSteps": [
29
+ "Sign up at onesignal.com",
30
+ "Create a new app in the dashboard",
31
+ "Configure your platforms (iOS/Android/Web) with your APNs/FCM credentials",
32
+ "Go to Settings > Keys & IDs to find your App ID and REST API Key",
33
+ "Set ONESIGNAL_APP_ID and ONESIGNAL_API_KEY environment variables"
34
+ ],
35
+ "envVarName": "ONESIGNAL_API_KEY",
36
+ "codeSnippet": "// Server-side notification sending\nconst response = await fetch('https://onesignal.com/api/v1/notifications', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Basic ${process.env.ONESIGNAL_API_KEY}`,\n },\n body: JSON.stringify(notification),\n});"
37
+ },
38
+ "pricing": {
39
+ "model": "freemium",
40
+ "freeTier": "Unlimited subscribers, unlimited notifications, unlimited apps (free plan)",
41
+ "startingPrice": "$9/month for Growth plan with advanced features",
42
+ "costPer": "Free plan covers core push notifications; paid plans add segmentation, analytics, A/B testing",
43
+ "pricingUrl": "https://onesignal.com/pricing"
44
+ },
45
+ "rateLimits": {
46
+ "tier": "free tier",
47
+ "limit": "No documented notification rate limit; API requests: 2,500 per hour",
48
+ "notes": "OneSignal batches notifications internally. For large sends, use segments rather than individual API calls.",
49
+ "retryStrategy": "Implement exponential backoff for 429 and 5xx API responses. OneSignal handles delivery retries internally."
50
+ },
51
+ "sdk": {
52
+ "primaryLanguage": "typescript",
53
+ "installCommand": "npm install --save-exact @onesignal/node-onesignal",
54
+ "importStatement": "import * as OneSignal from '@onesignal/node-onesignal';",
55
+ "otherLanguages": ["python", "ruby", "java", "php", "csharp", "swift", "android"]
56
+ },
57
+ "codeExamples": [
58
+ {
59
+ "title": "Send a push notification to specific users",
60
+ "language": "typescript",
61
+ "code": "import * as OneSignal from '@onesignal/node-onesignal';\n\nconst configuration = OneSignal.createConfiguration({\n restApiKey: process.env.ONESIGNAL_API_KEY!,\n});\nconst client = new OneSignal.DefaultApi(configuration);\n\nconst notification = new OneSignal.Notification();\nnotification.app_id = process.env.ONESIGNAL_APP_ID!;\nnotification.contents = { en: 'Your order has shipped! Track it now.' };\nnotification.headings = { en: 'Order Update' };\n\n// Send to specific users by external ID\nnotification.include_aliases = {\n external_id: ['user-123', 'user-456'],\n};\nnotification.target_channel = 'push';\n\nconst response = await client.createNotification(notification);\nconsole.log('Notification ID:', response.id);\nconsole.log('Recipients:', response.recipients);",
62
+ "notes": "Use external_id to identify users by your own user ID (set when registering devices). This avoids managing OneSignal's player_id internally."
63
+ }
64
+ ],
65
+ "gotchas": [
66
+ "Setting up push notifications requires configuring APNs certificates (iOS) and FCM keys (Android) in the OneSignal dashboard. This is the most time-consuming part of setup and requires Apple Developer account access.",
67
+ "Web push notifications require HTTPS. You cannot test web push on localhost — use ngrok, Vercel preview deployments, or a staging environment with HTTPS.",
68
+ "OneSignal's free plan stores only 90 days of notification history. If you need longer retention for analytics or audit logs, export data regularly or upgrade to a paid plan.",
69
+ "Device tokens (player IDs) can become stale if users uninstall and reinstall the app. Clean up invalid tokens from your database using OneSignal's device deletion API."
70
+ ],
71
+ "reliability": {
72
+ "uptimeGuarantee": "99.9% uptime SLA on paid plans",
73
+ "statusPageUrl": "https://status.onesignal.com",
74
+ "notes": "OneSignal processes billions of notifications per day. Very high reliability with global infrastructure."
75
+ },
76
+ "qualityScore": 8,
77
+ "qualityJustification": "Best push notification service with the most generous free tier in the category — truly unlimited subscribers and notifications at no cost. Multi-channel support (push + email + SMS) from one platform is convenient. Setup complexity for mobile (APNs/FCM) is unavoidable industry-wide.",
78
+ "alternatives": ["knock", "novu"],
79
+ "complementary": ["twilio", "resend", "clerk"],
80
+ "bestFor": "Mobile and web push notifications with an unlimited free tier — ideal for apps that need multi-channel (push + email + SMS) from a single platform",
81
+ "lastVerified": "2026-02-25",
82
+ "entryVersion": 1,
83
+ "addedBy": "claude-code-session-2"
84
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "Lemon Squeezy",
3
+ "slug": "lemonsqueezy",
4
+ "category": "payments",
5
+ "subcategory": "merchant-of-record",
6
+ "website": "https://lemonsqueezy.com",
7
+ "description": "Lemon Squeezy is a Merchant of Record platform for selling digital products, software licenses, and SaaS subscriptions. Like Paddle, it handles all tax compliance globally. Designed with a developer-first API and a clean merchant dashboard. Particularly strong for selling one-time digital products (ebooks, templates, plugins) in addition to subscriptions.",
8
+ "useCases": [
9
+ {
10
+ "task": "Sell digital products (ebooks, templates, plugins) with instant delivery",
11
+ "fit": "perfect"
12
+ },
13
+ {
14
+ "task": "Accept SaaS subscription payments with global tax handling",
15
+ "fit": "perfect"
16
+ },
17
+ {
18
+ "task": "Generate and manage software license keys",
19
+ "fit": "good"
20
+ },
21
+ {
22
+ "task": "Set up a simple checkout page without building a custom payment UI",
23
+ "fit": "good"
24
+ }
25
+ ],
26
+ "auth": {
27
+ "method": "api_key",
28
+ "setupSteps": [
29
+ "Create a Lemon Squeezy account at lemonsqueezy.com",
30
+ "Verify your account and complete store setup",
31
+ "Add your store and configure store details",
32
+ "Create products in your store dashboard",
33
+ "Go to Settings > API and generate an API key",
34
+ "Set up webhooks in Settings > Webhooks and copy the signing secret"
35
+ ],
36
+ "envVarName": "LEMONSQUEEZY_API_KEY",
37
+ "codeSnippet": "import { lemonSqueezySetup } from '@lemonsqueezy/lemonsqueezy.js';\n\nlemonSqueezySetup({\n apiKey: process.env.LEMONSQUEEZY_API_KEY!,\n onError: (error) => console.error('Lemon Squeezy error:', error),\n});"
38
+ },
39
+ "pricing": {
40
+ "model": "usage_based",
41
+ "freeTier": null,
42
+ "startingPrice": "5% + $0.50 per transaction (Starter)",
43
+ "costPer": "5% + $0.50 per transaction; Enterprise plans negotiated for high volume",
44
+ "pricingUrl": "https://www.lemonsqueezy.com/pricing"
45
+ },
46
+ "rateLimits": {
47
+ "tier": "standard",
48
+ "limit": "120 API requests/minute",
49
+ "notes": "Webhooks delivered at least once with retry on failure. Event IDs should be used for idempotency.",
50
+ "retryStrategy": "Use the event_id from webhook payload as idempotency key. Return HTTP 200 immediately and process async."
51
+ },
52
+ "sdk": {
53
+ "primaryLanguage": "typescript",
54
+ "installCommand": "npm install --save-exact @lemonsqueezy/lemonsqueezy.js",
55
+ "importStatement": "import { lemonSqueezySetup, getProducts, createCheckout } from '@lemonsqueezy/lemonsqueezy.js';",
56
+ "otherLanguages": ["php", "python"]
57
+ },
58
+ "codeExamples": [
59
+ {
60
+ "title": "Create a checkout session",
61
+ "language": "typescript",
62
+ "code": "import { lemonSqueezySetup, createCheckout } from '@lemonsqueezy/lemonsqueezy.js';\n\nlemonSqueezySetup({\n apiKey: process.env.LEMONSQUEEZY_API_KEY!,\n});\n\n// Create a checkout for a specific variant\nconst { data, error } = await createCheckout(\n process.env.LEMONSQUEEZY_STORE_ID!, // Your store ID\n process.env.LEMONSQUEEZY_VARIANT_ID!, // The product variant ID\n {\n checkoutOptions: {\n embed: false,\n media: true,\n logo: true,\n },\n checkoutData: {\n email: 'customer@example.com', // Pre-fill customer email\n custom: {\n userId: 'user_123', // Pass through to webhooks\n },\n },\n productOptions: {\n redirectUrl: 'https://yourapp.com/success',\n receiptButtonText: 'Go to Dashboard',\n receiptThankYouNote: 'Thank you for subscribing!',\n },\n }\n);\n\nif (error) {\n console.error('Failed to create checkout:', error);\n throw new Error(error.title);\n}\n\nconst checkoutUrl = data?.data.attributes.url;\nconsole.log('Checkout URL:', checkoutUrl);\n// Redirect user to checkoutUrl",
63
+ "notes": "Lemon Squeezy checkout URLs are single-use and expire after 24 hours. Always generate a fresh checkout URL per customer session. Pass custom data (like userId) in checkoutData.custom — it will be available in webhook payloads."
64
+ },
65
+ {
66
+ "title": "Verify and handle webhook",
67
+ "language": "typescript",
68
+ "code": "import crypto from 'crypto';\nimport type { Request, Response } from 'express';\n\ninterface LemonSqueezyWebhookPayload {\n meta: {\n event_name: string;\n custom_data?: Record<string, string>;\n };\n data: {\n id: string;\n attributes: Record<string, unknown>;\n };\n}\n\nexport async function handleLemonSqueezyWebhook(req: Request, res: Response) {\n const rawBody = req.body as string; // Must be raw string before JSON parse\n const signature = req.headers['x-signature'] as string;\n\n // Verify HMAC-SHA256 signature\n const hmac = crypto.createHmac('sha256', process.env.LEMONSQUEEZY_WEBHOOK_SECRET!);\n const digest = hmac.update(rawBody).digest('hex');\n\n if (!crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature))) {\n console.error('Invalid webhook signature');\n return res.status(401).send('Invalid signature');\n }\n\n const payload = JSON.parse(rawBody) as LemonSqueezyWebhookPayload;\n const eventName = payload.meta.event_name;\n const eventId = payload.data.id; // Use as idempotency key\n const customData = payload.meta.custom_data;\n\n switch (eventName) {\n case 'order_created': {\n const order = payload.data.attributes;\n console.log('New order:', eventId, 'status:', order['status']);\n // Deliver digital product or provision access\n if (order['status'] === 'paid') {\n await deliverProduct(customData?.userId, eventId);\n }\n break;\n }\n case 'subscription_created': {\n const subscription = payload.data.attributes;\n console.log('New subscription:', eventId, 'status:', subscription['status']);\n await provisionSubscription(customData?.userId, payload.data.id);\n break;\n }\n case 'subscription_cancelled': {\n console.log('Subscription cancelled:', eventId);\n await scheduleAccessRevocation(customData?.userId);\n break;\n }\n default:\n console.log('Unhandled event:', eventName);\n }\n\n return res.status(200).json({ received: true, eventId });\n}\n\nasync function deliverProduct(userId: string | undefined, orderId: string) {\n // Your product delivery logic here\n}\n\nasync function provisionSubscription(userId: string | undefined, subscriptionId: string) {\n // Your subscription provisioning logic here\n}\n\nasync function scheduleAccessRevocation(userId: string | undefined) {\n // Your access revocation logic here\n}",
69
+ "notes": "Lemon Squeezy uses HMAC-SHA256 for webhook signature verification — use crypto.timingSafeEqual() to prevent timing attacks. The raw body must be used for signature verification before parsing as JSON. Use payload.data.id as an idempotency key."
70
+ }
71
+ ],
72
+ "gotchas": [
73
+ "Lemon Squeezy is newer and smaller than Paddle or Stripe. In 2024, Stripe acquired Lemon Squeezy. While this is broadly positive for stability, the roadmap may change and some features may eventually be consolidated into Stripe's MoR offerings.",
74
+ "Like Paddle, Lemon Squeezy is the Merchant of Record — your company name does NOT appear on bank statements. Some B2B customers require invoices from the actual vendor and may push back on the MoR model for procurement.",
75
+ "Lemon Squeezy's API rate limit (120 requests/minute) is lower than Paddle's. If you have bulk operations (syncing subscribers, updating prices across many products), implement request queuing and exponential backoff.",
76
+ "License key generation is a powerful feature but must be explicitly enabled per product and configured with a key pattern. Keys are not automatically generated for subscriptions — only for products with license keys enabled."
77
+ ],
78
+ "reliability": {
79
+ "uptimeGuarantee": "99.9% uptime (no published SLA)",
80
+ "statusPageUrl": "https://lemonsqueezy.statuspage.io",
81
+ "notes": "Stripe-backed infrastructure after 2024 acquisition. Handles PCI DSS compliance and tax remittance as Merchant of Record globally."
82
+ },
83
+ "qualityScore": 7,
84
+ "qualityJustification": "Excellent developer experience for selling digital products and licenses. Cleaner UI than Paddle, good API documentation. Acquisition by Stripe in 2024 provides stability but also introduces uncertainty about long-term direction. Scores below Paddle for market maturity and enterprise readiness.",
85
+ "alternatives": ["paddle", "stripe"],
86
+ "complementary": ["resend", "clerk", "supabase"],
87
+ "bestFor": "Selling digital products, software licenses, and SaaS subscriptions without managing tax compliance — particularly strong for individual creators and small teams",
88
+ "lastVerified": "2026-02-25",
89
+ "entryVersion": 1,
90
+ "addedBy": "claude-code-session-4"
91
+ }
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "Paddle",
3
+ "slug": "paddle",
4
+ "category": "payments",
5
+ "subcategory": "merchant-of-record",
6
+ "website": "https://paddle.com",
7
+ "description": "Paddle is a Merchant of Record (MoR) that handles payments, subscriptions, global tax compliance (VAT, GST, sales tax), and fraud detection for SaaS businesses. You sell through Paddle — they handle the tax liability, meaning you never have to register for VAT in individual countries. Ideal for indie developers and SaaS companies selling globally without a dedicated finance team.",
8
+ "useCases": [
9
+ {
10
+ "task": "Accept SaaS subscription payments globally without handling tax compliance",
11
+ "fit": "perfect"
12
+ },
13
+ {
14
+ "task": "Sell a software product to international customers with automatic VAT/GST",
15
+ "fit": "perfect"
16
+ },
17
+ {
18
+ "task": "Manage subscription upgrades, downgrades, and trials",
19
+ "fit": "good"
20
+ },
21
+ {
22
+ "task": "Process one-time payments for digital products",
23
+ "fit": "good"
24
+ }
25
+ ],
26
+ "auth": {
27
+ "method": "api_key",
28
+ "setupSteps": [
29
+ "Register a Paddle account at paddle.com",
30
+ "Verify your business details and get approved as a Paddle seller",
31
+ "Add your products and prices in the Paddle Dashboard",
32
+ "Go to Developer Tools > Authentication and generate your API key",
33
+ "Configure webhooks in Developer Tools > Notifications and copy the webhook secret"
34
+ ],
35
+ "envVarName": "PADDLE_API_KEY",
36
+ "codeSnippet": "import { Paddle, Environment } from '@paddle/paddle-node-sdk';\n\nconst paddle = new Paddle(process.env.PADDLE_API_KEY!, {\n environment: Environment.Sandbox, // Use Environment.Production for live\n});"
37
+ },
38
+ "pricing": {
39
+ "model": "usage_based",
40
+ "freeTier": null,
41
+ "startingPrice": "5% + $0.50 per transaction (Starter)",
42
+ "costPer": "5% + $0.50/transaction up to $10K MRR; custom rates above $50K MRR",
43
+ "pricingUrl": "https://paddle.com/pricing/"
44
+ },
45
+ "rateLimits": {
46
+ "tier": "standard",
47
+ "limit": "200 API requests/minute",
48
+ "notes": "Webhook events are delivered at least once — implement idempotency keys to handle duplicates. Paddle retries failed webhooks for up to 72 hours.",
49
+ "retryStrategy": "Implement webhook idempotency using the event ID. Return 200 quickly; process async."
50
+ },
51
+ "sdk": {
52
+ "primaryLanguage": "typescript",
53
+ "installCommand": "npm install --save-exact @paddle/paddle-node-sdk",
54
+ "importStatement": "import { Paddle, Environment } from '@paddle/paddle-node-sdk';",
55
+ "otherLanguages": ["python", "php", "ruby"]
56
+ },
57
+ "codeExamples": [
58
+ {
59
+ "title": "Create a subscription checkout link",
60
+ "language": "typescript",
61
+ "code": "import { Paddle, Environment } from '@paddle/paddle-node-sdk';\n\nconst paddle = new Paddle(process.env.PADDLE_API_KEY!, {\n environment: Environment.Sandbox,\n});\n\n// Create a transaction (checkout) for a subscription price\nconst transaction = await paddle.transactions.create({\n items: [\n {\n priceId: 'pri_01h1234abcde', // Your Paddle price ID\n quantity: 1,\n },\n ],\n customData: {\n userId: 'user_123',\n planName: 'pro',\n },\n checkoutSettings: {\n successUrl: 'https://yourapp.com/success',\n },\n});\n\n// Redirect user to checkout\nconst checkoutUrl = transaction.checkout?.url;\nconsole.log('Checkout URL:', checkoutUrl);",
62
+ "notes": "Paddle generates a hosted checkout page — redirect the user to transaction.checkout.url. You do not need to build your own payment form. Paddle's overlay checkout can also be embedded on your page using Paddle.js."
63
+ },
64
+ {
65
+ "title": "Handle Paddle webhook events",
66
+ "language": "typescript",
67
+ "code": "import { Paddle, Environment } from '@paddle/paddle-node-sdk';\nimport type { Request, Response } from 'express';\n\nconst paddle = new Paddle(process.env.PADDLE_API_KEY!, {\n environment: Environment.Sandbox,\n});\n\nexport async function handlePaddleWebhook(req: Request, res: Response) {\n const signature = req.headers['paddle-signature'] as string;\n const rawBody = req.body as string; // Must be raw string, not parsed JSON\n\n let event;\n try {\n event = paddle.webhooks.unmarshal(\n rawBody,\n process.env.PADDLE_WEBHOOK_SECRET!,\n signature\n );\n } catch (err) {\n console.error('Webhook signature verification failed:', err);\n return res.status(400).send('Invalid signature');\n }\n\n // Use event.eventId as idempotency key to avoid double-processing\n const eventId = event.eventId;\n\n switch (event.eventType) {\n case 'subscription.created': {\n const subscription = event.data;\n console.log('New subscription:', subscription.id, 'customer:', subscription.customerId);\n // Provision access for the customer\n await provisionSubscription(subscription.customerId, subscription.id);\n break;\n }\n case 'transaction.completed': {\n const transaction = event.data;\n console.log('Payment succeeded:', transaction.id, 'total:', transaction.details?.totals?.total);\n // Update payment records\n await recordPayment(transaction.id, transaction.customerId);\n break;\n }\n case 'subscription.canceled': {\n const subscription = event.data;\n console.log('Subscription canceled:', subscription.id);\n // Revoke access at period end\n await scheduleAccessRevocation(subscription.customerId, subscription.scheduledChange?.effectiveAt);\n break;\n }\n default:\n console.log('Unhandled event type:', event.eventType);\n }\n\n // Always return 200 immediately\n return res.status(200).json({ received: true, eventId });\n}\n\nasync function provisionSubscription(customerId: string, subscriptionId: string) {\n // Your provisioning logic here\n}\n\nasync function recordPayment(transactionId: string, customerId: string) {\n // Your payment recording logic here\n}\n\nasync function scheduleAccessRevocation(customerId: string, effectiveAt?: string) {\n // Your access revocation logic here\n}",
68
+ "notes": "Paddle webhooks must be verified using paddle.webhooks.unmarshal(). Pass the raw request body as a string — do not parse it as JSON before verification. Use the eventId as an idempotency key to safely handle Paddle's at-least-once delivery."
69
+ }
70
+ ],
71
+ "gotchas": [
72
+ "Paddle is the Merchant of Record — customers see 'Paddle' on their bank statement, not your company name. Some customers may be confused by this and initiate chargebacks thinking it's a fraudulent charge. Add a note to your receipt emails explaining this.",
73
+ "Paddle's Merchant of Record model means you CANNOT easily migrate your subscriber base to another payment processor. All subscription data (customer, payment method, billing history) is locked in Paddle. Plan your stack accordingly before onboarding thousands of subscribers.",
74
+ "Paddle's 5% fee applies to every transaction including renewals. At scale, this becomes expensive compared to Stripe (2.9% + $0.30) — especially for low-ticket, high-volume subscriptions. Calculate the break-even point for your price point.",
75
+ "Paddle's sandbox environment uses different API keys than production. Test mode and live mode are completely separate — you cannot transfer products, prices, or customer data between them."
76
+ ],
77
+ "reliability": {
78
+ "uptimeGuarantee": "99.9% uptime SLA",
79
+ "statusPageUrl": "https://paddle.statuspage.io",
80
+ "notes": "Globally distributed payment infrastructure with automatic failover. Paddle handles PCI DSS compliance on your behalf as Merchant of Record."
81
+ },
82
+ "qualityScore": 8,
83
+ "qualityJustification": "Best choice for indie hackers and small SaaS teams that want to sell globally without a finance/legal team. Handles VAT, GST, and sales tax automatically as Merchant of Record. SDK quality is good; dashboard is polished. Transaction fee (5%) is higher than Stripe but includes tax handling that would otherwise require a separate service like TaxJar.",
84
+ "alternatives": ["lemonsqueezy", "stripe"],
85
+ "complementary": ["stripe", "resend", "clerk", "supabase"],
86
+ "bestFor": "Selling SaaS subscriptions and digital products globally without managing tax compliance — Paddle acts as the legal seller in each country",
87
+ "lastVerified": "2026-02-25",
88
+ "entryVersion": 1,
89
+ "addedBy": "claude-code-session-4"
90
+ }