---
updatedAt: 2026-06-09T20:38:45.000Z
agentTools:
  projectIndex: https://developer.bill.com/llms.txt
---

# Webhook API notification rules

BILL webhook notifications for events follow a set of rules.

<Table align={["left","left"]}>
  <thead>
    <tr>
      <th style={{ textAlign: "left" }}>
        Design
      </th>

      <th style={{ textAlign: "left" }}>
        Description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ textAlign: "left" }}>
        **Notification URL**
      </td>

      <td style={{ textAlign: "left" }}>
        The notification URL is the location where you receive event notifications. The URL that you provide must be HTTPS.

        When you are testing with BILL webhooks, you can use an online service for generating a test notification URL. For example, <Anchor label="webhook.site" target="_blank" href="https://webhook.site">webhook.site</Anchor>  or  <Anchor label="pipedream.com/requestbin" target="_blank" href="https://pipedream.com/requestbin">pipedream.com/requestbin</Anchor> .
      </td>
    </tr>

    <tr>
      <td style={{ textAlign: "left" }}>
        **All notifications are organization-specific**
      </td>

      <td style={{ textAlign: "left" }}>
        BILL sends you event notifications only for the BILL organization used to set up a subscription.

        When you set up a subscription, the `organizationId` in the API response represents the BILL organization for which your subscription is created. See <Anchor label="Work with BILL webhooks" target="_blank" href="doc:working-with-bill-webhooks">Work with BILL webhooks</Anchor> for more information.
      </td>
    </tr>

    <tr>
      <td style={{ textAlign: "left" }}>
        **Event notification`id`**
      </td>

      <td style={{ textAlign: "left" }}>
        BILL sends each event notification with a unique event `id`. Your integration must save event `id` value to avoid processing any duplicate notifications.
      </td>
    </tr>

    <tr>
      <td style={{ textAlign: "left" }}>
        **JSON escaped payload**
      </td>

      <td style={{ textAlign: "left" }}>
        When BILL sends you an event notification, the `payload` is JSON-escaped and is presented as a string.

        Ensure that your integration handles JSON escaped payloads for notifications. See <Anchor label="Work with BILL webhooks" target="_blank" href="doc:working-with-bill-webhooks">Work with BILL webhooks</Anchor> for more information about a sample payload.
      </td>
    </tr>

    <tr>
      <td style={{ textAlign: "left" }}>
        **Order of notifications**
      </td>

      <td style={{ textAlign: "left" }}>
        In case notifications are sent out of order, organize the notifications based on the timestamp of each notification.
      </td>
    </tr>

    <tr>
      <td style={{ textAlign: "left" }}>
        **Time To Live (TTL)**
      </td>

      <td style={{ textAlign: "left" }}>
        BILL maintains a 180-day event history for each subscription. You can get the list of event notifications sent to you for a subscription with `GET /v3/events/subscription/{subscriptionId}`.
      </td>
    </tr>

    <tr>
      <td style={{ textAlign: "left" }}>
        **Notification retries**
      </td>

      <td style={{ textAlign: "left" }}>
        When BILL does not receive a HTTP 200 `statusCode` for an event notification within 10 seconds, the notification is considered a failure.

        When an event notification fails, BILL tries to send the notification again with exponential backoff - 2 seconds, 4 seconds, 8 seconds, and 16 seconds. BILL attempts to send the notification five times.

        To address any issues with notification retries, you can get the list of event notifications sent to you for a subscription with `GET /v3/events/subscription/{subscriptionId}`.
      </td>
    </tr>
  </tbody>
</Table>