Webhooks
Webhooks let external systems trigger custom logic in Cetmix Tower by sending HTTP requests to a configurable URL. Each webhook has an endpoint path, an Authenticator (for IP allowlisting and optional custom authentication), and Python code that runs when the request is received. The response and each call are logged.
The full URL of a webhook is: <your_tower_url>/cetmix_tower_webhooks/<endpoint>. Requests must use the HTTP method (GET or POST) configured on the webhook. POST payloads can be JSON or form URL-encoded.
Module
Webhooks are provided by the Cetmix Tower Webhook module (cetmix_tower_webhook). The Webhooks and Webhook Authenticators menus are visible only to Root users.
Access Rules
| Group | Webhook / Authenticator | Webhook Log |
|---|---|---|
| Root | CRUD | R (read-only) |
Only users in the Root group can create, read, update, or delete Webhooks and Webhook Authenticators. Webhook call logs are read-only for Root.
Info
CRUD stands for Create, Read, Update, Delete.
Webhook Configuration
Webhooks are under Settings > Automation > Webhooks (Cetmix Tower menu).
Main settings
| Field | Description |
|---|---|
| Name | Display name of the webhook. |
| Reference | Used for Odoo automation and YAML export/import. Leave blank to generate automatically. |
| Enabled | If unchecked, the webhook is disabled and requests to its URL return 404. |
| Authenticator | Webhook Authenticator used for this webhook (required). IP allowlist and custom auth are defined there. |
| Endpoint | URL path segment. Must start and end with a letter or digit; may contain letters, digits, underscores, dashes, and slashes. Combined with method, must be unique. |
| Full URL | Computed full URL (copy button). Format: https://your-domain/cetmix_tower_webhooks/<endpoint>. |
| Method | POST or GET. Incoming request method must match. |
| Payload Type | For POST: JSON or Form URL-Encoded. How the request body is parsed. Hidden for GET. |
| Run as User | Odoo user as which the webhook code runs. Defaults to Administrator. Use with care. |
| Variables | Configuration Variables (Manager/Root). Shown when linked. |
| Secrets | Secrets/Keys (Manager/Root). Shown when linked. |
Code and Help
- Code tab: Python code executed when the webhook is called. You must set a
resultdictionary with: exit_code(int, default 0): 0 = success, other = failure.message(str, optional): Message returned in the HTTP response and stored in the log.- Help tab: Lists variables available in the code (e.g.
payload,headers). Same Odoo objects and libraries as in Commands, exceptserveris not available. - YAML tab: Export webhook definition as YAML.
Logs button: opens call logs for this webhook.
Webhook Authenticator
Webhook Authenticators are under Settings > Automation > Webhook Authenticators. Each webhook must use one authenticator. The authenticator:
- IP allowlist — Optionally restrict which client IPs can call webhooks using this authenticator (comma-separated IPs and/or CIDR ranges, e.g.
192.168.1.10,10.0.0.0/24). Empty = allow all. - Trusted proxy IPs — Comma-separated IPs/CIDR of trusted proxies. Only if the immediate connection comes from these,
X-Forwarded-For/X-Real-IPare used to determine the client IP for the allowlist check. - Python code — Optional custom authentication. Code can use
headers,raw_data,payload. It must setresultto a dict:allowed(bool, required), optionallyhttp_code(int),message(str). Ifallowedis False, the request is rejected (default HTTP 403).
Authenticators also have Code, Help, and YAML tabs; Variables and Secrets (Manager/Root); and a Logs button for calls that used this authenticator.
Request flow
- Request — Client sends GET or POST to
/cetmix_tower_webhooks/<endpoint>. - Match — Tower finds an active webhook with that endpoint and method. If none, response is 404 and a log entry is created.
- IP check — Authenticator’s allowlist is applied (if set). If the client IP is not allowed, response is 403 and the request is logged.
- Authenticator code — Authenticator’s Python code runs (if any). If it returns
allowed: False, response uses the code’shttp_code/messageand the request is logged. - Webhook code — Webhook’s Python code runs with
payloadandheaders. The code setsresultwithexit_codeandmessage. Non-zero exit code leads to HTTP 500 and the message in the response. - Log and response — A log record is created (webhook, endpoint, method, auth status, code status, HTTP status, IP, etc.). Client receives a JSON response:
{"message": "..."}.
Webhook call logs
Webhook Calls under the Logs menu lists all webhook invocations. Each log stores: webhook, endpoint, method, authentication status, webhook code status, HTTP status, request payload/headers, result or error message, client IP, country (if GeoIP is available), and “Run as” user.
Log retention is configured in Settings: number of days to keep webhook logs. Older logs are removed automatically by autovacuum (default 30 days).





