When webhooks are triggered in the gateway, a notification is sent as a POST request to the specified destination URL. The post body contains two x-www-form-urlencoded parameters:

  • bt_signature
  • bt_payload

This payload is signed to ensure that the message originated from Braintree and was not modified in transit. The message is identical to standard API responses and contains a snapshot of the related entity at the time the webhook was triggered.

These parameters should be passed to the gateway.webhook_notification.parse. The result will be a WebhookNotification object consisting of:

  • A timestamp (in UTC)
    • Tip: Notifications may not be delivered sequentially, so be sure to look at the timestamp of the event.
  • A kind (directly mapped to triggers)
  • A standard Braintree object, depending on the type of notification (e.g. a subscription object for recurring billing webhooks)
    • Tip: Save webhook data to your database for reporting purposes or use it to trigger other actions in your app

Import the Response library at the beginning of app.py to respond with a 200 HTTP response code after receiving a notification.

from flask import Flask, request, render_template, Response

Then update the webhook route to the following:

def webhook():
    webhook_notification = gateway.webhook_notification.parse(str(request.form['bt_signature']), request.form['bt_payload'])

    # Example values for webhook notification properties
    print(webhook_notification.kind) # "subscription_went_past_due"
    print(webhook_notification.timestamp) # "Sun Jan 1 00:00:00 UTC 2012"

    return Response(status=200)


An invalid signature exception is raised if the webhook notification you attempt to parse has an invalid signature.


If a webhook takes longer than 30 seconds to respond, it is considered a timeout and will be retried. We will resend webhook notifications every hour for up to 3 hours in sandbox, or up to 24 hours in production, until the webhook responds with a successful HTTPS response code (i.e. ‘2xx’) within 30 seconds.

Next Page: Testing and Go Live →