A Basic PHP Webhook Example

Hello All,

I had a heck of a time getting started on this so hopefully this is helpful to someone…

A couple notes:

  1. I put double brackets {{}} around everything you’d want to change/update for your specific use

  2. This probably won’t work as-is because its a bastardized version of my real script so its certainly not plug-and-play.

  3. I know my formatting is weird.

  4. the PHP below should be put on your server at the URI you specify in the Webhook on Monday when setting it up.

     <?php
     //return monday challenge
     echo file_get_contents('php://input');
    
     // capture second response which should be JSON payload
     $php_event = json_decode(file_get_contents('php://input'), true)['event'];
    
     // init
     ini_set("log_errors", 1);
     ini_set('error_reporting', E_ALL);
     ini_set("error_log", "monday.log"); // this is an empty file you should create to monitor/debug your webhook
    
     // a function to dump large arrays etc to the log
     function error_log_dump( $object=null ){
     	ob_start();                    // start buffer capture
     	var_dump( $object );           // dump the values
     	$buffer_contents = ob_get_contents(); // put the buffer into a variable
     	ob_end_clean();                // end capture
     	error_log("-------------------------\n".print_r($buffer_contents, true), 3, "monday.log");
     }
    
     // function to make queries and mutaions via Monday API v2
     function ping_api($query){
     	$data = @file_get_contents(
     		"https://api.monday.com/v2/",
     		false,
     		stream_context_create(
     			[
     				'http' => [
     					'method' => 'POST',
     					'header' => [
     						'Content-Type: application/json',
     						'User-Agent: [MYTEAM] GraphQL Client',
     						'Authorization: {{YOUR TOKEN HERE}}'
     					],
     					'content' => json_encode($query)
     				]
     			]
     		)
     	);
    
     	// decode the response back to PHP
     	$response = json_decode(
     		$data,
     		true
     	);
    
     	// error reporting
     	if(is_null($response)){
     		error_log("query error: no response from server");
     		exit();
     	} elseif (isset($response["errors"])) {
     		error_log("query error: ".$response["errors"][0]["message"]);
     		exit();
     	} elseif (isset($response["data"])) {
     		//error_log("query success");
     		return $response;
     	}
     	//error_log_dump($response);
     }
    
     // debug response
     error_log_dump($php_event);
    
     if($php_event['boardId'] == "{{ID OF CERTAIN BOARD YOU WANT TO WATCH - DON'T FORGET TO GIVE THE BOARD A WEBHOOK AUTOMATION IN MONDAY}}"){
    
     	if($php_event['type'] == "update_column_value"){ // change was an update (not a new item - that's below)
    
     		// code here
    
     		// here is something I found useful using "watch arrays" to monitor only certain columns
    
     		// create an array of column ids to watch
     		$watch_array = ["{{ID OF FIRST_COLUMN YOU WANT TO WATCH}}", "{{ID OF FIRST_COLUMN YOU WANT TO WATCH}}", "{{AND DO ON}}"];
     		if(in_array($php_event['columnId'], $watch_array)){
    
     			// get more info about the item that changed
     			$item_that_changed_query = ["query" =>
     				"
     					{
     						items(ids: [".$php_event["pulseId"]."]){
     							column_values(ids:[link_to_item0]) {
     								id
     								text
     								title
     								value
     							}
     						}
     					}
     				"
     			];
     			$item_that_changed_response = ping_api($item_that_changed_query);
    
     			// if you want the name of the item...
     			$item_that_changed_name = $project_response["data"]["items"][0]["name"];
    
     			// if you want the meat of the response, you probably want the column values which is an array
     			$item_that_changed_column_values = $item_that_changed_response["data"]["items"][0]["column_values"];
    
     			// then you can loop the array to scrub the data or whatever
     			foreach ($project_array as $key => $val) {
    
     				if($val['id'] == "{{THE ID OF A CERTAIN COLUMN}}"){
     					
     				}
     				elseif($val['title'] == "{{THE TILE OF A CERTAIN COLUMN}}"){ // probably not advisable because titles can change so easily
     					if($val['text'] == ""){
     						$my_text = "THIS STUPID VALUE WAS EMPTY!";
     					}
     				}
     				elseif($val['title'] == "{{MULTILINE TEXT}}"){
     					if($val['text'] != ""){
     						$scope = nl2br($val['text']); //reformat line breaks
     					}
     				}
     			}
    
     			// if you have linked columns you can get the id for the linked item then us it to make another query
     			$linked_item_id = json_decode($item_that_changed_response["data"]["items"][0]["column_values"][0]["value"], true)["linkedPulseIds"][0]["linkedPulseId"];
     			$linked_item_query = ["query" =>
     				"
     					{
     						items(ids: [".$linked_item_id."]){
     							board {
     								id
     							}
     							column_values(ids:[{{A COMMA SEPARATED LIST OF IDS YOU WANT TO GRAB}}]) {
     								id
     								text
     								title
     								value
     							}
     						}
     					}
     				"
     			];
     			$linked_item_response = ping_api($linked_item_query);
    
     			// to mutate an item I've been using arraysa because the JSON escaping is really confusing!
     			// yes its wierd that I'm encodeing the array twice... IDK it works!
     			$column_values = json_encode(
     				[
     					"{{ID OF A 'LONG TEXT' COLUMN YOU WANT TO CHANGE}}" => [
     						"text" => "{{SOME LONG TEXT YOU WANT TO WRITE}}"
     					],
     					"{{ID OF A 'NUMBER' COLUMN IS LESS COMPLICATED}}" => "150"
     				]
     			);
     			$item_i_want_to_change_query = ["query" =>
     				"
     					mutation{
     						change_multiple_column_values (
     							board_id: {{ID OF BOARD WHERE YOU WANT TO CHANGE THE ITEM}},
     							item_id: {{ID OF ITEM YOU WANT TO CHANGE}},
     							column_values: ".json_encode($column_values).",
     						)
     						{
     							id
     						}
     					}
     				"
     			];
     			$item_i_want_to_change_response = ping_api($item_i_want_to_change_query);
     		}
     	}
     	elseif ($php_event["type"] == "create_pulse") { // item created as opposed to changed
    
     		// code here
    
     	}
     } // end of that board's webhooks
     elseif($php_event['boardId'] == "{{SOME OTHER BOARD ID}}"){ // another board you want to watch
    
     	// code here
    
     }
    

    ?>

2 Likes
$json = file_get_contents('php://input');
$data = json_decode($json,true);

switch ($data) {
  case $data["challenge"]!="":
    header('Content-Type: application/json');
    echo $json;
    break;
}
2 Likes

Hey @robzinn :wave:

Sorry that it took us a while to recognize this gem! Thank you so much for helping the community by sharing this, I do hope it will carve a path for other users to get this to work and have an easier time with it.

I appreciate your effort here and keeping the community spirit!

-Alex

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.