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.

"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 ='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.