Webhooks

Get notifications through our Webhooks API resource.

Our Platform API's Webhooks resource is a group of endpoints for receiving notifications of events so you can automate processes and updates to your system. Subscribe to a wide range of events and update or delete each event at any time.

This page gives information about Maast webhooks and instructions for implementing and managing webhooks using the API and the Maast Manager portal. For details on using the portal as the primary tool to add and manage webhooks, see Webhooks in Maast Manager. For field definitions and details on all supported requests, see Webhooks in API Reference.


Features

The Webhooks API resource has the following benefits:

  • Versatility - Get notifications involving payments, invoicing, recurring billing, Account Updater, and Customer Vault.
  • Persistence - The API retries notifications for 48 hours, and it notifies you by email when all retries have been exhausted.
  • Savings - Notifications of issues helps you solve them quickly and get paid.
  • Security - Use a webhook secret to validate that requests are initiated by Maast, a PCI DSS certified Level 1 compliant service provider.

The resource supports several different requests. We offer API reference for all supported requests and detailed implementation guides for some.

We have guides for the following API functions:

See Webhooks in API Reference for the following additional functions supported by the API:


Implement

Perform the following tasks to integrate a webhook:

1. Configure your server

Set up a webhook endpoint (notification_url) on your server to listen to POST requests from Maast. Please note the following:

  • The endpoint must use HTTPS and should serve HTTP POST requests.
  • Maast will post requests when one of your subscribed events is triggered.
  • The endpoint URL should respond with an HTTP 2xx response.
  • Any other HTTP response message is considered a failure, and Maast will retry posting the same request until a successful response is received or the request expires, whichever comes first.
  • Refer to Notifications Schema in Webhook Conventions for the models of all available webhook events.

2. Configure the webhook

You can configure a webhook through either the Maast Manager portal or the API:

  • Maast Manager - To create and edit a webhook in the Maast Manager portal, follow the instructions in the Webhooks in Maast Manager guide. Save the generated secret.
  • API - To create and edit a webhook using API, do the following:
    • Perform the tasks in the Add a Webhook guide. Save the returned webhook ID (webhook_id), the secret, and the basic authorization information if applicable (user_name and user_password).
    • Perform the tasks in the Add an Event guide.

3. Validate your URL

To validate that your webhook URL can receive Maast notifications, perform these tasks:

  1. Log in to the Maast Manager portal and select 'Administration' from the left-hand menu.
  2. Under 'Integration,' select 'Webhook Configuration.'
  3. Locate your webhook in the table. In its 'Action' column, select 'Validate.' When you do so, Maast posts a validate_url event to your site and checks for a HTTP 2xx response.

Note the following:

  • If your URL is not validated, a message will appear containing the specific HTTP error to address.
  • If you change the SSL certificate on your URL, you should validate the URL again. Maast will then add your certificate authority to our internal repository.

4. Secure your webhook

Maast signs each webhook request with an x-qualpay-webhook-signature header, which is a Base 64 encoded HMAC-256 digest generated from the request payload using the webhook's secret.

Perform the following steps to validate that a request is initiated by Maast, which ensures the security of the webhook:

  • Get the Maast webhook signature from the HTTP request header x-qualpay-webhook-request.
  • Separate the signature into individual signatures using commas (,). If there is only one
    signature, there will be no commas in the header.
  • Compute the HMAC with sha-256 function using the request payload and your secret.
  • Base64 encode the HMAC.
  • Compare the computed value against the header signature(s). A match validates that the request is
    signed by Maast.

🚧

Multiple Secrets

If you rotate the webhook secret through Maast Manager, you can opt to keep the old secret valid for a specified period. This allows sufficient time to update your systems with the new secret.

During this period, a webhook has two simultaneous secrets, and the header contains a comma-separated list of the Base 64 encoded Hash until the old secret expires.

Sample Validation Functions

If you implement your own validation function, you can test using the following sample data:

secret: 793a08534c4511e780520a3416b2e023

x-qualpay-webhook-signature: GI9mk44dQR4mHOJjc4pOmWyZCaNwqgDqXJWsHDXgTO8=

request payload: {
  "webhook_id": 139,
  "db_timestamp": "20170620080004",
  "event": "validate_url",
  "is_test": true,
  "data":{}
}

Below is sample implementation to validate the request in PHP:

// $qpheader is the contents of request header 'x-qualpay-webhook-signature'
// $postdata is the raw json payload of the request
// $secret is the webhook secret
function validate($secret, $qpheader, $postdata) {
  $isvalid = false;
  $signaturearr = [];
  if( !is_null($qpheader) ){
    if( preg_match("/,/", $qpheader) ) {
      $signaturearr = explode(",", $qpheader);
    } else {
      $signaturearr = [$qpheader];
    }
    foreach($signaturearr as &$qpsignature) {
      $computed = base64_encode(hash_hmac('sha256', $postdata, $secret, true));
      if( hash_equals($computed, $qpsignature) ) {
        $isvalid = true;
        break;
      }
    }
  }
  return $isvalid;
}

Below is sample implementation to validate the request in Java:

/**
 * @param secret    is the webhook secret
 * @param header    is the contents of request header 'x-qualpay-webhook-signature'
 * @param postData  is the raw json payload of the request
 * @return
 */
public boolean validate(String secret, String header, String postData) {
  boolean isValid = false;
  try {
    if( secret != null && !"".equals(secret.trim())  && header != null || !"".equals(header.trim() ) ) {
      String[] signatureArr = header.split(",");
      for(String qpSignature : signatureArr) {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(),"HmacSHA256");
        mac.init(secretKey);
        byte[] hmac = mac.doFinal(postData.getBytes("UTF8"));
        String computed = Base64.encodeBase64String(hmac);
        if( MessageDigest.isEqual(computed.getBytes(), qpSignature.getBytes()) ) {
          isValid = true;
          break;
        }
      }
    }
  } catch(NoSuchAlgorithmException ex) {
    throw new RuntimeException("HmachSHA256 function not available", ex);
  } catch(InvalidKeyException ex) {
    throw new RuntimeException("secret is invalid", ex);
  } catch (Exception ex) {
    throw new RuntimeException(ex);
  }
  return isValid;
}

Check the Webhook Status

You can review the status of webhook requests through either the Maast Manager portal or the API:

  • Maast Manager - Follow the steps in Webhooks in Maast Manager to view and change the current status of webhooks requests.
  • API - Send a Get Webhook request with the webhook_id to receive information about your webhook. Find the webhook's current status in the status field of the response.

Find a table of possible webhook statuses here.


Retries

Please note the following about Maast's retry workflow:

  • Maast queues every POST request and attempts to post it to the notification URL.
  • If your webhook endpoint is unavailable, Maast retries posting the request every hour until the request expires.
  • All requests expire in 48 hours.
  • If Maast cannot post to the URL within 48 hours, the webhook is suspended. Maast sends a notification of this suspension if the webhook has an email address.
  • When a webhook is suspended, Maast holds all POST requests already queued for the webhook and adds no new requests for the webhook.
  • You can reactivate the suspended webhook in Maast Manager.
  • When reactivated, Maast attempts to post all unexpired requests in the queue.

Test and Go Live

See our Test and Go Live guide to test your API integration and to start transacting with an active production account.

🚧

Validate in Production

When moving to production, you must redo the validation process for your webhooks configuration.