Test with BILL webhook security

In this section, we walk through the steps for validating the BILL webhook security measures.

When you create a new subscription, a one-time securityKey is one of the generated values in the response. BILL uses the HMAC-SHA256 algorithm to sign all event notifications sent to your notificationUrl with the securityKey. The output format of the generated hash value is base64.

The generated hash is sent as the x-bill-sha-signature header value with all event notifications. With this value, you can verify that each notification sent to you is from BILL.

Generate test notification URL

Use an online service for generating a test notification URL. For example, webhook.site or pipedream.com/requestbin. In the rest of this article, we refer to a webhook.site test notification URL.

Create test subscription

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

Create a test subscription for the bill.created event with POST /v3/subscriptions.

Sample request

In your request, set the required fields (name, status, events, and notificationUrl). Set notificationUrl as the generated notification URL in the previous step.

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": "Created bills",
  "status": {
    "enabled": true
  },
  "events": [{
    "type": "bill.created",
    "version": "1"
  }],
  "notificationUrl": "https://webhook.site/{unique_id}"
}'

Response

In the response, a BILL-generated subscription id is available. The organizationId represents the BILL organization for which your subscription is created. In addition, the one-time generated securityKey is available.

{
  "id": "{subscription_id}",
  "name": "Created bills",
  "organizationId": "{organization_id}",
  "status": {
    "enabled": true,
    "actor": "CLIENT"
  },
  "events": [{
    "type": "bill.created",
    "version": "1"
  }],
  "notificationUrl": "https://webhook.site/{unique_id}",
  "createdTime": "2025-12-10T23:25:27.127+00:00",
  "securityKey": "{security_key}"
}

Generate test event notification

Generate a test event notification with POST /v3/subscriptions/{subscriptionId}/test request. In your request, all the fields are optional. To see specific information in the test event notification, you can set eventType, version, and any details. You can get the BILL events catalog with GET /v3/events/catalog.

Sample response

In this response example, a test event notification is available. The JSON-escaped payload is presented as a string. You will receive such a response with you do not set any of the optional values in your POST /v3/subscriptions/{subscriptionId}/test request.

{
    "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\":\"2025-12-15T23:15:27.127+00:00\"}}",
    "createdTime": "2025-12-15T23:15:27.127+00:00",
    "statusCode": 200
}

On the webhook.site page, you see response header and body details of the test event notification.

  • Under Request Details & Headers, the x-bill-sha-signature value is the hash generated by BILL for the payload JSON value.
  • Under Request Content, the payload JSON is available. In the next step, we use the unformatted (minified) version of the payload JSON value.

Generate hash with the payload

In our testing, we use an online tool for generating a hash with the payload from the earlier step. Using this tool, enter the required information and click Compute.

InformationDetails
Enter Plain Text to Compute HashEnter the unformatted (minified) version of the payload from the earlier step
Enter the Secret KeyEnter the securityKey value from the subscription response
Select Cryptographic Hash FunctionSelect SHA-256
Output Text FormatSelect Base64

If the Hashed Output value matches the x-bill-sha-signature value, this confirms that BILL was the source of the event notification.

Update your security key

❗️

This step is critical

This step is critical. After using your security key for testing with any online tool, generate a new security key for your subscription with POST /v3/subscriptions/{subscriptionId}/security-key.