Setting up webhooks

The BillForward REST API gives the ability to create, update and access your billing data.

Webhooks and notifications notify you of billing events that occur, without need to poll the API.

For example
A subscription has entered a dunning period and failed to be paid.
A notification will be sent out notifying any listeners of the failed payment.
Webhook API documentation 

Adding Endpoints

Webhooks represent HTTP(S) endpoints which are notified when a billing event occurs. Endpoints can be configured using either the BillForward UI, or the REST API.

Your webhook endpoint needs to be publicly addressable, to protected your end-point a number of approaches can be made to protect the receiving URL from being called by 3rd parties:

  • Add HTTP basic authentication to your end-point URL.
    • For example: https://[username]:[password]@app.acme.inc/handle/billforward/webhook`
  • Confirm the Webhook data by calling the BillForward API
  • Generate a seed as part of the URL. Note this is security by obfuscation, and not recommended.
    • For example: https://app.acme.inc/handle/billforward/webhook?my_random_seed_number_24557fe7-74af-4370-8ed9-4cc3ca2de5fa

CSRF-protected servers

A number of webhooks use CSRF tokens to provide protection against cross-site request forgery. The web server automatically checks to see if there is a CSRF token in the POST request body. This protection may stop a valid BillForward Webhook notification from being received. We suggest disabling CSRF for our webhook.

Rails

    class BillForwardController < ApplicationController
      # If your controller accepts requests other than BillForward webhooks,
      # you'll probably want to use `protect_from_forgery` to add CSRF
      # protection for your application. But don't forget to exempt
      # your webhook route!
      protect_from_forgery :except => :webhook

      def webhook
        # Process webhook data in `params`
      end
    end

Django

    import json

    # Webhooks are always sent as HTTP POST requests, so we want to ensure
    # that only POST requests will reach your webhook view. We can do that by
    # decorating `webhook()` with `require_POST`.
    #
    # Then to ensure that the webhook view can receive webhooks, we need
    # also need to decorate `webhook()` with `csrf_exempt`.
    @require_POST
    @csrf_exempt
    def webhook(request):
      # Process webhook data in `request.body`

Codeigniter

    //Configure this in your config.php
    //There are a number of alternate examples provided discussed here:
    //https://ellislab.com/forums/viewthread/182631/
    if (isset($_SERVER["REQUEST_URI"]))
    {
        if(stripos($_SERVER["REQUEST_URI"],'/mypage') === FALSE)
        {
            $config['csrf_protection'] = TRUE;
        }
        else
        {
            $config['csrf_protection'] = FALSE;
        }
    }
    else
    {
        $config['csrf_protection'] = TRUE;
    }

Handing Webhooks

When BillForward sends a Notification to your webhook, a HTTP 200 code should be returned. Any data other than HTTP Response code returned in the response will be ignored.

A response code other than 200 will result in the notification’s state being marked as Sending, and it will be subsequently scheduled for a re-send.

The number of times a notification is re-sent is defined by the Notification dunning lines, these can be configured via UI (Setup -> Webhooks) or via the API.

Webhook Dunning API documentation 

Developing with Webhooks

As webhook notifications must be sent to a publicly-accessible endpoint, it can prove tricky to test the full development flow without a public IP. Luckily, various services provide reverse-HTTP tunnels. These can send HTTP requests directly to your local machine!

A number of useful utilities include:

Back-off strategy

If your webhook endpoint stops responding Billforward will follow the backoff schedule, where for example, after 16 consecutive attempts to contact your webhook endpoint end in failure Billforward will pause attempts for 5 minutes. When the webhook is paused, notifications are still created but are scheduled to be sent when the pause period ends.

Following is the full schedule:

Failed consecutive attemptsWill pause for
165 minutes
3215 minutes
6460 minutes
12824 hours
25672 hours
512delete the webhook

Was this article helpful?
YesNo