Documentation › Configure

Chat notifications

Post build results, deploys, backup failures and downtime to Slack, Discord, Microsoft Teams or your own endpoint.

Project admins add channels in Settings → Chat notifications : pick the service, paste its webhook URL and tick the events to post. Each message says what happened and links to the build (branch, stage, commit, author and duration). Use Send test to check the channel; the last delivery and its error, if any, are shown under each channel.

Build failed / succeeded Any stage. Failed tests count as a failure. Successes are off by default: every push would post.

Production deployed A new production build is live, with its address.

Backup failed A daily backup failed (once, until one works again) or the weekly restore test failed.

Production down / back up The same incidents as the downtime alerts, with the downtime once it recovers. Project moves too.

Slack

Create an incoming webhook In Slack, add the Incoming Webhooks app (or open your own Slack app → Incoming Webhooks → Add New Webhook to Workspace ) and pick the channel.

Copy the Webhook URL It starts with https://hooks.slack.com/services/ . Paste it in the project's settings with Slack selected.

Discord

Create a webhook Channel settings → Integrations → Webhooks → New Webhook .

Copy the Webhook URL It starts with https://discord.com/api/webhooks/ . Mentions in commit messages (such as @everyone) never ping anyone.

Microsoft Teams

Add a workflow to the channel In the channel, … → Workflows , then the template Post to a channel when a webhook request is received .

Copy the URL it shows It is on logic.azure.com or powerplatform.com . The older connector URLs on webhook.office.com work too, while Microsoft keeps them running.

Your own endpoint (webhook)

Any HTTPS endpoint receives a POST with a JSON body:

Payload

{

"event": "build_failed",

"project": {"id": 1, "name": "Acme ERP", "slug": "acme"},

"branch": "feature-invoicing",

"stage": "development",

"build": {"id": 42, "status": "failed", "commit": "abcdef1…", "commit_message": "…", "author": "…",

"duration_s": 185, "url": "https://…/projects/1/branches/7?tab=logs&build=42", "app_url": ""},

"title": "feature-invoicing: build failed",

"text": "…",

"url": "https://…",

"occurred_at": "2026-09-25T08:14:00+00:00"

}

Events: build_failed , build_succeeded , deployed , backup_failed , production_down , production_up , move_done , move_failed , upgrade_done , upgrade_failed , maintenance_done (and test from Send test ). The secret is shown once, when you add the endpoint. Each request carries X-OdooCloud-Signature: sha256=<hex> , the HMAC-SHA256 of the raw body with that secret, and X-OdooCloud-Event . Check it before trusting the payload:

Python

import hashlib, hmac

def valid(secret: str, body: bytes, header: str) -> bool:

expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()

return hmac.compare_digest(expected, header)

Delivery

Messages are sent in the background: a slow or unreachable channel never delays a build. Each gets 5 seconds and one retry.

Redirects are not followed. Only public HTTPS addresses are accepted: private, local and the platform's own addresses are refused.

The URL is kept encrypted and never shown again; only its host and last characters are. To change it, remove the channel and add it again.