Skip to Content
WebhooksCreate Webhook

Creating a Webhook

Creating a webhook allows you to receive real-time notifications about events in your application and track changes in your subscribers’ status.

Quick Start

Create a webhook

Log into your account and navigate to Settings → Webhooks in the control panel.

Create Webhook

Fill out the form and save settings

Fill in the required fields of the webhook creation form:

  • Name - give a descriptive name to your webhook
  • URL - specify the URL of your endpoint to receive notifications
  • Events - select the events you want to subscribe to
  • Status - activate the webhook

Click “Create” to create the webhook. The system will start sending notifications to the specified URL.

Save Webhook

Available Events

Select one or more events to subscribe to:

EventDescription
Payment CompletedSuccessfully completed payment (one-time or first subscription payment)
Subscription CreatedCreation of a new subscription
Subscription UpdatedSubscription update (plan change, status change, etc.)
Subscription CancelledSubscription cancellation
Refund CreatedCreation of a refund

Event subscription: Select only the events that are necessary for your application to avoid unnecessary load on your server.

Endpoint Requirements

Mandatory Requirements

  • HTTPS: Webhooks are sent only to HTTPS URLs
  • Response Status: Your endpoint must return HTTP status 200-299 for successful processing
  • Timeout: Response timeout is 10 seconds
  • Idempotency: Be prepared to receive duplicate events

Endpoint Example

const express = require('express'); const app = express(); app.use(express.json()); app.post('/monetize/webhook', async (req, res) => { try { const event = req.body; // Process event by type switch (event.type) { case 'payment.completed': await handlePaymentCompleted(event.data); break; case 'subscription.created': await handleSubscriptionCreated(event.data); break; // ... other event types default: console.log(`Unhandled event type: ${event.type}`); } res.status(200).json({ status: 'success' }); } catch (err) { console.error(`Webhook error: ${err}`); res.status(500).json({ error: 'Internal error' }); } }); async function handlePaymentCompleted(data) { console.log(`Payment completed: ${data.payment.id}`); // Activate user access await activateUserAccess(data.user.id); }

Secret Key Setup

Why Secret Key is Needed

The secret key is used to create an HMAC SHA256 signature, which allows you to:

  • Verify authenticity of notifications from Monetize.software
  • Prevent attacks with fake webhook notifications
  • Ensure security of your endpoint

Secret Key Generation

Create a cryptographically strong secret key:

const crypto = require('crypto'); // Generate 32-byte key const secret = crypto.randomBytes(32).toString('hex'); console.log('Secret key:', secret);

Signature Verification

When specifying a secret key, each request will contain the X-Monetize-Signature header:

const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); // Remove "sha256=" prefix from header signature = signature.replace('sha256=', ''); return crypto.timingSafeEqual( Buffer.from(expectedSignature), Buffer.from(signature) ); } // Usage in middleware app.post('/monetize/webhook', (req, res) => { const signature = req.headers['x-monetize-signature']; const payload = JSON.stringify(req.body); if (!verifyWebhookSignature(payload, signature, YOUR_SECRET)) { return res.status(401).json({ error: 'Invalid signature' }); } // Process webhook... });

Security: Always verify the webhook signature in production to ensure the request is truly from Monetize.software.

Testing Functionality

After creating a webhook:

  1. Create a test transaction in your application
  2. Check the logs in the control panel (Settings → Webhooks → your webhook → View Logs)
  3. Ensure receipt of notifications at your endpoint
  4. Verify correctness of data processing

Webhook Management

Viewing Created Webhooks

The webhooks table displays:

  • Name - webhook name
  • Status - active/inactive
  • Events - subscribed events
  • Creation Date - when the webhook was created
  • Last Call - time of the last successful call

Webhook Actions

For each webhook, the following actions are available:

  • View Logs - history of all notification delivery attempts
  • Edit - modify webhook settings
  • Delete - complete webhook deletion

Viewing Logs

Logs contain detailed information about each delivery attempt:

  • Date and Time - when the delivery attempt was made
  • Event Type - which event triggered the notification
  • Paywall ID - identifier of the associated paywall
  • HTTP Status - response code from your endpoint
  • Response Body - response content
  • Attempt Count - delivery attempt number
  • Error Message - error details for failed deliveries

Limits and Restrictions

LimitationValue
Maximum payload size1 MB
Timeout10 seconds
Maximum webhooks per account10
Log retention30 days
Retry delivery attempts5 attempts

Retry Delivery

The system automatically retries delivery in case of failure:

  • Number of attempts: 5 attempts
  • Intervals: 5, 10, 20, 40, and 80 minutes
  • Retry conditions: HTTP status 5xx or connection timeout

Attempt logging: All delivery attempts are logged and available in the control panel.

Security Recommendations

Basic Principles

  1. Always verify the signature when using a secret key
  2. Use HTTPS for all webhook URLs
  3. Don’t log full webhook data in plain text
  4. Restrict access to webhook endpoints
  5. Validate data before processing

Error Handling

app.post('/monetize/webhook', async (req, res) => { try { // Verify signature if (!verifySignature(req)) { return res.status(401).json({ error: 'Unauthorized' }); } // Validate data structure if (!isValidEvent(req.body)) { return res.status(400).json({ error: 'Invalid payload' }); } // Idempotent processing const eventId = req.body.id; if (await isEventProcessed(eventId)) { return res.status(200).json({ status: 'already_processed' }); } // Process event await processEvent(req.body); await markEventAsProcessed(eventId); res.status(200).json({ status: 'success' }); } catch (error) { console.error('Webhook error:', error); res.status(500).json({ error: 'Internal error' }); } });

Troubleshooting

Common Issues

IssueCauseSolution
HTTP 401Invalid signatureCheck secret key
HTTP 404URL unavailableCheck URL correctness
HTTP 500Error on your serverCheck your application logs
TimeoutSlow processingOptimize processing time
Duplicate eventsNetwork issuesImplement idempotent processing

Debugging

  1. Check webhook logs in the control panel
  2. Review payload of sent events
  3. Check response status of your endpoint
  4. Ensure URL availability through browser or curl
  5. Check headers of requests and responses

Next Steps

Last updated on