Create a Webhook integration
Learn to create an integration and listen to Aircall events

Select a language:

    This tutorial will guide you through the creation of a Webhook integration on Aircall.

    Getting started

    Before starting to code, you will need to have:

    1. One server, to run the backend application we are going to create. You can use Heroku or any hosted solution you prefer

    2. An Aircall account - sign up here

    Step by step

    Now we are all setup, here are the steps we are going to follow:

    1. Create an Aircall Webhook integration
    2. Create API endpoints
    3. Listen to specific Aircall events

    1 - Create a Webhook integration

    You can create and manage Webhooks from your Dashboard. For this tutorial, we will only subscribe to the call.created event but you can activate the ones that suit your needs.

    1. Go to the Integration page in your dashboard
    2. Click on the Webhook integration and on the Install button
    3. Toggle the switches of the events you want to receive
    4. [Optional] In the integration name (custom) field, set a name to easily identify your webhook in the integrations list
    5. In the url field, set the value to the url of your future server followed by /aircall/calls (i.e. https://my-webhook-integration.herokuapp.com/aircall/calls)
    6. Click on the Save button to confirm the creation of the webhook

    Webhook creation

    There is a limit of 10 webhooks you can create per account

    2 - Create new endpoints

    At this point, you will need to have a running server to move forward (for Heroku, check the Getting starting documentation).

    • Let's start by adding an index route responding to the GET method - if you don't already have one:
    const app = require('express')();
    const bodyParser = require('body-parser');
    
    app.use(bodyParser.json());
    
    app.get('/', (req, res) => {
      res.json({'message': 'Server is running'});
    });
    
    # config/routes.rb
    Rails.application.routes.draw do
      # You can have the root of your site routed with "root"
      root 'welcome#index'
    end
    
    # controllers/welcome_controller.rb
    class WelcomeController < ApplicationController
      # GET /
      def index
        render :ok, json: { message: 'Server is running' }
      end
    end
    
    package main
    
    import (
        "log"
        "net/http"
        "github.com/gin-gonic/gin"
    )
    
    func main() {
        port := os.Getenv("PORT")
    
        if port == "" {
            log.Fatal("$PORT must be set")
        }
    
        router := gin.Default()
    
        router.GET("/", func(c *gin.Context) {
            c.JSON(http.StatusOK, gin.H{"message": "Server is running"})
        })
    
        router.Run(":" + port)
    }
    
    • Then we need to add a new route POST /aircall/calls which will handle all incoming webhooks:
    // POST /aircall/calls
    app.post('/aircall/calls', (req, res) => {
      res.sendStatus(200);
    });
    
    # config/routes.rb
    Rails.application.routes.draw do
      # You can have the root of your site routed with "root"
      root 'welcome#index'
    
      # Post route that invoke 'calls' method from WebhookController
      post 'aircall/calls' => 'webhook#calls'
    end
    
    
    # controllers/webhook_controller.rb
    class WebhookController < ApplicationController
      # POST /aircall/calls
      def calls
        head :ok
      end
    end
    
        router.POST("/aircall/calls", func(c *gin.Context) {
          c.JSON(http.StatusOK, gin.H{})
        })
    

    Your server should always return a "200" HTTP status code. After 10 failed attempts, Aircall will automatically disable your webhook.

    3 - Listen for specific events

    Once our routes are created, we want them to handle specific events. Aircall will send the event type in the body of the request, set as the event attribute.

    Here is an example of the call.created payload:

    {
      "resource": "call",
      "event": "call.created",
      "timestamp": 1512588391,
      "token": "123ASECRETTOKEN456",
      "data": {
        "id": 123,
        ...
        "direction": "inbound",
        "raw_digits": "+19171234567"
        ...
      }
    }
    
    • We will update our webhook handler to execute business logic when we receive call.created:
    app.post('/aircall/calls', (req, res) => {
      if (req.body.event === 'call.created') {
        // Run some logic
      }
      else {
        console.warn('Even type non-handled:', request.body.event);
      }
    
      res.sendStatus(200);
    });
    
    def calls
      if params[:event] == 'call.created'
        # Run some logic
      else
        logger.warn "Event type non-handled: #{params[:event]}"
      end
    
      head :ok
    end
    
    type Call struct {
        Event string   `json:"event" binding:"required"`
    }
    
    router.POST("/aircall/calls", func(c *gin.Context) {
        var body Call
        c.BindJSON(&body)
    
        if body.Event == "call.created" {
            // Run some logic
        } else {
            log.Println("Event type non-handled: " + body.Event)
        }
    
        c.JSON(http.StatusOK, gin.H{})
    })
    

    Now, it's time for you to add your business logic! If you need more information about the objects sent with the events, follow this link.

    We wrote other tutorials to help you out
    building awesome integrations

    Discover them now!