diff --git a/content/administration/odoo_online.rst b/content/administration/odoo_online.rst index 5d16c073ce..cb5c3ce012 100644 --- a/content/administration/odoo_online.rst +++ b/content/administration/odoo_online.rst @@ -14,6 +14,8 @@ Odoo Online databases are accessed using any web browser and do not require a lo To quickly try out Odoo, shared `demo `_ instances are available. No registration is required, but each instance only lives for a few hours. +.. _odoo_online/database-management: + Database management =================== diff --git a/content/applications/studio.rst b/content/applications/studio.rst index e6248779d0..66621659f5 100644 --- a/content/applications/studio.rst +++ b/content/applications/studio.rst @@ -15,8 +15,8 @@ Studio studio/pdf_reports studio/approval_rules -**Studio** is a toolbox used to customize Odoo without coding knowledge. For example, in any app, -add or modify: +**Odoo Studio** is a toolbox used to customize Odoo without coding knowledge. For example, in any +app, add or modify: - :doc:`Fields ` - :doc:`Views ` @@ -31,10 +31,22 @@ Learn how to :doc:`build an app from scratch `. .. _studio/access: -To access Studio, navigate to the app and model you want to modify, then click the :icon:`oi-studio` -(:guilabel:`Toggle Studio`) icon, or vice versa. +To access **Studio**, navigate to the app and model you want to modify, then click the +:icon:`oi-studio` (:guilabel:`Toggle Studio`) icon. Alternatively, with any app open, click the +:icon:`oi-studio` (:guilabel:`Toggle Studio`) icon and navigate to the relevant app and model. To close **Studio**, click :guilabel:`Close` in the upper-right corner. +.. warning:: + Installing **Studio** in an Odoo database on the *Standard* pricing plan automatically triggers + an upsell to the *Custom* pricing plan. + + - **For yearly or multi-year contracts**: An upsell order is created with a 30-day limit. + - **For monthly contracts**: The subscription automatically switches to the *Custom* plan and + the new rate is applied when the next bill is generated. + + For more information, refer to `Odoo's pricing page `_ or + contact your account manager. + .. seealso:: `Odoo Tutorials: Studio `_ diff --git a/content/applications/studio/automated_actions.rst b/content/applications/studio/automated_actions.rst index 196713b861..04569f1269 100644 --- a/content/applications/studio/automated_actions.rst +++ b/content/applications/studio/automated_actions.rst @@ -4,15 +4,21 @@ Automation rules ================ -Automation rules are used to trigger automatic changes based on user actions (e.g., apply a -modification when a field is set to a specific value), email events, time conditions (e.g., archive -a record 7 days after its last update), or external events. +Automation rules allow the execution of one or more predefined actions in response to a specific +trigger, e.g., create an activity when a field is set to a specific value, or archive a record 7 +days after its last update. -To create an automation rule with Studio, proceed as follows: +When creating an automation rule, :ref:`domain filters ` +allow you to add conditions that must be met for the automation rule to run, e.g., the opportunity +must be assigned to a specific salesperson, or the state of the record must not be +:guilabel:`Draft`. + +To create an automation rule with **Odoo Studio**, proceed as follows: #. :ref:`Open Studio ` and click :guilabel:`Automations`, then :guilabel:`New`. -#. Select the :ref:`studio/automated-actions/trigger` and, if necessary, fill in the fields that - appear on the screen based on the chosen trigger. +#. Give the automation rule a clear, meaningful name that identifies its purpose. +#. Select the :ref:`trigger ` and, if necessary, fill in the + fields that appear on the screen based on the chosen trigger. #. Click :guilabel:`Add an action`, then select the :guilabel:`Type` of :ref:`action ` and fill in the fields that appear on the screen based on your selected action. @@ -20,18 +26,24 @@ To create an automation rule with Studio, proceed as follows: .. example:: - .. image:: automated_actions/automation-rule-ex.png - :alt: Example of an automated action on the Subscription model + To ensure follow-up on less satisfied clients, this automation rule creates an activity 3 months + after a sales order is created for clients with a satisfaction percentage lower than 30%. + + .. image:: automated_actions/create-activity-conditions.png + :alt: Example of an automation rule on the Subscription model + :scale: 80% .. tip:: - - To modify the :doc:`model ` of the automation rule, switch models before - clicking :guilabel:`Automations` in Studio, or :ref:`activate the developer mode + - Use the :guilabel:`Notes` tab to document the purpose and functioning of automation rules. This + makes rules easier to maintain and facilitates collaboration between users. + - To modify the :doc:`model ` targeted by the automation rule, switch models + before clicking :guilabel:`Automations` in Studio, or :ref:`activate developer mode `, create or edit an automation rule, and select the :guilabel:`Model` in the :guilabel:`Automation Rules` form. - - You can also create automation rules from any kanban stage by clicking the gear icon - (:guilabel:`⚙` ) next to the kanban stage name, then selecting :guilabel:`Automations`. In this - case, the :guilabel:`Trigger` is set to :guilabel:`Stage is set to` by default, but you can - change it if necessary. + - Automation rules can be created from any kanban stage by clicking the :icon:`fa-cog` + :guilabel:`(Settings)` icon that appears when hovering over the kanban stage name, then + selecting :guilabel:`Automations`. In this case, the :guilabel:`Trigger` is set to + :guilabel:`Stage is set to` by default, but it can be changed if necessary. .. image:: automated_actions/automations-kanban.png :alt: Create automations from a kanban stage @@ -41,99 +53,146 @@ To create an automation rule with Studio, proceed as follows: Trigger ======= -The :guilabel:`Trigger` is used to define when the automation rule should be applied. The available -triggers depend on the :doc:`model `. Five trigger categories are available -overall: +The :guilabel:`Trigger` is used to define what kind of event needs to occur for the automation rule +to run. The available triggers depend on the :doc:`model `. Five trigger +categories are available overall: + +- :ref:`studio/automated-actions/trigger-values-updated` +- :ref:`studio/automated-actions/trigger-email-events` +- :ref:`studio/automated-actions/trigger-timing-conditions` +- :ref:`studio/automated-actions/trigger-custom` +- :ref:`studio/automated-actions/trigger-external` + +.. _studio/automated-actions/conditions: + +Adding conditions +----------------- -- :ref:`studio/automated-actions/trigger/values-updated` -- :ref:`studio/automated-actions/trigger/email-events` -- :ref:`studio/automated-actions/trigger/values-timing-conditions` -- :ref:`studio/automated-actions/trigger/custom` -- :ref:`studio/automated-actions/trigger/external` +Domain filters allow you to determine the records an automation rule should target or exclude. +Efficient filtering enhances overall performance as it avoids unnecessary processing on records that +are not impacted by the rule. .. tip:: - You can also define a :guilabel:`Before Update Domain` to specify the conditions that must be met - *before* the automation rule is triggered. In contrast, the conditions defined using the - :ref:`Extra Conditions ` and - :ref:`Apply on ` filters are checked *during* the - execution of the automation rule. + :ref:`Activate developer mode ` before creating an automation rule to have the + most flexibility in adding domain filters. - To define a :guilabel:`Before Update Domain`, :ref:`activate the developer mode - `, create or edit an automation rule, click :guilabel:`Edit Domain`, then click - :guilabel:`New Rule`. +Depending on the trigger chosen, it is possible to define one or more conditions a record must meet +*before* and/or *after* a trigger occurs. - For example, if you want the automated action to happen when an email address is set on a - contact that did not have an address before (in contrast to modifying their existing address), - define the :guilabel:`Before Update Domain` to :guilabel:`Email is not set`, and the - :guilabel:`Apply on` domain to :guilabel:`Email is set`. +- The :guilabel:`Before Update Domain` defines the conditions a record must meet *before* the + trigger event occurs, e.g., the record must have `Type = Customer Invoice` and `Status = Posted`. + + With :ref:`developer mode activated `, click :guilabel:`Edit Domain`, if + available, then :guilabel:`New Rule`. + +- :guilabel:`Extra Conditions`, or in some cases :guilabel:`Apply on` filters, define the conditions + a record must meet *after* the trigger event occurs, e.g., the customer invoice must have `Payment + Status = Partially Paid`. + + With :ref:`developer mode activated ` if needed, click :guilabel:`Add conditions` + or :guilabel:`Edit Domain`, as relevant, then :guilabel:`New Rule`. + +When a :ref:`trigger ` occurs, e.g., the payment status of a +posted customer invoice is updated, the automation rule checks the defined conditions and only +executes the :ref:`action ` if the record matches those conditions. + +.. example:: + If the automated action should be executed when an email address is set for the first time (in + contrast to modifying an email address) on an existing contact that is an individual rather than + a company, use `Email is not set` and `Is a Company is not set` as the :guilabel:`Before Update + Domain` and `Email is set` as the :guilabel:`Apply on` domain. .. image:: automated_actions/before-update-domain.png :alt: Example of a trigger with a Before Update Domain -.. _studio/automated-actions/trigger/values-updated: +.. note:: + The :guilabel:`Before Update Domain` is not checked upon the creation of a record. + +.. _studio/automated-actions/trigger-values-updated: Values Updated -------------- -The triggers available in this category depend on the model and are based on common field changes, -such as adding a specific tag (e.g., to a task) or setting the :guilabel:`User` field. Select the -trigger, then select a value if required. +Trigger automated actions when specific changes happen in the database. The triggers available in +this category depend on the model and are based on common changes, such as adding a specific tag +(e.g., to a task) or setting a field's value (e.g., setting the :guilabel:`User` field). -.. image:: automated_actions/values-updated-trigger.png - :alt: Example of a Values Updated trigger +Select the trigger, then select a value if required. -.. _studio/automated-actions/trigger/email-events: +.. _studio/automated-actions/trigger-email-events: Email Events ------------ Trigger automated actions upon receiving or sending emails. -.. _studio/automated-actions/trigger/values-timing-conditions: +.. _studio/automated-actions/trigger-timing-conditions: Timing Conditions ----------------- -Trigger automated actions based on a date field. The following triggers are available: +Trigger automated actions at a point in time relative to a date field or to the creation or update +of a record. The following triggers are available: -- :guilabel:`Based on date field`: Select the field to be used next to the :guilabel:`Delay` field. -- :guilabel:`After creation`: The action is triggered when a record is created and saved. -- :guilabel:`After last update`: The action is triggered when an existing record is edited and - saved. +- :guilabel:`Based on date field`: The action is triggered a defined period of time before or after + the date of the selected date field. +- :guilabel:`After creation`: The action is triggered a defined period of time after a record is + created and saved. +- :guilabel:`After last update`: The action is triggered a defined period of time after an existing + record is edited and saved. You can then define: -- a :guilabel:`Delay`: Specify the number of minutes, hours, days, or months. To trigger the action - before the trigger date, specify a negative number. If you selected the :guilabel:`Based on date - field` trigger, you must also select the date field to be used to determine the delay. +- a :guilabel:`Delay`: Specify the number of minutes, hours, days, or months. To have an action + executed before the trigger date, specify a negative number. If you selected the :guilabel:`Based + on date field` trigger, you must also select the date field to be used to determine the delay. + + .. note:: + By default, the scheduler checks for time-triggered automation rules every 240 minutes, or 4 + hours. This frequency is generally sufficient for delays such as 3 months after the order date + or 7 days after the last update. + + For delays of less than the equivalent of 2400 minutes, or 40 hours, the system recalculates + the frequency of this check to ensure that more granular delays, e.g., 1 hour before the event + start date and time, or 30 minutes after creation, can be respected as closely as possible. + + An on-screen message indicates the possible delay after the scheduled triggering of the rule. + + .. image:: automated_actions/trigger-delay-message.png + :alt: Message about possible delay after scheduled execution + + To view or manually edit the frequency of the scheduler, with :ref:`developer mode activated + `, go to :menuselection:`Settings --> Technical --> Scheduled Actions` to see + all scheduled actions for your database. + + Enter `Automation` in the search bar, then, in the list of results, click :guilabel:`Automation + Rules: check and execute`. If desired, update the value of the :guilabel:`Execute Every` field. + Click :guilabel:`Run Manually` at any time to manually trigger this scheduled action. + - :guilabel:`Extra Conditions`: Click :guilabel:`Add condition`, then specify the conditions to be - met to trigger the automation rule. Click :guilabel:`New Rule` to add another condition. + met for the automation rule to run. Click :guilabel:`New Rule` to add another condition. -The action is triggered when the delay is reached and the conditions are met. +The action is executed when the delay is reached and the conditions are met. .. example:: - If you want to send a reminder email 30 minutes before the start of a calendar event, select the - :guilabel:`Start (Calendar Event)` under :guilabel:`Trigger Date` and set the :guilabel:`Delay` - to **-30** :guilabel:`Minutes`. + To send a reminder email 30 minutes *before* the start of a calendar event, select `Based on date + field` as the :guilabel:`Trigger`, then set the :guilabel:`Delay` to `-30` :guilabel:`Minutes` + and select :guilabel:`Start (Calendar Event)` as the date field. .. image:: automated_actions/timing-conditions-trigger.png :alt: Example of a Based on date field trigger -.. note:: - By default, the scheduler checks for trigger dates every 4 hours, meaning lower granularity in - time-based automations may not always be honored. - -.. _studio/automated-actions/trigger/custom: +.. _studio/automated-actions/trigger-custom: Custom ------ Trigger automated actions: -- :guilabel:`On save`: When the record is saved; -- :guilabel:`On deletion`: When a record is deleted; -- :guilabel:`On UI change`: When a field's value is changed on the :ref:`Form view - `, even before saving the record. +- :guilabel:`On save`: when a record is saved. +- :guilabel:`On deletion`: when a record is deleted. +- :guilabel:`On UI change`: when a field's value is changed on the :ref:`Form view + `, even before the record is saved. For the :guilabel:`On save` and :guilabel:`On UI change` triggers, you **must** then select the field(s) to be used to trigger the automation rule in the :guilabel:`When updating` field. @@ -145,49 +204,49 @@ field(s) to be used to trigger the automation rule in the :guilabel:`When updati Optionally, you can also define additional conditions to be met to trigger the automation rule in the :guilabel:`Apply on` field. +.. example:: + To trigger an automated action *upon* the creation of a record, e.g., when a new contact is + created, select the :ref:`On save ` trigger and use + `ID is not set` as the :guilabel:`Before Update Domain` and `ID is set` as the + :guilabel:`Apply on` domain. Make sure the correct field is selected in the :guilabel:`When + updating` field. + + When a new contact is saved, it is automatically assigned a database ID, thereby triggering the + automation rule. + + .. image:: automated_actions/on-save-on-creation.png + :alt: Example of a triggering an action upon creation of a record. + .. note:: - The :guilabel:`On UI change` trigger can only be used with the - :ref:`studio/automated-actions/action/python-code` action and only works when a modification is - made manually. The action is not executed if the field is changed through another automation - rule. + The :guilabel:`On UI change` trigger can only be used with the :ref:`Execute Code + ` action and only works when a modification is made + manually. The action is not executed if the field is changed through another automation rule. -.. _studio/automated-actions/trigger/external: +.. _studio/automated-actions/trigger-external: External -------- -Trigger automated actions based on an external event using a webhook. A webhook is a method of -communication between two systems where the source system sends an HTTP(S) request to a destination -system based on a specific event. It usually includes a data payload containing information about -the event that occurred. +Trigger automated actions based on a specific event in an external system or application using a +:doc:`webhook `. -To configure the :guilabel:`On webhook` trigger, copy the :guilabel:`URL` generated by Odoo into the -destination system (i.e., the system receiving the request). Then, in the :guilabel:`Target Record` -field, enter the code to run to define the record(s) to be updated using the automation rule. +After the webhook is configured in Odoo, where the webhook's URL is generated and the target record +defined, it needs to be implemented in the external system. .. warning:: - The URL must be treated as **confidential**; sharing it online or without caution could - potentially expose your system to malicious parties. Click the :guilabel:`Rotate Secret` button - to change the URL's secret if necessary. + It is *highly recommended* to consult with a developer, solution architect, or another technical + role when deciding to use webhooks and throughout the implementation process. If not properly + configured, webhooks may disrupt the Odoo database and can take time to revert. + +.. image:: automated_actions/webhook-update-record.png + :alt: Example of a Based on date field trigger .. note:: - - The code defined by default in the :guilabel:`Target Record` field works for webhooks coming - from another Odoo database. It is used to determine the record(s) to be updated using the - information in the payload. - - If you wish to use the webhook's content for a purpose other than to find the record(s) (e.g., - *create* a record), your only option is to use an :ref:`studio/automated-actions/action/python-code` - action. In this case, the :guilabel:`Target record` field must contain any valid code, but its - result doesn't have any effect on the automated action itself. - - The webhook content is available in the server action context as a `payload` variable (i.e., a - dictionary that contains the GET parameters or POST JSON body of the incoming request). - -You can also choose to :guilabel:`Log Calls` to record the payloads received, e.g., to make sure the -data sent by the source system matches the expected format and content. This also helps identify -and diagnose any issues that may arise. To access the logs, click the :guilabel:`Logs` smart -button at the top of the :guilabel:`Automation rules` form. + It is also possible to set up an automated action that :ref:`sends data to a external system's + webhook ` when an event occurs in your Odoo database. .. seealso:: - :doc:`automated_actions/webhooks` + :doc:`Webhook documentation ` .. _studio/automated-actions/action: @@ -195,24 +254,32 @@ Actions ======= Once you have defined the automation rule's :ref:`trigger `, click -:guilabel:`Add an action` to define the action to be executed. +:guilabel:`Add an action` in the :guilabel:`Actions To Do` tab to define the action to be executed. + +The title of the action is automatically generated based on the action you define, but it can be +updated manually. .. tip:: - You can define multiple actions for the same trigger/automation rule. The actions are executed - in the order they are defined. This means, for example, that if you define an - :guilabel:`Update record` action and then a :guilabel:`Send email` action, the email uses the - updated values. However, if the :guilabel:`Send email` action is defined before the - :guilabel:`Update record` action, the email uses the values set *before* the update action is - run. + You can define multiple actions for the same automation rule. By default, actions are executed in + the order in which they were defined. -.. _studio/automated-actions/action/update-record: + This means, for example, that if you define an :guilabel:`Update record` action and then a + :guilabel:`Send email` action where the email references the field that was updated, the email + uses the updated values. However, if the :guilabel:`Send email` action is defined before the + :guilabel:`Update record` action, the email uses the values set *before* the record is updated. + + To change the order of defined actions, click the :icon:`oi-draggable` :guilabel:`(drag handle)` + icon beside an action and drag it to the desired position. + +.. _studio/automated-actions/action-update-record: Update Record ------------- -This action allows to update one of the record's (related) fields. Click the :guilabel:`Update` -field and, in the list that opens, select or search for the field to be updated; click the right -arrow next to the field name to access the list of related fields if needed. +This action updates one of the record's (related) fields. Click the :guilabel:`Update` field and, in +the list that opens, select or search for the field to be updated. If needed, click the +:icon:`oi-chevron-right` :guilabel:`(right arrow)` next to the field name to access the list of +related fields. If you selected a :ref:`many2many field `, choose whether the field must be updated by :guilabel:`Adding`, :guilabel:`Removing`, or :guilabel:`Setting it to` @@ -220,10 +287,10 @@ the selected value or by :guilabel:`Clearing it`. .. example:: If you want the automated action to remove a tag from the customer record, set the - :guilabel:`Update` field to :guilabel:`Customer > Tags`, select :guilabel:`By Removing`, then + :guilabel:`Update` field to :guilabel:`Customer > Tags`, select :guilabel:`by Removing`, then select the tag. - .. image:: automated_actions/update-record-action.png + .. image:: automated_actions/update-record-tags.png :alt: Example of an Update Record action .. tip:: @@ -237,6 +304,8 @@ the selected value or by :guilabel:`Clearing it`. .. image:: automated_actions/update-record-compute.png :alt: Compute a custom datetime field using a Python expression +.. _studio/automated-actions/action-create-activity: + Create Activity --------------- @@ -244,19 +313,29 @@ This action is used to schedule a new activity linked to the record. Select an : Type`, enter a :guilabel:`Title` and description, then specify when you want the activity to be scheduled in the :guilabel:`Due Date In` field, and select a :guilabel:`User type`: -- To always assign the activity to the same user, select :guilabel:`Specific User` and add the user - in the :guilabel:`Responsible` field; +- To always assign the activity to the same user, select :guilabel:`Specific User`, then add the + user in the :guilabel:`Responsible` field. - To target a user linked to the record dynamically, select :guilabel:`Dynamic User (based on - record)` and change the :guilabel:`User Field` if necessary. + record)`. If needed, change the :guilabel:`User Field` by clicking on the placeholder field name + then selecting or searching for the user field in the list that appears. In the list, click the + :icon:`fa-chevron-right` :guilabel:`(right arrow)` next to the field name to access related fields + if needed. .. example:: - After a lead is turned into an opportunity, you want the automated action to set up a call for - the user responsible for the lead. To do so, set the :guilabel:`Activity Type` to - :guilabel:`Call` and the :guilabel:`User Type` to :guilabel:`Dynamic User (based on record)`. + After a proposition is sent to a opportunity with a high expected revenue, you want to create an + activity for the salesperson's team leader to call the potential client to increase the chances + of closing the deal. + + To do so, set the :guilabel:`Activity Type` to :guilabel:`Call` and the :guilabel:`User Type` to + :guilabel:`Dynamic User (based on record)`. Click on the placeholder field and select + :guilabel:`Sales Team`, then click the :icon:`fa-chevron-right` :guilabel:`(right arrow)` and + select :guilabel:`Team Leader`. .. image:: automated_actions/create-activity-action.png :alt: Example of a Create Activity action +.. _studio/automated-actions/action-send-email-sms: + Send Email and Send SMS ----------------------- @@ -276,7 +355,7 @@ email or text message: :guilabel:`SMS template` and post it as an internal note in the chatter. - :guilabel:`Note only`: to only post the message as an internal note in the chatter. -.. _studio/automated-actions/action/send-whatsapp: +.. _studio/automated-actions/action-send-whatsapp: Send WhatsApp ------------- @@ -286,14 +365,34 @@ Send WhatsApp :ref:`WhatsApp templates ` must be created. This action is used to send a WhatsApp message to a contact linked to a specific record. -To do so, select the appropriate :guilabel:`WhatsApp Template` from the drop-down menu. +To do so, select the appropriate :guilabel:`WhatsApp Template` from the dropdown menu. -.. _studio/automated-actions/action/add-followers: +.. _studio/automated-actions/action-add-remove-followers: Add Followers and Remove Followers ---------------------------------- -Use these actions to (un)subscribe existing contacts to/from the record. +This action is used to subscribe/unsubscribe existing contacts to/from the record. Followers can be +added in two ways: + +- To always add the same, specific contact(s), select :guilabel:`Specific Followers` as + :guilabel:`Followers Type` then choose the relevant contact from the dropdown. Repeat as many + times as needed to add multiple contacts. + +- To add a contact linked to the record dynamically, select :guilabel:`Dynamic Followers` as + :guilabel:`Followers Type`. If needed, change the :guilabel:`Followers Field` by clicking on the + placeholder field name then selecting or searching for the partner field in the list that appears. + In the list, click the :icon:`fa-chevron-right` :guilabel:`(right arrow)` next to the field name + to access related fields if needed. + +.. example:: + To keep customers informed of progress on a project, this automated action adds the relevant + customer as a follower when a project task is set to :guilabel:`In progress`. + + .. image:: automated_actions/add-followers-action.png + :alt: Adding the customer as a follower when project task set to in progress + +.. _studio/automated-actions/action-create-record: Create Record ------------- @@ -311,16 +410,22 @@ triggered the creation of the new record. :ref:`many2one field ` on the target model. .. tip:: - You can create another automation rule with :ref:`studio/automated-actions/action/update-record` + You can create another automation rule with :ref:`studio/automated-actions/action-update-record` actions to update the fields of the new record if necessary. For example, you can use a :guilabel:`Create Record` action to create a new project task and then assign it to a specific user using an :guilabel:`Update Record` action. -.. _studio/automated-actions/action/python-code: +.. _studio/automated-actions/action-execute-code: Execute Code ------------ +.. important:: + For automation rules that require the execution of :ref:`custom code + `, note that maintenance of custom code is not + included in the *Standard* or *Custom* pricing plans and incurs :ref:`additional fees + `. + This action is used to execute Python code. You can write your code into the :guilabel:`Code` tab using the following variables: @@ -341,18 +446,25 @@ using the following variables: .. tip:: The available variables are described both in the :guilabel:`Code` and :guilabel:`Help` tabs. +.. seealso:: + :doc:`Odoo's ORM capabilities <../../developer/reference/backend/orm>` + .. _studio/automated-actions/action-webhook: Send Webhook Notification ------------------------- -This action allows to send a POST request with the values of the :guilabel:`Fields` to the URL -specified in the :guilabel:`URL` field. +This action is used to send a `POST` API request with the values of the selected :guilabel:`Fields` +to the webhook URL specified in the :guilabel:`URL` field. The :guilabel:`Sample Payload` provides a preview of the data included in the request using a random record's data or dummy data if no record is available. -.. _studio/automated-actions/action/several-actions: +.. note:: + It is also possible to set up an automated action that :doc:`uses a webhook to receive data from + an external system ` when a predefined event occurs in that system. + +.. _studio/automated-actions/action-existing-actions: Execute Existing Actions ------------------------ diff --git a/content/applications/studio/automated_actions/add-followers-action.png b/content/applications/studio/automated_actions/add-followers-action.png new file mode 100644 index 0000000000..023992c89b Binary files /dev/null and b/content/applications/studio/automated_actions/add-followers-action.png differ diff --git a/content/applications/studio/automated_actions/automation-rule-ex.png b/content/applications/studio/automated_actions/automation-rule-ex.png deleted file mode 100644 index 221bb156cd..0000000000 Binary files a/content/applications/studio/automated_actions/automation-rule-ex.png and /dev/null differ diff --git a/content/applications/studio/automated_actions/before-update-domain.png b/content/applications/studio/automated_actions/before-update-domain.png index a775c61598..fad4436e2b 100644 Binary files a/content/applications/studio/automated_actions/before-update-domain.png and b/content/applications/studio/automated_actions/before-update-domain.png differ diff --git a/content/applications/studio/automated_actions/create-activity-action.png b/content/applications/studio/automated_actions/create-activity-action.png index cc6e2f42d0..749336a1eb 100644 Binary files a/content/applications/studio/automated_actions/create-activity-action.png and b/content/applications/studio/automated_actions/create-activity-action.png differ diff --git a/content/applications/studio/automated_actions/create-activity-conditions.png b/content/applications/studio/automated_actions/create-activity-conditions.png new file mode 100644 index 0000000000..d11e89466e Binary files /dev/null and b/content/applications/studio/automated_actions/create-activity-conditions.png differ diff --git a/content/applications/studio/automated_actions/on-save-on-creation.png b/content/applications/studio/automated_actions/on-save-on-creation.png new file mode 100644 index 0000000000..773650963e Binary files /dev/null and b/content/applications/studio/automated_actions/on-save-on-creation.png differ diff --git a/content/applications/studio/automated_actions/timing-conditions-trigger.png b/content/applications/studio/automated_actions/timing-conditions-trigger.png index 41ca2575d0..096f3872d4 100644 Binary files a/content/applications/studio/automated_actions/timing-conditions-trigger.png and b/content/applications/studio/automated_actions/timing-conditions-trigger.png differ diff --git a/content/applications/studio/automated_actions/trigger-delay-message.png b/content/applications/studio/automated_actions/trigger-delay-message.png new file mode 100644 index 0000000000..6708c26c18 Binary files /dev/null and b/content/applications/studio/automated_actions/trigger-delay-message.png differ diff --git a/content/applications/studio/automated_actions/update-record-action.png b/content/applications/studio/automated_actions/update-record-action.png deleted file mode 100644 index 1915eef219..0000000000 Binary files a/content/applications/studio/automated_actions/update-record-action.png and /dev/null differ diff --git a/content/applications/studio/automated_actions/update-record-compute.png b/content/applications/studio/automated_actions/update-record-compute.png index c0c8129128..87fd502c94 100644 Binary files a/content/applications/studio/automated_actions/update-record-compute.png and b/content/applications/studio/automated_actions/update-record-compute.png differ diff --git a/content/applications/studio/automated_actions/update-record-tags.png b/content/applications/studio/automated_actions/update-record-tags.png new file mode 100644 index 0000000000..83ee0a0c6b Binary files /dev/null and b/content/applications/studio/automated_actions/update-record-tags.png differ diff --git a/content/applications/studio/automated_actions/values-updated-trigger.png b/content/applications/studio/automated_actions/values-updated-trigger.png deleted file mode 100644 index 39758f7057..0000000000 Binary files a/content/applications/studio/automated_actions/values-updated-trigger.png and /dev/null differ diff --git a/content/applications/studio/automated_actions/webhook-update-record.png b/content/applications/studio/automated_actions/webhook-update-record.png new file mode 100644 index 0000000000..13cb528c06 Binary files /dev/null and b/content/applications/studio/automated_actions/webhook-update-record.png differ diff --git a/content/applications/studio/automated_actions/webhooks.rst b/content/applications/studio/automated_actions/webhooks.rst index bd16143347..2cd4c9ad07 100644 --- a/content/applications/studio/automated_actions/webhooks.rst +++ b/content/applications/studio/automated_actions/webhooks.rst @@ -7,280 +7,278 @@ Webhooks role when deciding to use webhooks and throughout the implementation process. If not properly configured, webhooks may disrupt the Odoo database and can take time to revert. -Webhooks, which can be created in **Studio**, are automation rules triggered by external events via -user-defined HTTP callbacks. When an external system sends data to an Odoo webhook's URL (the -"trigger") with a data file (the "payload"), Odoo responds with a predefined action in the database. +Webhooks, which can be created in **Odoo Studio**, allow you to automate an action in your Odoo +database when a specific event occurs in another, external system. -Unlike scheduled actions or manual API calls, webhooks enable real-time communication and -automation. For example, if a sales order is confirmed in an external POS system, a webhook can -instantly update Odoo's inventory, ensuring system synchronization. +In practice, this works as follows: when the event occurs in the external system, a data file (the +"payload") is sent to the Odoo webhook's URL via a `POST` API request, and a predefined action is +performed in your Odoo database. -.. note:: - This article covers creating a webhook that *takes in* data from an external source. However, - an automated action that :ref:`sends an API call to an external webhook - ` can also be created. - -Create a webhook in Studio -========================== +Unlike scheduled actions, which run at predefined intervals, or manual API requests, which need to +be explicitly invoked, webhooks enable real-time, event-driven communication and automation. For +example, you can set up a webhook to have your Odoo inventory data updated automatically when a +sales order is confirmed in an external point-of-sale system. -Webhooks are configured in **Studio**, and their setup is split between their :ref:`trigger -` and their :ref:`actions `. +Setting up a webhook in Odoo requires no coding when connecting two Odoo databases, but +:ref:`testing a webhook ` requires an external tool. +:ref:`Custom target records or actions ` may require programming +skills. -.. tip:: - - Setting up a webhook in Odoo requires no coding when connecting Odoo databases, but testing - requires an external tool like `Postman `_. :ref:`Custom target - records or actions ` may require programming skills. - - :ref:`Activate developer mode ` to modify the model targeted by the webhook - (e.g., sales orders or contact information) and to find the model's technical name (which may be - required for proper payload configuration). - -.. _studio/webhooks/webhook_trigger: +.. note:: + This article covers creating a webhook that *receives* data from an external source. However, + it is also possible to create an automated action that :ref:`sends data to an external webhook + ` when a change occurs in your Odoo database. -Set the webhook's trigger -------------------------- +.. _studio/webhooks/create-webhook: -To create a webhook with **Studio**, :ref:`open Studio `, click :guilabel:`Webhooks`, -then :guilabel:`New`. From here, name the webhook, modify the webhook's model (the kind of database -entry to be targeted) if needed, and toggle whether calls made to the webhook URL should be logged -(which would track the webhook's call history for troubleshooting). +Create a webhook in Odoo +======================== -The webhook's URL is automatically generated. This is the URL that should be used for testing the -webhook and connecting it to the external system that will send updates to the database. +.. important:: + Before implementing a webhook in a live database, configure and test it using a :ref:`duplicate + database ` to ensure the webhook performs as intended. -.. danger:: - The webhook's URL is **confidential** and should be treated with care. Sharing it online or - without caution can provide unintended access to the Odoo database. Click :guilabel:`Rotate - Secret` to change the URL if needed. +.. tip:: + :ref:`Activating developer mode ` before creating up a webhook gives greater + flexibility in selecting the :doc:`model <../models_modules_apps>` the automation rule + targets. It also allows you to find the technical name of the model and fields, which may be + needed to configure the payload. -Finally, if the system sending the webhook is not Odoo, adjust the :guilabel:`Target Record` actions -to look for the JSON record that is included in the API call's payload when the call is made to the -webhook's URL. If the system sending the webhook is an Odoo database, then make sure that the `id` -and `model` appear in the payload. + To find a model's technical name, with developer mode activated, hover over the model name and + then click :icon:`fa-arrow-right` :guilabel:`(Internal link)`. The technical name can be found in + the :guilabel:`Model` field. For example, a sales order webhook uses the *Sales + Order* model, but the technical name `sale.order` is used in the payload. -.. tip:: - Although the :guilabel:`Model` is set in Odoo, it is the model's technical name that must be - included in the payload. Hover over the model name, then click the :icon:`fa-arrow-right` - :guilabel:`(Internal link)` icon to find this technical name in the :guilabel:`Model` field. For - example, a sales order webhook uses the *Sales Order* model, but the technical name `sale.order` - is used in the payload. +To create a webhook in **Studio**, proceed as follows: -.. note:: - When creating a record in the Odoo database, the target record's default format should not be - used. Instead, use `model.browse(i)` or `model.search(i)`. +#. :ref:`Open Studio ` and click :guilabel:`Webhooks`, then :guilabel:`New`. +#. Give the webhook a clear, meaningful name that identifies its purpose. +#. If needed, and provided developer mode is activated, select the appropriate :guilabel:`Model` + from the dropdown. If developer mode is not activated, the automation rule targets the current + model by default. -.. _studio/webhooks/webhook_action: +#. The webhook's URL is automatically generated, but can be changed if needed by clicking + :guilabel:`Rotate Secret`. This is the URL that should be used when implementing the webhook in + the external system that will send updates to the database. -Set the webhook's action ------------------------- + .. warning:: + The URL is **confidential** and should be treated with care. Sharing it online or without + caution can provide unintended access to the Odoo database. If the URL is updated after the + initial implementation, make sure to update it in the external system. -To set a webhook's action while configuring a webhook, click :guilabel:`Add an action` under the -:guilabel:`Actions To Do` tab. Click the action's :guilabel:`Type` and set the fields as needed. +#. If desired, enable :guilabel:`Log Calls` to track the history of API requests made to the + webhook's URL, e.g., for troubleshooting purposes. -.. _studio/webhooks/test_webhook: +#. If the system sending the webhook is not Odoo, adjust the :guilabel:`Target Record` code to look + for the JSON record included in the payload when the API request is made to the webhook's URL. If + the system sending the webhook is an Odoo database, ensure that the `id` and `model` appear in + the payload. -Test the webhook ----------------- + If the webhook is used to create records in the Odoo database, use `model.browse(i)` or + `model.search(i)` instead of the default :guilabel:`Target Record` format. -.. note:: - Testing the webhook requires the webhook to be set up, a test payload to send to the webhook, and - an external tool or system to send the payload through a `POST` API request. Consider using a - tool like `Postman `_ so less technical skills are required. +#. Click :guilabel:`Add an action` in the :guilabel:`Actions To Do` tab to define the :ref:`actions + ` to be executed. +#. Before implementing the webhook in the external system, :ref:`test + ` it to ensure it works as intended. -If a message saying `200 OK` or `status: ok` gets returned during testing, then the webhook is -functioning properly on Odoo's side. From here, implementation can begin with the other tool to -automatically send those webhook calls into Odoo using the webhook's URL. +.. tip:: + - Webhooks can also be created via the :guilabel:`Automations` menu in **Studio** by selecting + the trigger :guilabel:`On webhook`. + - To access the history of API requests if :guilabel:`Log Calls` has been enabled, click the + :guilabel:`Logs` smart button at the top of the :guilabel:`Automation rules` form. + - If the purpose of the webhook is anything other than to update an existing record, e.g., to + create a new record, the :guilabel:`Execute Code` action must be chosen. -If any other responses are returned, the number sent in the response helps to identify the problem. -For example, a `500 Internal Server Error` means that Odoo could not interpret the call properly. If -this gets returned, ensure the fields found in the JSON file are properly mapped in the webhook's -configuration and in the system sending the test call. Turning on call logging in the webhook's -configuration provides error logs if the webhook is not functioning as intended. +.. _studio/webhooks/test-webhook: -Implement the webhook ---------------------- +Test a webhook +============== -Once the webhook is fully configured, begin connecting it to the system that sends data to the Odoo -database through this webhook. Make sure that the API calls are sent to the webhook's URL when -setting that system up. +Testing a webhook requires a test payload and an external tool or system, like +`Postman `_, to send the payload via a `POST` API request. This section +presents the steps to test a webhook in Postman. -.. _studio/webhooks/webhook_examples: +.. tip:: + - See the :ref:`webhook use cases section ` for step-by-step + explanations of how to test webhooks using test payloads. + - To get specific help with testing a webhook with Postman, contact their support team. -Webhook use cases -================= +#. In Postman, create a new HTTP request and set its method to :guilabel:`POST`. +#. Copy the webhook's URL from your Odoo database using the :icon:`fa-link` :guilabel:`(link)` icon + and paste it into the URL field in Postman. +#. Click the :guilabel:`Body` tab and select :guilabel:`raw`. +#. Set the file type to :guilabel:`JSON`, then copy the code from the test payload and paste it into + the code editor. +#. Click :guilabel:`Send`. -Below are two examples of how to use webhooks in Odoo. These webhooks require external tools (which -are listed with the example). +.. _studio/webhooks/test-webhook-response: -.. warning:: - Consult with a developer, solution architect, or another technical role when deciding to - implement webhooks. If not properly configured, webhooks may disrupt the Odoo database and can - take time to revert. +In the :guilabel:`Response` viewer at the bottom of the screen in Postman, details, including a HTTP +response code, indicate whether or not the webhook is functioning correctly. -Update a sales order's currency -------------------------------- +- A `200 OK` or `status: ok` message indicates that the webhook is functioning properly on Odoo's + side. From here, implementation can begin with the other system to automatically send the API + requests to the Odoo webhook's URL. -This webhook updates a sales order in the **Sales** app to USD. It useful for subsidiaries outside -the United States with a mother company located inside the United States or during mergers when -consolidating data into one Odoo database. - -Set the webhook's trigger -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To set up this webhook, open the **Sales** app. Then, :ref:`set the trigger -` so the :guilabel:`Model` is set to `Sales Order`. Also, set -the :guilabel:`Target Record` to `model.env[payload.get('model')].browse(int(payload.get('id')))`. -This is broken down below. - -- **model**: what gets updated in Odoo (in this case, sales orders). This matches the - :guilabel:`Model` set earlier. -- **env**: where the action takes place. In this case, it is Odoo. -- **payload**: what is sent to the webhook's URL. This contains the information that updates - the sales order. -- **get('model')**: tells the webhook what database record to look at. In this case, the - webhook retrieves (`get`) the data tied to a specific `model`. In this example, this is the - Sales Order model. -- **browse**: tells the webhook to look in the `model` (Sales Order) set by the payload for what to - update. -- **int**: turns the target into an `integer` (a whole number). This is important in case some - words (a `string`) or a decimal number is included in the payload's target record. -- **get('id')**: identifies the sales order number that is being updated in Odoo. - -Set the webhook's action -~~~~~~~~~~~~~~~~~~~~~~~~ - -After setting the trigger, set the webhook's action by clicking :guilabel:`Add an action`. For the -:guilabel:`Type`, click :guilabel:`Update Record`. Then, select `Update`, choose the field -`Currency`, and select `USD` to have the currency field updated to USD. Finally, click -:guilabel:`Save & Close`. - -Webhook setup summary -~~~~~~~~~~~~~~~~~~~~~ - -To summarize what is set up, the webhook targets sales orders, identified by their sales order -number, and updates their currency to `USD` when a POST request is sent to the webhook's URL that -includes that sales order number (which is identified by the payload's `id` record). +- If any other response is returned, the number associated with it helps to identify the problem. + For example, a `500 Internal Server Error` message means that Odoo could not interpret the call + properly. In this case, ensure the fields found in the JSON file are properly mapped in the + webhook's configuration and in the system sending the test call. -Test the webhook -~~~~~~~~~~~~~~~~ +.. tip:: + Turning on call logging in the webhook's configuration in Odoo provides error logs if the webhook + is not functioning as intended. -Test the webhook's setup to make sure everything is correct. This process uses a tool called -`Postman `_ to send the simulated trigger. +Implement a webhook in an external system +========================================= -This section walks through the steps to test this webhook in Postman, but does not offer help if -there's an issue within that tool. To get specific help with Postman, contact their support team. +When the webhook has been successfully created in Odoo and tested, implement it in the system that +sends data to the Odoo database, making sure the `POST` API requests are sent to the webhook's URL. -Once Postman is open, create a new :guilabel:`HTTP` request and set its method to :guilabel:`POST`. -Next, copy the webhook's URL that is being tested and paste it into the URL field in Postman. After -that, click the :guilabel:`Body` tab and select the :guilabel:`raw` option. Set the file type to -:guilabel:`JSON`, then copy this code and paste it into the file. +.. _studio/webhooks/webhook-examples: -.. code-block:: json +Webhook use cases +================= - { - "model": "sale.order", - "id": "SALES ORDER NUMBER" - } +Below are two examples of how to use webhooks in Odoo. A test payload is provided for each example, +and can be found in the section on testing the webhook. `Postman `_ is +used to send the test payload. -From here, choose a sales order to test the webhook on. If it is not possible to test in a live -Odoo database, consider creating a demo database with a sample sales order and the webhook that was -configured. Replace `SALES ORDER NUMBER` with the sales order's number without the `S` or any zeros -before the number. For example, a sales order with the number `S00007` should be entered as `7` in -Postman. Finally, click :guilabel:`Send` in Postman. +Update a sales order's currency +------------------------------- -If a message saying `200 OK` or `status: ok` gets returned, then the webhook is functioning properly -on Odoo's side. The test sales order's currency is updated. From here, implementation can begin with -the other tool to automatically send those webhook calls into Odoo using the webhook's URL. +This webhook updates a sales order in the **Sales** app to `USD` when the external system sends a +`POST` API request to the webhook's URL that includes that sales order number (which is identified +by the payload's `id` record). -If any other responses are returned, the number associated with them helps to identify the problem. -For example, a `500 Internal Server Error` means that Odoo could not interpret the call properly. If -this gets returned, ensure the `model` and `id` fields are properly mapped in the webhook's -configuration and in Postman. +This could be useful for subsidiaries outside the United States with a mother company located inside +the United States or during mergers when consolidating data into one Odoo database. -.. _studio/webhooks/webhook-example: +Create the webhook +~~~~~~~~~~~~~~~~~~ -Create a new contact --------------------- +To create this webhook, proceed as follows: -This webhook uses custom code to create a new contact in an Odoo database. This could be helpful for -automatically creating new vendors or customers. +#. Open the **Sales** app, then :ref:`open Studio ` and click :guilabel:`Webhooks`. + The *Sales Order* model is selected by default. +#. Click :guilabel:`New`. The :guilabel:`Trigger` is set to :guilabel:`On webhook` by default. +#. Set the :guilabel:`Target Record` to + `model.env[payload.get('model')].browse(int(payload.get('id')))`, where: -Set the webhook's trigger -~~~~~~~~~~~~~~~~~~~~~~~~~ + - `payload.get('model')` retrieves the value associated with the `model` key in the payload, + i.e., `sale.order`, which is the technical name of the *Sales Order* model. + - `payload.get('id')` retrieves the value associated with the `id` key in the payload, i.e., + the number of the target sales order in your Odoo database with the `S` and leading + zeros removed. + - `int` converts the retrieved id to an integer (i.e., a whole number) because the method + `browse()` can only be used with an integer. -To set up this webhook, open the **Contacts** app. Then, :ref:`set the trigger -` so the :guilabel:`Model` is set to `Contact`. Also, set the -:guilabel:`Target Record` to `model.browse([2])`. This is broken down below. +#. Click :guilabel:`Add an action`. +#. In the :guilabel:`Type` section, click :guilabel:`Update Record`. +#. In the :guilabel:`Action details` section, select :guilabel:`Update`, choose the field + :guilabel:`Currency`, and select :guilabel:`USD`. +#. Click :guilabel:`Save & Close`. -- **model**: what gets updated in Odoo (in this case, a contact). This matches the :guilabel:`Model` - set earlier. -- **browse**: tells the webhook to look in the `model` (the contacts) set by the payload for - what to create. +Test the webhook +~~~~~~~~~~~~~~~~ -Set the webhook's action -~~~~~~~~~~~~~~~~~~~~~~~~ +To test this webhook, proceed as follows: -After setting the trigger, set the webhook's action by clicking :guilabel:`Add an action`. For the -:guilabel:`Type`, click :guilabel:`Execute Code`, then set the :guilabel:`code` to the sample code -below. Finally, click :guilabel:`Save & Close`. +#. With `Postman `_ open, create a new HTTP request and set its method to + :guilabel:`POST`. +#. Copy the URL of the Odoo webhook using the :icon:`fa-link` :guilabel:`(link)` icon and paste it + into the URL field in Postman. +#. Click the :guilabel:`Body` tab and select :guilabel:`raw`. +#. Set the file type to :guilabel:`JSON`, then copy this code, i.e., the payload, and paste it into + the code editor: -.. code-block:: python + .. code-block:: json - # variables to retrieve and hold data from the payload - contact_name = payload.get('name') - contact_email = payload.get('email') - contact_phone = payload.get('phone') + { + "model": "sale.order", + "id": "SALES ORDER NUMBER" + } - # a Python function to turn the variables into a contact in Odoo - if contact_name and contact_email: - new_partner = env['res.partner'].create({ - 'name': contact_name, - 'email': contact_email, - 'phone': contact_phone, - 'company_type':'person', - 'customer_rank': 1, - }) - # an error message for missing required data in the payload - else: - raise ValueError("Missing required fields: 'name' and 'email'") +#. In your Odoo database, choose a sales order to test the webhook on. In the pasted code, replace + `SALES ORDER NUMBER` with the sales order's number without the `S` or any zeros before the + number. For example, a sales order with the number `S00007` should be entered as `7` in Postman. +#. Click :guilabel:`Send`. +#. Consult the :ref:`Response viewer ` in Postman to + determine whether or not the webhook is functioning properly. If a message other than `200 OK` or + `status: ok` is returned, the number associated with the message helps to identify the problem. +.. _studio/webhooks/webhook-example: -Webhook setup summary -~~~~~~~~~~~~~~~~~~~~~ +Create a new contact +-------------------- -To summarize what is set up, the webhook creates a contact when an API call is sent to the webhook's -URL that includes the contact's information. +This webhook uses custom code to create a new contact in an Odoo database when the external system +sends a `POST` API request to the webhook's URL that includes the contact's information. This could +be helpful for automatically creating new vendors or customers. + +Create the webhook +~~~~~~~~~~~~~~~~~~ + +To create this webhook, proceed as follows: + +#. Open the **Contacts** app, then :ref:`open Studio ` and click :guilabel:`Webhooks`. + The *Contact* model is selected by default. +#. Click :guilabel:`New`. The :guilabel:`Trigger` is set to :guilabel:`On webhook` by default. +#. Set the :guilabel:`Target Record` to `model.browse([2])`. This is essentially a placeholder as + the code in the automated action tells the webhook what needs to be retrieved from the payload + and in which model the record needs to be created. +#. Click :guilabel:`Add an action`. +#. In the :guilabel:`Type` section, click :guilabel:`Execute Code`. +#. Copy this code and paste it into the code editor in the :guilabel:`Code` tab of the + :guilabel:`Action details` section: + + .. code-block:: python + + # variables to retrieve and hold data from the payload + contact_name = payload.get('name') + contact_email = payload.get('email') + contact_phone = payload.get('phone') + + # a Python function to turn the variables into a contact in Odoo + if contact_name and contact_email: + new_partner = env['res.partner'].create({ + 'name': contact_name, + 'email': contact_email, + 'phone': contact_phone, + 'company_type':'person', + 'customer_rank': 1, + }) + # an error message for missing required data in the payload + else: + raise ValueError("Missing required fields: 'name' and 'email'") + +#. Click :guilabel:`Save & Close`. Test the webhook ~~~~~~~~~~~~~~~~ -Test the webhook's setup to make sure everything is correct. This process uses a tool called -`Postman `_ to send the simulated trigger. - -This section walks through the steps to test this webhook in Postman, but does not offer help if -there's an issue within that tool. To get specific help with Postman, contact their support team. - -Once Postman is open, create a new request, and set its method to :guilabel:`POST`. Next, copy the -webhook's URL that is being tested and paste it into the URL field in Postman. After that, click the -:guilabel:`Body` tab and click :guilabel:`raw`. Set the file type to :guilabel:`JSON`, then copy -this code and paste it into the file. - -.. code-block:: json - - { - "name": "CONTACT NAME", - "email": "CONTACTEMAIL@EMAIL.COM", - "phone": "CONTACT PHONE NUMBER" - } - -Replace the fields above with a new contact's information in Postman, and then click -:guilabel:`Send`. - -If a message saying `200 OK` or `status: ok` gets returned, then the webhook is functioning properly -on Odoo's side. The new test contact appears in the **Contacts** app. From here, implementation can -begin with the other tool to automatically send those webhook calls into Odoo using the webhook's -URL. - -If any other responses are returned, the number associated with them helps to identify the problem. -For example, a `500 Internal Server Error` means that Odoo could not interpret the call properly. If -this gets returned, ensure the fields found in the JSON file are properly mapped in the webhook's -configuration and in Postman. +To test this webhook, proceed as follows: + +#. In `Postman `_, create a new HTTP request and set its method to + :guilabel:`POST`. +#. Copy the URL of the Odoo webhook using the :icon:`fa-link` :guilabel:`(link)` icon and paste it + into the URL field in Postman. +#. Click the :guilabel:`Body` tab and select :guilabel:`raw`. +#. Set the file type to :guilabel:`JSON`, then copy this code, i.e., the payload, and paste it into + the code editor: + + .. code-block:: json + + { + "name": "CONTACT NAME", + "email": "CONTACTEMAIL@EMAIL.COM", + "phone": "CONTACT PHONE NUMBER" + } + +#. In the pasted code, replace the `CONTACT NAME`, `CONTACTEMAIL@EMAIL.COM`, and `CONTACT PHONE + NUMBER` with a new contact's information. +#. Click :guilabel:`Send`. +#. Consult the :ref:`Response viewer ` in Postman to + determine whether or not the webhook is functioning properly. If a message other than `200 OK` or + `status: ok` is returned, the number associated with the message helps to identify the problem.