Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions setup/webhook_outgoing/odoo/addons/webhook_outgoing
6 changes: 6 additions & 0 deletions setup/webhook_outgoing/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
363 changes: 363 additions & 0 deletions webhook_outgoing/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
================
Outgoing Webhook
================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8bdaa6bf8f8de957410bd7bde59aa2ef3a84eaecce4da8d7d349b040e297dd77
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwebhook-lightgray.png?logo=github
:target: https://github.com/OCA/webhook/tree/16.0/webhook_outgoing
:alt: OCA/webhook
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/webhook-16-0/webhook-16-0-webhook_outgoing
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/webhook&target_branch=16.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows creating automations that send webhook/HTTP requests
to external systems.

Key Features
------------

- **Integration with Automated Actions**: Extends Odoo's automated
actions with webhook capabilities
- **Jinja Template Support**: Render request bodies dynamically using
Jinja2 templating engine
- **Queue Job Support**: Execute webhooks asynchronously using queue_job
for better performance
- **Multiple Request Types**: Support for standard HTTP, GraphQL, and
Slack webhooks
- **Flexible Configuration**: Customize endpoints, headers, body
templates, and request methods
- **Request Logging**: Optional logging of webhook calls for debugging
and troubleshooting

Use Cases
---------

- Send notifications to Slack, Discord, or other chat platforms when
records are created/updated
- Trigger external API calls when business events occur in Odoo
- Integrate with third-party services without custom code
- Synchronize data with external systems in real-time

**Table of contents**

.. contents::
:local:

Installation
============

Prerequisites
-------------

This module requires the following dependencies:

- ``queue_job`` - For asynchronous webhook execution. Please configure
``queue_job`` properly before installation.
- Python ``jinja2`` library - For template rendering

Installation Steps
------------------

1. Install the ``queue_job`` module from OCA/queue if you want to use
asynchronous execution:

- Available at: https://github.com/OCA/queue

2. If you haven't installed ``queue_job`` before installing this module,
you will need to restart the server to have ``queue_job`` loaded.

Post-Installation
-----------------

After installation, the module adds a new "Custom Webhook" action type
to Automated Actions. No additional configuration is required to start
using the module.

Configuration
=============

Navigate to **Settings > Technical > Automation > Automated Actions** to
configure webhook automations.

Basic Configuration
-------------------

1. **Create a New Automated Action**

- Click "Create"
- Set the **Model** (e.g., Sale Order, Contact, etc.)
- Define the **Trigger** (On Creation, On Update, etc.)
- Set **Action To Do** to "Custom Webhook"

2. **Configure Webhook Details**

**Endpoint**

- Enter the full URL of the webhook endpoint
- Example: ``https://hooks.slack.com/services/YOUR/WEBHOOK/URL``

**Request Method**

- Choose between GET or POST
- Most webhooks use POST

**Request Type**

- **HTTP Request**: Standard REST API calls
- **GraphQL**: For GraphQL APIs
- **Slack**: Optimized for Slack webhooks

3. **Headers Configuration**

Add any required headers in JSON format:

.. code:: json

{
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_TOKEN"
}

4. **Body Template**

Use Jinja2 syntax to create dynamic payloads:

.. code:: jinja

{
"id": {{ record.id }},
"name": "{{ record.name }}",
"email": "{{ record.email }}",
"created_date": "{{ record.create_date }}"
}

Available variables:

- ``record``: The record that triggered the action
- Any field from the record model

Asynchronous Execution
----------------------

Enable **Delay Execution** to run webhooks in the background using queue
jobs:

- Check "Delay Execution"
- Set **Delay ETA (s)** to specify how many seconds to wait before
execution

Webhook Logging
---------------

Enable **Log Calls** to track all webhook requests and responses for
debugging:

- Check "Log Calls"
- View logs in **Settings > Technical > Webhook Logging**

Domain Filters
--------------

Use the **Apply on** field to filter which records trigger the webhook
based on domain conditions.

Security Considerations
-----------------------

- Use HTTPS endpoints for secure communication
- Regularly review webhook logs for suspicious activity

Usage
=====

Example 1: Send Slack Notification on New Sale Order
----------------------------------------------------

1. Go to **Settings > Technical > Automation > Automated Actions**

2. Click **Create** and configure:

- **Name**: "Notify Slack on New Sale"
- **Model**: Sale Order
- **Trigger**: On Creation
- **Action To Do**: Custom Webhook

3. Configure the webhook:

- **Endpoint**: ``https://hooks.slack.com/services/YOUR/WEBHOOK/URL``
- **Request Method**: POST
- **Request Type**: Slack
- **Headers**:

.. code:: json

{
"Content-Type": "application/json"
}

- **Body Template**:

.. code:: jinja

{
"text": "New sale order created!",
"attachments": [{
"color": "good",
"fields": [
{
"title": "Order Number",
"value": "{{ record.name }}",
"short": true
},
{
"title": "Customer",
"value": "{{ record.partner_id.name }}",
"short": true
},
{
"title": "Amount",
"value": "${{ record.amount_total }}",
"short": true
}
]
}]
}

Example 2: POST to External API
-------------------------------

Configure a webhook to send contact data to an external CRM:

- **Endpoint**: ``https://api.example.com/contacts``
- **Request Method**: POST
- **Request Type**: HTTP Request
- **Headers**:

.. code:: json

{
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}

- **Body Template**:

.. code:: jinja

{
"external_id": {{ record.id }},
"first_name": "{{ record.name }}",
"email": "{{ record.email }}",
"phone": "{{ record.phone }}",
"company": "{{ record.company_id.name if record.company_id else '' }}"
}

Example 3: GraphQL Query
------------------------

Send a GraphQL mutation when a product is updated:

- **Endpoint**: ``https://api.example.com/graphql``
- **Request Method**: POST
- **Request Type**: GraphQL
- **Body Template**:

.. code:: jinja

mutation {
updateProduct(input: {
id: {{ record.id }}
name: {{ record.name | escape }}
price: {{ record.list_price }}
}) {
id
statusCode
}
}

Using Jinja2 Templates
----------------------

**Available Variables**

- ``record``: The current record triggering the action
- Access related fields using dot notation: ``record.partner_id.name``

**Common Jinja2 Filters**

.. code:: jinja

{# String manipulation #}
{{ record.name | upper }}
{{ record.description | truncate(100) }}

{# Default values #}
{{ record.email | default('no-email@example.com') }}

{# Conditional rendering #}
{% if record.state == 'sale' %}
"status": "confirmed"
{% else %}
"status": "draft"
{% endif %}

{# Escaping for GraphQL #}
{{ record.name | escape }}

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/webhook/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/webhook/issues/new?body=module:%20webhook_outgoing%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Hoang Tran

Contributors
------------

- Hoang Tran thhoang.tr@gmail.com

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/webhook <https://github.com/OCA/webhook/tree/16.0/webhook_outgoing>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions webhook_outgoing/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
23 changes: 23 additions & 0 deletions webhook_outgoing/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2024 Hoang Tran <thhoang.tr@gmail.com>.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

{
"name": "Outgoing Webhook",
"summary": "Webhook to publish events based on automated triggers",
"version": "16.0.0.0.1",
"author": "Hoang Tran,Odoo Community Association (OCA)",
"license": "LGPL-3",
"website": "https://github.com/OCA/webhook",
"depends": [
"base_automation",
"queue_job",
],
"data": [
"security/ir.model.access.csv",
"data/queue_data.xml",
"views/webhook_logging_views.xml",
"views/ir_action_server_views.xml",
"views/menus.xml",
],
"installable": True,
}
Loading