Page cover image

🪝After Sell Webhook

You can set up an after-sales webhook for your URL or server, which will automatically trigger after each completed sale.

With webhook you can build custom integration or logic after each sale of a digital product

Setup webhook to your API endpoint

Go to Store page -> Settings

  1. Paste webhook url to which you would like to recieve after sell notifications and click Apply

  2. Now after sell you will receive notifications in JSON format to your webhook url

Example of JSON which you receive after sell:


{
    "uuid": "4f45e140", // Unique transaction UUID
    "amount": 40,
    "total_amount": 37.74,
    "commission": 2.26,
    "vat": 3.75,
     "metadata" : { 
        "order_id": "559472095N",
        "name": "Alex Brown",
        "shop_url": "https://google.com/"
    },
    "additional_fields": {
        "text_0": { // text_0 is field name
            "text": "Your telegram username", // field title
            "type": "text", // field type
            "value": "@eva.melstore" // value which user fill out on checkout
        },
         "text_1": {  // text_1 is field name
            "text": "Your website url", // Field title
            "type": "text", // field type
            "value": "https://mel.store/eva" // value which user fill out on checkout
        }
    },
    "exchange_rate": 1, // Exchange rate for this payment if the currency is not USD
    "currency": "USD", // Currency of the payment
    "customer_name": "Eva Choo", // Customer's name
    "customer_phone": "+45454286940", // customer phone
    "customer_email": "eva.choo@mel.store", // Customer's email
    "created_at": "1687278245", // Timestamp when the payment was processed
    "product_id": 15, // ID of your product on mel.store
    "product_title": "Individual service for you!", // Title of the product
    "product_type": "CustomService"
}
product_type may has several values:
  
RecurringMembership - Recurring Membership
CustomService - Custom Service
OneToOneCall - 1:1 Call book on calendar
PdfGuideEbook - Pdf Guide Or EBook

uuid

unique uuid string which identify your transaction

amount

Amount paid by the customer in the transaction currency, will include vat amount if VAT applied to this transaction

total_amount

amount which credited to your balance, most frequently it would be converted to USD using exchange rate

exchange_rate

int or float, it is exchange rate which was applied when total_amount credited to your balance, if it's equal 1 then transaction and wallet where it was credited has the same currency

commission

service or platform fee which was applied to process and credit this sell to your wallet, it always has the same currency as wallet where total_amount was credited to your balance, for example: your was credited $100.00 to your balance then fee would be also in USD

vat

VAT which was applied to transaction if customer selected country where VAT must be applied: for e.g European Union or UK. If customer paid VAT then platform commission would be calculated from all transaction amount. VAT always has the same currency as original transaction currency, if customer was paid in EUR then VAT amount will be in EUR

metadata

arbitrary objects, contains data which you specified while creating a new payment link, please reffer to Restfull API -> Payment Links

additional_fields

optional object with additional fields which you've added to checkout page inside product settings (5. Collected customer information), if your customer was fill out additional fields on form while checkout you will get it

currency

currency of customer transaction, for e.g USD, EUR, AED

customer_name

name of the customer that was filled out on the sales form.

customer_phone

phone number of the customer that was filled out on the sales form.

customer_email

email of the customer that was filled out on the sales form.

created_at

Timestamp when the payment was processed in UTC timezone

product_id

Unique id of your product

product_title

Title of your product

product_type

The type of your product may have the following values:

RecurringMembership - Recurring Subscription
CustomService - Custom Service
OneToOneCall - 1:1 Call book on calendar
PdfGuideEbook - Pdf Guide Or EBook

Webhook delivery mechanism

  • Your server must return a response code of 200:

    Your server must acknowledge receipt of webhook notifications by responding with a HTTP 200 status code. Any other response codes indicate a failure in processing the notification correctly.

  • Retry mechanism for unsuccessful deliveries:

  • If your server doesn't return a 200 status code (maybe due to a temporary issue or server downtime), the webhook service will retry sending the notification every hour to ensure successful delivery.

  • Retries will occur for a duration of 1 day:

    The webhook service will give it another go to send the notification, trying once every hour for a whole day. If at any time during that day your server gives a thumbs up with a 200 status code, the service will stop the retries, happy that the message got through. But if the day ends without a positive response, the service will give up on sending that specific notification.

Sending test event and check webhook setup

By clicking "check status" button you can see if your webhook setup correctly and returns 200 status code, also it would trigger sending a test event to your webhook url

Signing each request

For enhanced security, you can set up a special webhook key that will be attached to the headers of each request as "webhook-key: <your_api_key>". This helps verify that the current request was genuinely sent by mel.store. To generate new key you should click refresh button next to webhook key field.

On your side you can compare key with what what received

Example of checking and handling webhook on your side

Function handleWebhookRequest(request): 
// Extract the webhook-key from request headers
 webhookKeyFromHeaders = request.headers['webhook-key']
 
// Compare the received key with your stored API key
if webhookKeyFromHeaders !== <stored_api_key>:
    // API key mismatch error
    return Response(401, "Unauthorized: Invalid webhook key.")
else:
    // Further process the webhook data
    webhookData = request.body

    // Let's say you want to check the product type and handle it accordingly
    if webhookData.product_type == "RecurringMembership":
        // Handle recurring membership
        processRecurringMembership(webhookData)
    elif webhookData.product_type == "CustomService":
        // Handle custom service
        processCustomService(webhookData)
    // ... Handle other product types similarly ...

    // Return a successful response to acknowledge the receipt of the webhook
    return Response(200, "Webhook processed successfully.")
End Function    

Last updated