..
This file is part of monday-client.
Copyright (C) 2024 Leet Cyber Security
monday-client is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
monday-client is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with monday-client. If not, see .
Webhooks
========
This guide explains how to work with monday.com Webhooks using monday-client and how to implement URL verification on your server endpoint.
References: `monday.com Webhooks API `_.
.. contents::
:depth: 2
:local:
Overview
--------
monday-client provides a ``Webhooks`` service with helpers to query, create, and delete webhooks for a board. After you create a webhook, monday.com will send a verification POST to your webhook URL with a JSON body containing a ``challenge`` token. Your endpoint must echo that token back to verify the URL.
.. note::
For standard webhooks, a personal API key is sufficient to create them. To receive webhooks that include a JWT ``Authorization`` header, or to prevent end-users from disabling integration webhooks, you must create the webhook using an integration app OAuth token.
URL Verification
----------------
When you create a webhook, monday.com verifies that you control the target URL by POSTing a JSON body containing a randomly generated token:
.. code-block:: python
{ 'challenge': 'challenge_text_here' }
Your server must respond with HTTP 200 and the same JSON body:
.. code-block:: python
{ 'challenge': 'challenge_text_here' }
Minimal endpoint examples
~~~~~~~~~~~~~~~~~~~~~~~~~
FastAPI:
.. code-block:: python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.post('/webhooks/monday')
async def monday_webhook(request: Request):
body = await request.json()
if isinstance(body, dict) and 'challenge' in body:
return JSONResponse(content={'challenge': body['challenge']}, status_code=200)
# Handle normal webhook delivery here
return JSONResponse(content={'ok': True}, status_code=200)
Flask:
.. code-block:: python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post('/webhooks/monday')
def monday_webhook():
data = request.get_json(silent=True) or {}
if 'challenge' in data:
return jsonify({'challenge': data['challenge']}), 200
# Handle normal webhook delivery here
return jsonify({'ok': True}), 200
Notes:
- Return quickly with 200; monday will retry once per minute for 30 minutes if not acknowledged.
- If the request includes an Authorization header with a JWT (when created with an integration app token), verify it against your app's signing secret before processing events.
- Always use HTTPS and return JSON that exactly matches the received ``challenge`` object.
- The webhook URL must be <= 255 characters, and must be reachable from monday.com's servers.
- See monday's URL verification docs for full details: https://developer.monday.com/api-reference/reference/webhooks#url-verification
Creating and managing webhooks with monday-client
-------------------------------------------------
Create a webhook
~~~~~~~~~~~~~~~~
.. code-block:: python
import asyncio
from monday import MondayClient
async def main():
monday_client = MondayClient(api_key='your_api_key')
webhook = await monday_client.webhooks.create(
board_id=1234567890,
url='https://example.com/webhooks/monday',
event='create_item', # see supported events below
# Optional config for supported events, e.g.:
# config={'columnId': 'status'}
)
print(webhook)
asyncio.run(main())
.. tip::
If you need to call the webhooks API with a different token (for example, an integration app OAuth token to enable JWT-authenticated deliveries), use the :py:meth:`monday.client.MondayClient.use_api_key` context manager (inside an async function):
.. code-block:: python
import asyncio
from monday import MondayClient
async def main():
monday_client = MondayClient(api_key='your_api_key')
async with monday_client.use_api_key('integration_oauth_token'):
await monday_client.webhooks.create(
board_id=1234567890,
url='https://example.com/webhooks/monday',
event='create_item',
)
asyncio.run(main())
Query webhooks
~~~~~~~~~~~~~~
.. code-block:: python
import asyncio
from monday import MondayClient
async def main():
monday_client = MondayClient(api_key='your_api_key')
hooks = await monday_client.webhooks.query(board_id=1234567890)
print(hooks)
asyncio.run(main())
Delete a webhook
~~~~~~~~~~~~~~~~
.. code-block:: python
import asyncio
from monday import MondayClient
async def main():
monday_client = MondayClient(api_key='your_api_key')
deleted = await monday_client.webhooks.delete(webhook_id='123')
print(deleted)
asyncio.run(main())
Supported events
----------------
The API supports these event types (see monday docs for details):
- ``change_column_value``
- ``change_status_column_value``
- ``change_subitem_column_value``
- ``change_specific_column_value``
- ``change_name``
- ``create_item``
- ``item_archived``
- ``item_deleted``
- ``item_moved_to_any_group``
- ``item_moved_to_specific_group``
- ``item_restored``
- ``create_subitem``
- ``change_subitem_name``
- ``move_subitem``
- ``subitem_archived``
- ``subitem_deleted``
- ``create_column``
- ``create_update``
- ``edit_update``
- ``delete_update``
- ``create_subitem_update``
Event configuration (``config``)
--------------------------------
Some events accept a ``config`` JSON argument when creating the webhook. Examples:
- ``change_specific_column_value``: ``{'columnId': ''}``
- ``change_status_column_value``: ``{'columnValue': {'index': }, 'columnId': ''}``
- ``item_moved_to_specific_group``: ``{'groupId': ''}``
Retry policy
------------
monday retries failed webhook deliveries once per minute for 30 minutes.
Testing notes
-------------
When running integration/mutation tests in this repository, configure a target URL that responds to monday's URL verification by echoing the ``challenge`` JSON back. Provide this via ``tests/integrations/config.yml`` as ``monday.webhook_target_url`` or the ``MONDAY_WEBHOOK_TARGET_URL`` environment variable.
Further reading
---------------
- monday.com Webhooks reference: https://developer.monday.com/api-reference/reference/webhooks