Webhooks

In case you want to perform your own actions when events happen in Moonbase, you can configure webhooks to forward events to your own APIs. Webhooks can be set up to trigger on a number of different events:

  • Payment events
    • OrderPaid
    • OrderCompleted
    • OrderPayoutScheduled
    • OrderRefunded
  • Licensing events
    • LicenseActivated
    • TrialActivated

To get started with webhooks, head over to your Moonbase account settings, and set up your first webhook:

Once created, it's immediately active and you will have access to the secret key used to compute the signature as described in Security.

Do you have a specific scenario you need webhooks for that is not covered by the current events and content?
Reach out to us through the support channel, or at developers@moonbase.sh.

Security

To ensure that the webhook requests are in fact originating from Moonbase and not some malicious actor, we apply a HMAC-SHA256 algorithm on the body of the request and include this signature in a X-Signature header on the request.

Example signature verification code

    using var algorithm = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
    var json = await request.Content.ReadAsStringAsync();
    var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(json));
    var signature = Convert.ToBase64String(hash).ToUpperInvariant();
    var sentSignature = request.Headers.GetValues("X-Signature").Single();
    Assert.Equal(sentSignature, signature);

Should you ever need to change the secret key, you can do so by editing the webhook.

JSON structure

All webhook requests being sent by Moonbase will have a fixed structure with some basic details about the event that occurred. Additionally, relevant resources are also attached, so that you don't have to query the Moonbase API to fetch more details. The shape of these resources differ between events, and are described on this page.

  • Name
    id
    Type
    string
    Description

    Identifier of this unique webhook request.

  • Name
    endpoint
    Type
    string
    Description

    The endpoint the request is being sent to.

  • Name
    eventType
    Type
    enum
    Description

    The event being communicated, will one of the events listed in this article.

  • Name
    timestamp
    Type
    string
    Description

    Timestamp of the time at which the event occurred.

  • Name
    resource
    Type
    object
    Description

    The resource that the event relates to:

    • Name
      type
      Type
      enum
      Description

      One of: Order, License, Trial

    • Name
      data
      Type
      object
      Description

      The actual contents of the entity. See below for more details about how this is structured.

  • Name
    customer
    Type
    object
    Nullability
    nullable
    Description

    Details about the customer associated with the event. In case the customer is unknown, it will be null.

    • Name
      id
      Type
      string
      Description

      Unique identifier of the customer.

    • Name
      name
      Type
      string
      Description

      Name of the customer.

    • Name
      email
      Type
      string
      Description

      Email address of the customer.

    • Name
      isDeleted
      Type
      boolean
      Description

      Flag showing if the customer account was deleted

Webhook request

{
    "id": "a885619a-cb5e-41a6-a07b-1be4e520cccb",
    "endpoint": "https://api.my-domain.example/webhook",
    "eventType": "OrderCompleted",
    "timestamp": "2024-11-11T11:11:11.0000000Z",
    "resource": {
        "type": "Order",
        "data": {...}
    },
    "customer": {
        "id": "92c0f540-9044-4b00-af4c-fe29f5da355e",
        "name": "Example customer name",
        "email": "user@example.com",
        "isDeleted": false
    }
}

Payment Events

When customers make purchases through Moonbase, they make them on what we call an "Order". This is why the events related to payments are all prefixed with Order, and the typical lifecycle of an order goes like this:

  1. The customer pays for an order, a OrderPaid event is sent (not applicable for free purchases)
  2. Moonbase fulfills the order, issuing licenses and sending receipts, completing the order, a OrderCompleted event is sent
  3. Moonbase then calculates all affiliate revenue splits and schedules payout for the order, a OrderPayoutScheduled event is sent

Lastly, if you chose to refund the order, Moonbase will emit a OrderRefunded event to any webhook listening.

All events concering orders will have the same shape of the order:

  • Name
    id
    Type
    string
    Description

    Unique identifier of the order.

  • Name
    status
    Type
    enum(Paid|Completed)
    Description

    The current status of the order, Paid if not yet completed, Completed if paid and fulfilled.

  • Name
    currency
    Type
    string
    Description

    The currency used for this purchase.

  • Name
    completedAt
    Type
    DateTime
    Optionality
    optional
    Description

    The timestamp for when the order was completed.

  • Name
    isRefunded
    Type
    boolean
    Description

    Flag indicating if this purchase has been refunded.

  • Name
    isDisputed
    Type
    boolean
    Description

    Flag indicating if this purchase has been disputed.

  • Name
    total
    Type
    object
    Description

    Calculated total for all items part of the order, contains:

    • original: The original amount before discounts
    • discount: The total amount of discounts added
    • subtotal: The total amount after discounts have been removed
    • taxes: Total taxes to pay, may be inclusive or exclusive of the subtotal depending on configuration, currency and region.
    • due: How much is being paid in total by the customer
  • Name
    payout
    Type
    object
    Optionality
    optional
    Description

    Payout details for this order, only present if an amount is to be paid. Note that this may get updated as affiliate revenue splits are calculated later in the pipeline.

    • subtotal: The original amount paid by the customer
    • taxes: The total amount of taxes collected and remitted
    • platformFees: The total amount of fees going to Moonbase
    • due: How much is being paid out to you
  • Name
    billingDetails
    Type
    object
    Description

    Billing details about the customer who made the purchase:

    • Name
      name
      Type
      string
      Description

      Full name of the customer.

    • Name
      businessName
      Type
      string
      Nullability
      nullable
      Description

      In case the purchase was a business purchase, this field will have the name.

    • Name
      taxId
      Type
      string
      Nullability
      nullable
      Description

      In case the purchase was a business purchase, this field will have the tax id if given.

    • Name
      email
      Type
      string
      Description

      Email address of the customer.

    • Name
      phone
      Type
      string
      Nullability
      nullable
      Description

      Phone number of the customer. Note that collecting phone numbers is an optional feature in Moonbase and not activated by default.

    • Name
      address
      Type
      object
      Description

      Billing address for the customer. Contains the following properties:

      • Name
        countryCode
        Type
        string
        Description

        ISO 3166-1 alpha-2 two-letter country code.

      • Name
        streetAddress1
        Type
        string
        Description

        First line of the regular street address.

      • Name
        streetAddress2
        Type
        string
        Optionality
        optional
        Description

        Second line of the regular street address.

      • Name
        postCode
        Type
        string
        Description

        Postal code of the address.

      • Name
        locality
        Type
        string
        Description

        Locality of the address, only required if no region is given.
        Also known as City.

      • Name
        region
        Type
        string
        Description

        Region of the address, only required if no locality is given.
        Also known as State.

  • Name
    items
    Type
    array
    Description

    Collection of items part of the order. Note that this can be either products or bundles, and they are discriminated using the type property. Some properties are present on both types, others are shared:

      Product line item

    • Name
      type
      Type
      'Product'
      Description

      Item type discriminator.

    • Name
      productId
      Type
      string
      Description

      The unique ID of the product.

      Bundle line item

    • Name
      type
      Type
      'Bundle'
      Description

      Item type discriminator.

    • Name
      bundleId
      Type
      string
      Description

      The unique ID of the bundle.

      Shared

    • Name
      quantity
      Type
      number
      Description

      The quantity of this item.

    • Name
      price
      Type
      object
      Description

      The original price of the product or bundle.

    • Name
      total
      Type
      object
      Description

      The calculated total for this line item.

    • Name
      variation
      Type
      object
      Description

      Details about the selected pricing variation for this item.

    • Name
      fulfillment
      Type
      object
      Optionality
      optional
      Description

      Details about the license fulfillment for this purchase.

Order data example

{
    "id": "dc0b53f9-4e43-4179-8554-00f2a8228a25",
    "status": "Completed",
    "currency": "EUR",
    "completedAt": "2024-11-11T11:11:11.0000000Z",
    "isRefunded": false,
    "isDisputed": false,
    "total": {
        "original": {
            "currency": "EUR",
            "amount": 10
        },
        "discount": {
            "currency": "EUR",
            "amount": 5
        },
        "subtotal": {
            "currency": "EUR",
            "amount": 5
        },
        "taxes": {
            "currency": "EUR",
            "amount": 5
        },
        "due": {
            "currency": "EUR",
            "amount": 5
        }
    },
    "billingDetails": {
        "name": "Example User",
        "businessName": null,
        "taxId": null,
        "email": "user@example.com",
        "phone": null,
        "address": {
            "countryCode": "NO",
            "streetAddress1": "Utsikten 6",
            "streetAddress2": null,
            "locality": "Skien",
            "region": null,
            "postCode": "3718"
        }
    },
    "couponsApplied": [
        {
            "id": "43396b94-53b4-4901-8e9e-ab1d6ee7d3b5",
            "code": "MY-UNIQUE-CODE",
            "name": "Half off coupons",
            "description": "Thanks for being our customer!",
            "discount": {
                "type": "PercentageOffDiscount",
                "percentage": 0.5
            },
            "applicableProductIds": [],
            "applicableBundleIds": []
        }
    ],
    "items": [
        {
            "type": "Product",
            "productId": "example-product",
            "quantity": 1,
            "price": {
                "EUR": 10
            },
            "total": {
                "original": {
                    "currency": "EUR",
                    "amount": 10
                },
                "discount": {
                    "currency": "EUR",
                    "amount": 5
                },
                "subtotal": {
                    "currency": "EUR",
                    "amount": 5
                },
                "due": {
                    "currency": "EUR",
                    "amount": 5
                }
            },
            "variation": {
                "id": "v802c5",
                "name": "Default",
                "entitlement": {
                    "type": "PerpetualLicense"
                },
                "recurrence": {
                    "type": "OneOff"
                },
                "price": {
                    "EUR": 10
                }
            },
            "fulfillment": {
                "type": "License",
                "licenseIds": [
                    "d564a47a-d7f3-48ea-8698-57ad7512b11d"
                ]
            }
        }
    ]
}

Licensing events

We currently expose the following licensing related events:

  • LicenseActivated: Happens the first time a license is activated on any device
  • TrialActivated: Happens the first time a trial is started on any device

These events have different resource shapes:

License events

  • Name
    id
    Type
    string
    Description

    Unique identifier of license.

  • Name
    status
    Type
    enum(Active|Revoked)
    Description

    The current status of the license.

  • Name
    productId
    Type
    string
    Description

    The product ID that the license is for.

License data example

{
    "id": "5ec722c7-f7d9-441d-83af-69ea634e429b",
    "status": "Active",
    "productId": "example-product"
}

Trial events

  • Name
    id
    Type
    string
    Description

    Unique identifier of trial.

  • Name
    status
    Type
    enum(Active|Expired)
    Description

    The current status of the trial.

  • Name
    productId
    Type
    string
    Description

    The product ID being trialled.

  • Name
    lastValidatedAt
    Type
    DateTime
    Description

    The time of last validation.

  • Name
    expiresAt
    Type
    DateTime
    Description

    The time at which this trial expires.

Trial data example

{
    "id": "7cda66c7d03bd35bac892b97436c33b8",
    "status": "Active",
    "productId": "example-product",
    "lastValidatedAt": "2024-11-11T11:11:11.0000000Z",
    "expiresAt": "2025-11-11T11:11:11.0000000Z"
}

Was this page helpful?