Working with BILL webhooks

When you set up a subscription for your choice of BILL events, you receive real time event notifications when those events are triggered.

❗️

IMPORTANT

For organization-level users, BILL sends event notifications only for the BILL organization used to set up a subscription. When a subscription is set up, the organizationId in the API response represents the BILL organization for which the subscription is created.

When a partner user creates a subscription for events, event notifications for all organizations created by the partner user.

Subscribing to BILL events

BILL provides a catalog of all events that you can subscribe to with GET /v3/events/catalog. See the /v3/events/catalog API for more information.

To create a subscription with POST /v3/subscriptions, set the required fields.

FieldDescription
nameSubscription name
statusSubscription status information. Set enabled as true for keeping the subscription enabled. You can use the field to disable the subscription at a later time.

When an event notification fails, BILL tries to send the notification again with exponential backoff. When BILL does not receive a HTTP 200 statusCode after resending a notification even after exponential backoff, BILL sets the subscription enabled status as false and stops sending any notifications.

The enabled status stays as false until the problem is resolved at your end and until the enabled status is set as true again.
eventsIn the events array, add events that you can subscribe to.

- type: Event name
- version: Event versionYou can get the full catalog of all events that you can subscribe to with GET /v3/events/catalog.
notificationUrlThe location where you receive event notifications. The URL that you provide must be HTTPS.

📘

NOTE

To create a subscription at the partner level, simply set your partner sessionId (with /v3/partner/login) and appKey as the required header values. The base URL and body parameters in the POST /v3/subscriptions request are the same for partner users and organization users.

Sample request

In this cURL example, a subscription is created for the bill.created, bank.updated, and bill.archived events. The required X-Idempotent-Key, devKey, and sessionId header values are set. A notificationUrl is set as the location URL for you to receive event notifications when any of the subscribed events is triggered.

📘

NOTE

When you are testing with BILL webhooks, you can use an online service for setting up a notification URL. For example, public.requestbin.com.

curl --request POST \
--url 'https://gateway.stage.bill.com/connect-events/v3/subscriptions' \
--header 'content-type: application/json' \
--header 'X-Idempotent-Key: {UUID4_key}' \
--header 'devKey: {developer_key}' \
--header 'sessionId: {session_id}' \
--data '{
  "name": "Bill management",
  "status": {
    "enabled": true
  },
  "events": [{
    "type": "bill.created",
    "version": "1"
  },
  {
    "type": "bill.updated",
    "version": "1"
  },
  {
    "type": "bill.archived",
    "version": "1"
  }],
  "notificationUrl": "https://example.com/billmanagement"
}'

Response

In the response, a BILL-generated subscription id is available. The organizationId represents the BILL organization for which your subscription is created. BILL sends you event notifications only for the BILL organization used to set up this subscription.

{
  "id": "{subscription_id}",
  "name": "Bill management",
  "organizationId": "{organization_id}",
  "status": {
    "enabled": true,
    "reason": "Notifications for bill-related events",
    "actor": "CLIENT"
  },
  "events": [{
    "type": "bill.created",
    "version": "1"
  },
  {
    "type": "bill.updated",
    "version": "1"
  },
  {
    "type": "bill.archived",
    "version": "1"
  }],
  "notificationUrl": "https://example.com/billmanagement",
  "createdTime": "2024-12-10T23:25:27.127+00:00",
  "securityKey": "{security_key}"
}

When you create a new subscription, a one-time securityKey is one of the generated values in the response. All event notifications sent to your notificationUrl are signed with this key using the HMAC-SHA256 algorithm. The key is sent as the x-bill-sha-signature header value in the notification.

📘

NOTE

You can use the security key to verify all notifications sent to you. It is good practice to keep the security key for your subscription updated in a timely manner. You can generate a new security key for your subscription with POST /v3/subscriptions/{subscriptionId}/security-key.

See the /v3/subscriptions API for more information about the complete list of subscription operations.

Generating a test subscription event

When you set up a subscription, you can generate a test event with POST /v3/subscriptions/{subscriptionId}/test.

You can use this endpoint to confirm whether the your subscription and notifications workflow has been successfully set up. BILL sends you a test event notification to the specified subscription notificationUrl.

❗️

IMPORTANT

All the fields in the test event notification are test values. You cannot use any of the test values for any other operation.

Sample response

In this response example, a test event notification is available. The JSON-escaped payload is presented as a string.

{
    "id": "{event_id}",
    "type": "test",
    "version": "1",
    "subscriptionId": "{subscription_id}",
    "payload": "{\"metadata\":{\"eventId\":\"{event_id}\",
        \"subscriptionId\":\"{subscription_id}\",\"organizationId\":\"{organization_id}\",
        \"eventType\":\"test\",\"version\":\"1\"},
        \"payload\":{\"createdDate\":\"2024-12-15T23:15:27.127+00:00\"}}",
    "createdTime": "2024-12-15T23:15:27.127+00:00",
    "statusCode": 200
}

Getting events for a subscription

You can get the list of event notifications sent to you for a subscription with GET /v3/events/subscription/{subscription_id}.

📘

NOTE

You can also resend a specific event with POST /v3/events/subscription/{subscriptionId}/event/{eventId}.

Sample response

In this response example, an array of event objects are available along with a BILL-generated event id. Each event object represents the notification that BILL sends to your notificationUrl when the event is triggered. The JSON-escaped payload of each event notification is presented as a string.

[
   {
      "id": "{event_id1}",
      "type": "bill.created",
      "version": "1",
      "subscriptionId": "{subscription_id}",
      "payload": "{\"metadata\": {\"eventId\": \"{event_id1}\",
          \"subscriptionId\": \"{subsrciption_id}\", \"organizationId\": \"{organization_id}\",
          \"eventType\": \"bill.created\", \"version\": \"1\"}, \"bill\": {\"id\": \"{bill_id1}\",
          \"vendorId\": \"{vendor_id}\", \"invoiceNumber\": \"202401\",
          \"invoiceDate\": \"2024-12-16T00:00:00.127+00:00\", \"amount\": 228.99,
          \"createdDate\": \"2024-12-15T23:15:23.127+00:00\", \"archived\": false}}"
      "createdTime": "2024-12-15T23:15:27.127+00:00",
      "statusCode": 200
   },
   {
      "id": "{event_id2}",
      "type": "bill.created",
      "version": "1",
      "subscriptionId": "{subscription_id}",
      "payload": "{\"metadata\": {\"eventId\": \"{event_id2}\",
          \"subscriptionId\": \"{subsrciption_id}\", \"organizationId\": \"{organization_id}\",
          \"eventType\": \"bill.created\", \"version\": \"1\"}, \"bill\": {\"id\": \"{bill_id2}\",
          \"vendorId\": \"{vendor_id}\", \"invoiceNumber\": \"202402\",
          \"invoiceDate\": \"2024-12-16T00:00:00.127+00:00\", \"amount\": 149,
          \"createdDate\": \"2024-12-15T23:17:31.127+00:00\", \"archived\": false}}"
      "createdTime": "2024-12-15T23:17:35.127+00:00",
      "statusCode": 200
   }
]

📘

NOTE

The HTTP 200 statusCode informs BILL that the event notification was successfully sent to your notificationUrl.

In the next section, we list examples of the BILL webhook notification payloads in the Notification payloads reference.