Work 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.
Organization-level users vs Partner users
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, BILL sends event notifications for all organizations created by the partner user.
Subscribe to BILL events
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.
To create a subscription with POST /v3/subscriptions
, set the required fields.
Field | Description |
---|---|
name | Subscription name |
status | Subscription 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. |
events | In 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 . |
notificationUrl | The location where you receive event notifications. The URL that you provide must be HTTPS. |
Create a subscription at the Partner level
To create a subscription at the partner level, simply set your partner
sessionId
(with/v3/partner/login
) andappKey
as the required header values. The base URL and body parameters in thePOST /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.
Use an online service for setting up a notification URL
When you are testing with BILL webhooks, you can use an online service for generating a test notification URL. For example, webhook.site or pipedream.com/requestbin.
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,
"actor": "CLIENT"
},
"events": [{
"type": "bill.created",
"version": "1"
},
{
"type": "bill.updated",
"version": "1"
},
{
"type": "bill.archived",
"version": "1"
}],
"notificationUrl": "https://example.com/billmanagement",
"createdTime": "2025-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. 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.
Security key best practice
Keep the security key for your subscription updated in a timely manner. 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.
Subscribe to Spend & Expense API events
When you are subscribing to the BILL Spend & Expense API events, your POST /v3/subscriptions
API request must include the apiToken
header value for authentication.
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 'apiToken: {api_token}' \
--data '{
"name": "Bill management",
"status": {
"enabled": true
},
"events": [{
"type": "spend.transaction.updated",
"version": "1"
}],
"notificationUrl": "https://example.com/billmanagement"
}'
Generate a test event notification
When you set up a subscription, you can generate a test event with POST /v3/subscriptions/{subscriptionId}/test
. 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 notification URL.
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
}
Important
All the fields in the test event notification are test values. You cannot use any of the test values for any other operation.
Get 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}
.
Resend a specific event
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\": \"202501\",
\"invoiceDate\": \"2025-12-16T00:00:00.127+00:00\", \"amount\": 228.99,
\"createdDate\": \"2025-12-15T23:15:23.127+00:00\", \"archived\": false}}"
"createdTime": "2025-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\": \"202502\",
\"invoiceDate\": \"2025-12-16T00:00:00.127+00:00\", \"amount\": 149,
\"createdDate\": \"2025-12-15T23:17:31.127+00:00\", \"archived\": false}}"
"createdTime": "2025-12-15T23:17:35.127+00:00",
"statusCode": 200
}
]
HTTP 200
statusCode
The HTTP 200
statusCode
informs BILL that the event notification was successfully sent to yournotificationUrl
.
In the next section, we list examples of the BILL webhook notification payloads in the Notification payloads reference.
Updated 6 days ago