Issue webhooks
Send signed issue, comment and project events from a team to an HTTPS endpoint, and verify each delivery's signature.
A webhook sends a JSON message to an address you choose when something happens to the issues or projects of Personal or the selected team. Team admins manage webhooks.
Create a webhook
Open Webhooks in the Issues section of the sidebar and choose Create webhook. Enter a name, the endpoint address and the events to send, then choose Save webhook. The address must use HTTPS and its host must resolve to a public address. Redirects are not followed.
After saving, the page shows the webhook's signing secret once. Choose Copy secret and store it where your endpoint can read it; Magpie shows only its last four characters after that.
| Event | Sent when |
|---|---|
issue.created |
An issue is created, including by a public form, the API or an import |
issue.updated |
An issue, its labels, links, attachments, comments or triage state change, or it is restored from Trash |
issue.completed |
An issue moves into a status in the Completed category |
issue.deleted |
An issue is moved to Trash |
comment.created |
Someone comments on an issue |
project.created |
A project is created |
project.completed |
A project's status is set to Completed |
Manage webhooks
The Webhooks page lists each webhook with its address, its events, whether it is enabled, the end of its signing secret and when it last delivered. Beside each one:
- Pause stops sending, and Enable starts again.
- Rotate secret makes a new signing secret and shows it once. The old secret stops working at once.
- Remove removes the webhook.
Choose a webhook's name to change its name, address, events or Enabled setting. Pausing or removing a webhook, or changing its address or events, cancels the deliveries still waiting to be sent to it.
What Magpie sends
Each delivery is an HTTPS POST with a JSON body:
{
"id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
"type": "issue.updated",
"created_at": "2026-10-15T09:30:00+00:00",
"data": {
"issue": {
"uuid": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"identifier": "WEB-14",
"title": "Checkout button does nothing",
"description_markdown": "Steps to reproduce...",
"status": "in_progress",
"priority": "high",
"assignee_user_id": 42,
"due_date": "2026-10-20",
"project": { "uuid": "a7f3c2d1-0b6e-4c8a-9e21-5d4b3c2a1f00", "name": "Website" },
"created_at": "2026-10-01 08:00:00",
"updated_at": "2026-10-15 09:30:00"
},
"team": { "id": 7, "name": "Acme" },
"actor": { "id": 42, "name": "Sam Lee" }
}
}
status is the status's key, not its display name. An issue.created event
also has source: internal, api, public_form or import. An
issue.deleted event has deleted_at, and a comment.created event has a
comment with its uuid, body_markdown and created_at. Project events
have a project with its uuid, name, identifier_prefix,
description_markdown, status, start_date and target_date in place of
issue.
Each request has these headers:
X-Magpie-Event: the event type.X-Magpie-Id: the event ID, the same asidin the body.X-Magpie-Timestamp: when this attempt was signed, in Unix seconds.X-Magpie-Signature:t=<timestamp>,v1=<hex digest>.
Verify a delivery
Before you use a delivery, compute an HMAC-SHA256 of the timestamp, a full
stop and the raw request body, using the signing secret as the key, and compare
it with the v1 value. Reject a request whose timestamp is older than you
allow. In PHP:
parse_str(str_replace(',', '&', $_SERVER['HTTP_X_MAGPIE_SIGNATURE']), $sig);
$expected = hash_hmac('sha256', $sig['t'] . '.' . $rawBody, $secret);
$valid = hash_equals($expected, $sig['v1']) && abs(time() - (int) $sig['t']) < 300;
Retries
Events are queued when the change is made and sent by a background job. A response with a 2xx status counts as delivered. After a failure, Magpie tries again with increasing delays, up to 5 attempts in all, and then stops. A retry keeps the same event ID, so the same event can arrive more than once; store the IDs you have handled and skip repeats.
For help with webhooks, Contact support.
Ask Magpie support
Send Magpie staff a question about anything this article does not answer.