Webhooks
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.
"Content-Type": "application/json",
"User-Agent": "Autopilot",
"X-Plane-Delivery": "f819eff4-cd50-4987-bc97-e5be1e04c94f",
"X-Plane-Event": "project",
"X-Plane-Signature": "7896ae9addb1f73931132b4f3e052bf12c410b837b24898e75dcd660c7"
Header | Description |
---|---|
X-Plane-Delivery | It is a randomly generated UUID for uniquely identifying the payload |
X-Plane-Event | It describes the event for which the webhook triggered |
X-Plane-Signature | A 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": {
"id":"22b6fc9c-1849-45da-b103-52a3e3a6b4c1",
"workspace_detail": {
"name":"Testing Project",
"slug":"testing-project",
"id":"bob1b192-f988-4bf9-b569-825de8cb0678"
},
"created_at":"2023-10-25T04:38:59.566962Z",
"updated_at":"2023-10-25T06:44:48.543685Z",
"name":"vfecddcwerj",
"description":"",
"description_text":null,
"description_html":null,
"network":2,
"identifier":"TRACE",
"emoji":null,
"icon_prop":null,
"module_view":true,
"cycle_view":true,
"issue_views_view":true,
"page_view":true,
"inbox_view":true,
"cover_image":null,
"archive_in":0,
"close_in":0,
"created_by":"6bb20d1c-4960-41ca-af4f-cee01de160c4",
"updated_by":"6bb20d1c-4960-41ca-af4f-cee01de160c4",
"workspace":"bob1b192-f988-4bf9-b569-825de8cb0678",
"default_assignee":null,
"project_lead":null,
"estimate":null,
"default_state":null
},
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.
"action":"delete",
"data":{
"id":"9a28bd00-ed9c-4f5d-8be9-fc05cbb1fc57"
},
"event":"issue",
"webhook_id":"f1a2fe64-c8d4-4eed-b3ef-498690052c1d",
"workspace_id":"c467e125-59e3-44ec-b5ee-f9c1e138c611"
- However, for both POST and PATCH requests, the complete payload is sent in the response.
"event":"issue",
"action":"update",
"webhook_id":"f1a2fe64-c8d4-4eed-b3ef-498690052c1d",
"workspace_id":"c467e125-59e3-44ec-b5ee-f9c1e138c611",
"data":{ ... }