A webhook triggers a HTTP POST request on the specified url, whenever there is a change in an event. Like a new project is created, updated or deleted then a webhook can be triggered to receive the required payload.

Creating a webhook

url You are required to provide a url in which you want the payloads to be triggered.

Then select the events for which you want the webhook to be triggered.

After you create the webhook, a secret key will be created automatically and will be downloaded in csv format.

Webhook Header

"Content-Type": "application/json",
"User-Agent": "Autopilot",
"X-Plane-Delivery": "f819eff4-cd50-4987-bc97-e5be1e04c94f",
"X-Plane-Event": "project",
"X-Plane-Signature": "7896ae9addb1f73931132b4f3e052bf12c410b837b24898e75dcd660c7"
X-Plane-DeliveryIt is a randomly generated UUID for uniquely identifying the payload
X-Plane-EventIt describes the event for which the webhook triggered
X-Plane-SignatureA signature is generated based on the secret and the payload

Webhook Payload Example for the project update

"event": "project",
"action": "update",
"webhook_id": "3c2c32ac-82df-48b3-be2a-a3e21dbe8692",
"workspace_id": "d2d97c94-a6ad-4012-b526-5577c0d7c769",
"data": {
    "workspace_detail": {
        "name":"Testing Project",

User can choose the things for which they want the webhook to be triggered.

Currently Plane supports the following events for which webhook can be trigged:

  • Project
  • Issue
  • Cycle
  • Module
  • Issue Comment

Verifying Signature

import hashlib
import hmac

secret_token = os.environ.get("WEBHOOK_SECRET")

received_signature = request.headers.get('X-Plane-Signature')
received_payload = json.dumps(request.json).encode('utf-8')

expected_signature = hmac.new(secret_token.encode('utf-8'), msg=received_payload, digestmod=hashlib.sha256).hexdigest()

if not hmac.compare_digest(expected_signature, received_signature):
   raise HTTPException(status_code=403, detail="Invalid Signature provided")

How webhook works

Your webhook consumer is a simple HTTP endpoint. It must satisfy the following conditions:

  • It's available in a publicly accessible non-localhost URL.
  • It will respond to the Plane Webhook push (HTTP POST request) with a HTTP 200 ("OK") response.

If a delivery fails (i.e. server unavailable or responded with a non-200 HTTP status code), the push will be retried a couple of times. Here an exponential backoff delay is used: the attempt will be retried after approximately 10 minutes, then 30 minutes, and so on.

The webhooks are triggered for POST, PATCH, and DELETE requests.

  • For DELETE requests, the response only includes the ID of the deleted entity.
  • However, for both POST and PATCH requests, the complete payload is sent in the response.
"data":{ ... }

Note:- Whenever an issue is added to the module, the corresponding issue webhook will be triggered. Similarly, any updates made to the cycle issue will also activate the issue webhook.

Inbox Issue