SLINKOV.Design
DMITRIY SLINKOV

Customizing Bitrix24 by the webhook

Bitrix24 is a powerful system containing a lot of tools like CRM, tasks and projects management, company disk and calendar, business processes, website builder, marketing automation, etc. But what if these functions are not enough? Webhooks can give your Bitrix24 literally unlimited power. Let's see how easily you can do such an enhancement!

What the heck is API?!

You probably heard from Bitrix24 consultants this phrase: "Bitrix doesn't have such function. But we will make a webhook!"

Webhook became a panacea and the devil in the same bottle. But, as I told you many times in my videos, this devil is not awful at all.
With the help of webhooks you can do literally this:
  1. Add, modify, delete, import, copy or duplicate leads, tasks, orders, companies, contacts, invoices, custom list items, statuses, stages.
  2. Add, modify, delete custom fields, files, calendar events.
  3. Create and modify workflows and business processes.
YouTube channel: No-code & CRM guru
Dmitriy Slinkov: Bitrix24 – Customer revenue on the fly
Simple example of the task fulfilled by the webhook
One day one of my customers asked me if I can transfer products from order to tasks. It took just a couple of hours. Webhook simply copies all the product lines into the tasks. It makes sense when you sell services that must become tasks once the offer is accepted.
I'll describe how to do that in a separate video. In order not to miss it, please, subscribe to my YouTube channel "No-code & CRM guru".
Let me state this right from the beginning:
1️⃣ Webhooks are just scripts running on any hosting you trust and control
2️⃣ The hosting is a place where you normally keep your website (unless you use a website builder, one of which does exist inside the Bitrix24!)
3️⃣ Webhook is nothing more than just a webpage which your Bitrix24 calls via… the URL! The only difference with a usual webpage is: it goes to the deeper programming language right from the beginning of your page / your script
4️⃣ Everything that I tell you here about a webhook is pretty much applicable to ANY serious IT system!

When Steve Jobs made an iPhone his main discovery was not a glass touchable screen. He started the era of applications. Today we have apps almost for everything. But! When you have that huge universe of applications, you miss the opportunity to integrate them.

Imagine: your Angry Birds app sends the information about your achievements into your bank. Then, your bank app estimates your gaming productivity and gives you the best loan conditions. Because you are an artful person. Or… because you are so stable in this world that you have enough time to play mobile games…

Funny or not, today we face another global stage of software development — the API era!

There are a lot of closed CRM systems. They are proud to say "we are simple". And such a gimmick does its work: people buy dead simple systems. But! As soon as you got a tool, you need to improve it. Think about it when next time you are faced to choose CRM for your business.

When the system offers API, it is a sign that you always can make it better, adapt to your business needs, and, finally, integrate such an application into your ecosystem. It will work with your other applications!

Using API, you can integrate CRM with your accounting system, with your eCommerce system, even with… the systems of your business partners!

Acronyms you should know

So, once you decided to enter that funny API era, chances are you'll meet these acronyms:
However, the most important thing to know now is JavaScript Object Notation file. (JSON). Well, JSON is a generic data format with a minimal number of value types: strings, numbers, booleans, lists, objects, and null. Although the notation is a subset of JavaScript, these types are represented in all common programming languages, making JSON a good candidate to transmit data across language gaps.

Here is how that JSON might look like:
JavaScript Object Notation file (JSON)
If you read it up, you'll quickly find its readability. Look – this is just an Internet order!

Okay, I do have good news for you: you don't need to write such a file yourself!

The task is much-much easier!

Let's stop theorizing and start practicing?!

Dive into Bitrix24 and JSON

Let me show you my presentation slide by slide where I describe how the webhook and Bitrix24 itself and JSON are working together like a Formula-1 team.
Here you may see all the participants: Bitrix24, Internet, and a webhook.
B24 has a special Inbound Webhook form / card. You may find it by the following path: Developer resources \ Other \ Inbound webhook.
Copy that URL and paste it into your webhook's script. Right how it is shown here:
In the webhook script, you'll enter that URL manually. This URL will be used to send your JSON files. This number after the 'rest' is the User ID. It means that your webhook will work only on behalf of that user. I recommend using the ID of your super-admin. In the field "permissions" you'll choose CRM, Task, or other modules you agree to give permission to.

So, now the picture of communication between your webhook and Bitrix24 is:
Imagine for a second that our webhook needs to know the average temperature in Paris and your Bitrix24 does have such information.
Your webhook will send a JSON file containing [{ "city": "Paris", "units": "C"}] to Bitrix24 using THE secret URL we've described just above. And will "immediately" get the response like that one: [{ "low": "16", "high": "23"}]

Cool?
We reviewed the situation when the initiative is on the webhook's side. You wanted to know the temperature – you ask about it at any time you choose. But what about the situation when you want to get an alert when the temperature is changed? Or went higher the "high". For these situations, Bitrix24 has another form/card right near the Inbound webhook card.
You may find it by the following path: Developer resources \ Other \ Outbound webhook.
Here we are welcome to make manual settings on a Bitrix24's side. Tell to B24 the URL of your webhook.
Next important thing here the field "Events". For example, in one of my videos, I told you about Customer Revenue calculation. The webhook doing that is pretty convenient to call via the event "Invoice Status Updated".

This is not the only place where you can point to the event which will call your webhook.

There are also:
  1. Automation rules in CRM
  2. Automation rules in Tasks and Projects
  3. Workflow activity
In all these places you can point NOT only your webhook, but also some parameters!

Example: you want to check whether the Email of the lead returned to your website is the "work" Email or just some Gmail-like one. For that check you prepared a webhook and placed it's URL into the "Automation rules" section of your pipeline stage called "Returned to website". You may add to that URL lead's Email as a parameter. Like here:
You may see that 'email' and 'responsible' are variables which you may easily fetch inside your script and use further.

To finalize the visual picture, here is the last slide:
Event causes the call of your webhook.
Webhook sends a query-JSON and receives the reply-JSON.
This is it ;)

What next?

What next? Choose your preferred programming language. I've chosen PHP. To write a script for my webhook, I took the Visual Studio app. [BTW, links to all apps mentioned here, you may find in a description of this video (just scroll down a bit!).]

In order not to write JSON myself, I've found a good library. Now I can use very simple add, update, delete semantic to operate data in my Bitrix24! My script and links to the library you'll find in the description!

So, the script is ready, right?! Now we should host it somewhere. Obviously, if you write your code on PHP, you'll need a hoster who can provide you a server with a PHP interpreter, right?!

The only caution from my experience: don't use free hosting. Free means free – you never know how long you have to wait till the webhook will really act.

What else? Find your favorite FTP client and use it to:

  1. Transfer your webhooks to the "server"
  2. Download log files from the "server".

What webhooks can and can't do

Look at my YouTube channel. It is going to be the place of many webhook-driven Bitrix24 customizations.
Webhooks can help you integrate Bitrix24 with Prestashop, SAP SuccessFactors, Shopify, Microsoft Dynamics AX... the list is limitless!

Or look at this:
  • Lead processing automation with warming up 'cold' leads via complex workflow.
  • Integration of Bitrix24 with Google Sheets and Google Data Studio.
  • Creating various dashboards for multi-currency sales data.
  • Transforming products into tasks.
  • Automatical project/group creation when the Deal is moved to a certain status.
  • Closing projects with automatically generated procedures, notions to customer's clients, and invoices.
  • Automation of leads onboarding (data processing and catching up the cases when the lead visits the website)
  • Random and periodical invoicing system: transforming tasks into deals and invoices.

This is a list of what I personally did for my customers just in one month based ONLY on webhooks. The most interesting thing is: 2 months before that article, I had absolutely no experience in PHP, hosting, FTP, and whatnot. One developer made our first webhook then… disappeared. And, in order to fulfill my obligations to customers, I needed to start developing all these myself. What do all these mean? You can be just in the same level of coolness that I am))

What webhooks can NOT do:
  1. Make interface changes (including new interfaces like forms, custom notifications, and so on)
  2. Do anything that is not allowed by API (for instance, you can not have access to the Deal's comments, emails, email signatures…)
  3. Make you neither coffee nor… tea!

Lightning recap

Finally, here are only 6 obstacles you need to overcome to be able to run your webhook:

  1. Find hosting
  2. Decide what events will call your webhook
  3. Find the library (for PHP, I did it for you)
  4. Make your script
  5. Use FTP client.
[period]

Useful adds


<?php

    ini_set("log_errors", 1);
    ini_set("error_log", "./php-error.log");

    writeToLog($_REQUEST, 'incoming'); //comment it when everything will be debugged
    // 
    // This webhook should be called by Bitrix24 event '
    // Go to Your portal \ Developer resources \ Other \ Outbound webhook
    // or like it shown on the following screenshot: https://cloud.mail.ru/public/EmPS/BNuEV3s3p
    // 
    //=== CONSTANTS zone
    //
    define("UFRAS", "UF_CRM_XXXXXXXXX"); // The system name of custome field

    //=== VALIDATION & INITIALIZATION zone
    //Validates Webhook params and fill variables by Webhook params
    
    require __DIR__ . '/vendor/autoload.php';
    
    use \App\Bitrix24\Bitrix24API; // The library https://github.com/andrey-tech/bitrix24-api-php
    
    $webhookURL = 'https://[yourURLfromBitrix24]/';
    
    $bx24 = new Bitrix24API($webhookURL);
    
    $InvoiceID = $_REQUEST['data']['FIELDS']['ID'];
    
    //=== WORKING zone
    
    $InvoiceFields = $bx24->getInvoice($InvoiceID); //Get Invoice fields. 
    
    //If the Invoicee not just paid, then exit from the Webhook
    if ($InvoiceFields['PAYED'] != 'Y') {
        file_put_contents(getcwd() . '/hook.log', "\nInvvoice " . $InvoiceFields['ID'] . " is not paid \n", FILE_APPEND);
        exit;
    }
    
    if (!$Company) exit; //If no Company in Invoicee, exit.
    
    $Company = $InvoiceFields['UF_COMPANY_ID'];
    if (!$Company) exit; //If no Contact in Invoicee, exit.
    
    $CompanyFields = $bx24->getCompany($Company);
    
    //Which year is today?
    $CurrentYear = date("Y");
    $HappyThisYearString = $CurrentYear . '-01-01';
    $HappyThisYearTime = strtotime($HappyThisYearString);
    
    //=== WORKING ZONE
    
    //Summarize only this company's Invoice Amounts
    //First, let's get filtered invoices into an array
    $getInvoiceListGeneratorObject = $bx24->getInvoiceList(['ID' => 'ASC'],
    ['UF_COMPANY_ID' => $Company, 'PAYED' => 'Y'],
    ['ID', 'PRICE', 'DATE_PAYED', 'UF_DEAL_ID'],);
    //Invoice amounts into Array
    $InvoiceArray = array();
    foreach ($getInvoiceListGeneratorObject as $value) {
        $InvoiceArray = array_merge($InvoiceArray, $value);
    }
    
    //Summarize Invoice Amounts
    $m = count($InvoiceArray);
    if ($m == 0) {
        file_put_contents(getcwd() . '/hook.log', "\$no payments from this customer at all\n", FILE_APPEND);
        exit(json_encode(array('error' => 'no payments from this customer at all' )));
    }
    $RevenueCurrentYear = 0;
    for ($i = 0; $i < $m; $i++) {
        $t = strtotime($InvoiceArray[$i]['DATE_PAYED']);
        // file_put_contents(getcwd() . '/hook.log', "\n\$t = " . $t, FILE_APPEND);
        if ($t >= $HappyThisYearTime) {
            $RevenueCurrentYear += $InvoiceArray[$i]['PRICE'];
        }
    }
    if ($RevenueCurrentYear == 0) {
        file_put_contents(getcwd() . '/hook.log', "\n\$no payments from this customer this year\n", FILE_APPEND);
        exit(json_encode(array('error' => 'no payments from this customer this year' )));
    }
    
    $CompanyFields = $bx24->getCompany($Company);
    
    $bx24->updateCompany($Company, [UFRAS => $RevenueCurrentYear], ["REGISTER_SONET_EVENT" => "Y"]);
    
    //=== FUNCTIONS zone
    function writeToLog($data, $title = '') {
            $log = "\n------ max2SumInvoices.php ------------------\n";
            $log .= date("Y.m.d G:i:s") . "\n";
            // $log .= (strlen($title) > 0 ? $title : 'DEBUG') . "\n";
            // $log .= print_r($data, 1);
            file_put_contents(getcwd() . '/hook.log', $log, FILE_APPEND);
            return true;
    }