Skip to content

Webhooks

Webhooks provide a way for notifications to be delivered to an external web server whenever certain events occur on GitHub. See the GitHub Webhooks Documentation for more information.

Webhook Verification

GitHub always sends a signature in the headers of the webhook request. You can verify the signature to ensure that the webhook request is from GitHub. See the GitHub Docs - Validating webhook deliveries for more information.

githubkit provides a verify function to help you verify the webhook payload. Note that you should provide the raw request body to ensure the integrity of the payload. For example:

from githubkit.webhooks import verify

valid: bool = verify(secret, request.body, request.headers["X-Hub-Signature-256"])

Note

The verify function is time-constant. This is to prevent timing attacks.

Warning

The verify function also supports the X-Hub-Signature header. GitHub recommends that you use the X-Hub-Signature-256 header, which uses the HMAC-SHA256 algorithm. The X-Hub-Signature header uses the HMAC-SHA1 algorithm and is only included for legacy purposes.

You can also use the sign function to generate the signature for the payload. For example:

from githubkit.webhooks import sign

signature: str = sign(secret, payload, method="sha256")

Webhook Event Parsing

You can use githubkit to validate the webhook payload and convert it into a Pydantic model. githubkit provides a parse function and the function accepts the event name and the raw request body. For example:

from githubkit.webhooks import parse

event = parse(request.headers["X-GitHub-Event"], request.body)

(NOT RECOMMENDED) If you do not have the event name, you can use the parse_without_name function. This function will try to parse the payload with all supported event names. This will cost longer time, more memory and may return the wrong event type. For example:

from githubkit.webhooks import parse_without_name

event = parse_without_name(request.body)

Tip

The behavior of function parse_without_name is not the same between pydantic v1 and v2.

When using pydantic v1, the function will return the first valid event model (known as left-to-right mode).

When using pydantic v2, the function will return the highest scored valid event model (known as smart mode).

See: Union Modes.

If you want to parse the payload as a dict, you can use the parse_obj function. For example:

from githubkit.webhooks import parse_obj, parse_obj_without_name

event = parse_obj(request.headers["X-GitHub-Event"], request.json())
event = parse_obj_without_name(request.json())  # NOT RECOMMENDED

Note

The parse and parse_obj function supports type overload, if you provide static value for the event_name parameter, the return type will be inferred automatically.

Webhook Versioning

Usually, you don't need to specify the version of the webhook payload. githubkit uses the latest version by default. If you want to use a specific version (including GHEC), you can switch between versions as follows:

from githubkit import GitHub

event = GitHub.webhooks("2022-11-28").parse(request.headers["X-GitHub-Event"], request.body)