Webhooks allow you to perform actions when events are triggered in Servicebot. Actions such as adding a new user in your database when a Servicebot subscription starts, updating a user's status when they have changed their tier, or updating a CRM when a customer has cancelled.
We will go over the available events and the options you have for integrating in this guide, to see more details on each webhook event, check out this guide.

Synchronous vs Asynchronous

Servicebot allows for "synchronous" & "asynchronous" webhooks. Using synchronous webhooks, when a client makes a request which triggers a webhook, the process will wait until the endpoint responds and attach whatever data the client responded with to the payload the client receives.
With asynchronous webhooks, the webhook is called and the process continues without waiting for a response. 

Configuring a webhook endpoint in Servicebot

  1. Go to 'Settings' -> 'Webhook Settings'.
  2. Click '+ Add Endpoint'.
  3. Enter the URL of your application route listening to your endpoint, or a Zapier endpoint.
  4. Select "Synchronous" or "Asynchronous" and 'Add Endpoint'

Create a route in your app

Set up a route to receive webhook calls. For example: POST /servicebot-webhook

The following are events sent by Servicebot:

Pre-Request

  • Event Name- 'pre'
  • Description- This event is called when a customer first requests a service. This stage is good for validation of parameters, logging, and CMDB integration actions such as creating a configuration item.
  • Objects sent- Request, Service Template

Post-Request

  • Event Name- 'post'
  • Description- In this stage, the service instance finished being created. This is a good hook to listen to if you need to give a user access to your app, or alert third party integrations such as sending a Slack message.
  • Objects sent- Request, Service Template, Service Instance

Pre-Property-Change

  • Event Name- 'pre_property_change'
  • Description- The stage before a property change occurs, in this step you can see the instance and the updates to the properties.
  • Objects sent- Service Instance, Properties Changed

Post-Property-Change

  • Event Name- 'post_property_change'
  • Description- Called after a property change occurs, the instance will reflect any possible price changes which may have occurred with properties that affect price. 
  • Objects sent- Service Instance

Pre-Payment-Structure-Change

  • Event Name- 'pre_payment_structure_change'
  • Description- The stage before a price change occurs, in this step you can see the instance and the updates to the payment object. This is good for detecting when a customer changes their "tier" for example changing to a premium subscription from a basic. 
  • Objects sent- Service Instance, Payment Structure Templates

Post-Payment-Structure-Change

  • Event Name- 'post_payment_structure_change'
  • Description- Called after a price change occurs, the instance will reflect any possible price changes which may have occurred. 
  • Objects sent- Service Instance

Pre-Cancellation

  • Event Name- 'pre_decom'
  • Description- This event is called when a customer first requests a cancellation of a service.
  • Objects sent- Service Instance

Post-Cancellation

  • Event Name- 'post_decom'
  • Description- Called after a cancellation has been completed.
  • Objects sent- Service Instance

Pre-Reactivate

  • Event Name- 'pre_reactivate'
  • Description- This event is called when a customer first reactivates a cancelled service.
  • Objects sent- Service Instance

Pre-Reactivate

  • Event Name- 'post_reactivate'
  • Description- This event is called after an instance is reactivated, changing cancelled state into active state.
  • Objects sent- Service Instance

Example Webhook Listeners:

app.post("/servicebot-webhook", async function (req, res) {      
  let User = require('./models/user');          
  let eventData = req.body.event_data;          
  let email, user;          
  console.log(req.body.event_name);          
  try {              
    if (eventData.instance && eventData.instance.references) {
      email = eventData.instance.references.users[0].email;
      user = await User.findOne({'local.email': email});
    }              
  switch (req.body.event_name) {                  
    case "post_decommission":                      
      if(user) {                          
        user.status = "suspended";                          
        await user.save();                      
      }                      
      res.json({"message": "user suspended"});            
      break;                  
    case "post_provision":                      
      let instance = eventData.instance;                      
      let userId = eventData.instance.user_id;  
      let tierId = instance.references.payment_structure_templates[0].tier_id
      let newUser = new User();                      
      newUser.status = "active";                  
      newUser.accountType = "subscriber";                  
      newUser.local.email = instance.references.users[0].email      
      newUser.tierId = tierId;                
      newUser.servicebotUid = userId;                      
      // create the new user                      
      await newUser.save();                      
      res.json({"message": "new instance"});                    
      break;                  
    case "post_seat_created":                      
      let seat = eventData.seat;                      
      console.log("new seat!", seat);                      
      user = await User.findOne({'servicebotUid': seat.user_id});
      if(user){                          
        user.status = "active";                      
        user.accountType = "seat";                        
        user.tierId = null;                          
        await user.save();                      
      }else {
        let newUser = new User();              
        newUser.accountType = "seat";
        newUser.status = "active";
        newUser.local.email = seat.references.users[0].email;
        newUser.servicebotUid = seat.user_id;
        await newUser.save();                      
      }                      
      res.json({"message": "seat created"});
      break;                  
    case "post_seat_deleted":                      
      let deletedSeat = eventData.seat;                      
      user = await User.findOne({'servicebotUid': deletedSeat.user_id});                      
      user.status = "suspended";                      
      await user.save();                      
      res.json({"message": "seat deleted"});                
      break;                  
     case "post_reactivate":                      
      user.status = "active";                      
      await user.save();                      
      res.json({"message": "user reactivated"});    
      break;                  
    default:                      
      res.json({"test": "test"});                      
      break;              
    }          
  }catch(e){              
    console.error(e);              
    res.status(500).json({error: e});          
  }      
}); 

Did this answer your question?