> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layerfi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks event catalog

## Event Types

<Tabs>
  <Tab title="Data Entity Events">
    Data entity events follow `EntityName.operation` and generally use thin payloads.

    **Example payload:**

    ```json theme={null}
    {
      "id": "Customer_created_7bcef4fd-9458-49d0-a7e7-589f5e6f2683_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
      "type": "Customer.created",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "entity_id": "7bcef4fd-9458-49d0-a7e7-589f5e6f2683",
        "entity_external_id": "cust_2001"
      }
    }
    ```

    | Entity                                              | Events                                                                                          |
    | --------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
    | [BankTransaction](#events-with-additional-metadata) | `BankTransaction.created`, `BankTransaction.updated`, `BankTransaction.archived`                |
    | Bill                                                | `Bill.created`, `Bill.updated`, `Bill.archived`                                                 |
    | BillPayment                                         | `BillPayment.created`, `BillPayment.updated`, `BillPayment.archived`                            |
    | Business                                            | `Business.created`, `Business.updated`, `Business.archived`                                     |
    | [BusinessTask](#events-with-additional-metadata)    | `BusinessTask.created`, `BusinessTask.updated`, `BusinessTask.archived`                         |
    | Customer                                            | `Customer.created`, `Customer.updated`, `Customer.archived`                                     |
    | CustomerCredit                                      | `CustomerCredit.created`, `CustomerCredit.updated`, `CustomerCredit.archived`                   |
    | CustomerPayout                                      | `CustomerPayout.created`, `CustomerPayout.updated`, `CustomerPayout.archived`                   |
    | CustomerRefund                                      | `CustomerRefund.created`, `CustomerRefund.updated`, `CustomerRefund.archived`                   |
    | GeneralLedgerAccount                                | `GeneralLedgerAccount.created`, `GeneralLedgerAccount.updated`, `GeneralLedgerAccount.archived` |
    | Invoice                                             | `Invoice.created`, `Invoice.updated`, `Invoice.archived`                                        |
    | InvoicePayment                                      | `InvoicePayment.created`, `InvoicePayment.updated`, `InvoicePayment.archived`                   |
    | InvoiceWriteOff                                     | `InvoiceWriteOff.created`, `InvoiceWriteOff.updated`, `InvoiceWriteOff.archived`                |
    | TaxProfile                                          | `TaxProfile.created`, `TaxProfile.updated`, `TaxProfile.archived`                               |
    | TimeEntry                                           | `TimeEntry.created`, `TimeEntry.updated`, `TimeEntry.archived`                                  |
    | Trip                                                | `Trip.created`, `Trip.updated`, `Trip.archived`                                                 |
    | Vehicle                                             | `Vehicle.created`, `Vehicle.updated`, `Vehicle.archived`                                        |
    | Vendor                                              | `Vendor.created`, `Vendor.updated`, `Vendor.archived`                                           |
    | VendorCredit                                        | `VendorCredit.created`, `VendorCredit.updated`, `VendorCredit.archived`                         |
    | VendorPayout                                        | `VendorPayout.created`, `VendorPayout.updated`, `VendorPayout.archived`                         |
    | VendorRefund                                        | `VendorRefund.created`, `VendorRefund.updated`, `VendorRefund.archived`                         |

    ### Events with additional metadata

    `BankTransaction` lifecycle webhooks include an optional `category` object on `data` when the transaction is categorized to a ledger account. `category` includes the account `id`, optional `stable_name`, and `display_name`. This is typically present on `BankTransaction.updated` after categorization.

    <Expandable title="BankTransaction example payload">
      ```json theme={null}
      {
        "id": "BankTransaction_updated_7bcef4fd-9458-49d0-a7e7-589f5e6f2683_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
        "type": "BankTransaction.updated",
        "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
        "business_external_id": "biz_101",
        "data": {
          "entity_id": "7bcef4fd-9458-49d0-a7e7-589f5e6f2683",
          "entity_external_id": "webhook-txn-1",
          "category": {
            "id": "00000000-0000-0000-0000-000000000002",
            "stable_name": "MATERIALS",
            "display_name": "Materials for Sold Goods"
          }
        }
      }
      ```
    </Expandable>

    `BusinessTask` lifecycle webhooks include the current active task count for the business in addition to the standard lifecycle entity fields.

    <Expandable title="BusinessTask example payload">
      ```json theme={null}
      {
        "id": "BusinessTask_created_7bcef4fd-9458-49d0-a7e7-589f5e6f2683_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
        "type": "BusinessTask.created",
        "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
        "business_external_id": "biz_101",
        "data": {
          "entity_id": "7bcef4fd-9458-49d0-a7e7-589f5e6f2683",
          "entity_external_id": null,
          "open_task_count": 3
        }
      }
      ```
    </Expandable>
  </Tab>

  <Tab title="User Activity Events">
    User activity events use the `activity.*` namespace.

    **Example payload:**

    ```json theme={null}
    {
      "id": "activity_categorize_bank_transaction_44bb48bd-4af1-4e6f-a38a-fb24e5575dc7",
      "type": "activity.categorize_bank_transaction",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "transaction_id": "34db2910-5919-4985-8e7f-56dd83e76ed5",
        "categorization_method": "API",
        "categorization": null,
        "matchType": "INVOICE_PAYMENT",
        "created_at": "2026-03-31T16:42:11Z"
      }
    }
    ```

    * `activity.categorize_bank_transaction`
    * `activity.load_pnl`
    * `activity.load_balance_sheet`
    * `activity.load_cashflow_statement`
    * `activity.create_custom_account`
    * `activity.archive_custom_account`
    * `activity.reactivate_custom_account`
    * `activity.upload_custom_account_csv`
    * `activity.export_pnl_csv`
    * `activity.export_pnl_excel`
    * `activity.export_pnl_comparison_csv`
    * `activity.export_pnl_month_over_month`
    * `activity.export_pnl_line_item_excel`
    * `activity.export_balance_sheet_csv`
    * `activity.export_balance_sheet_excel`
    * `activity.export_cashflow_csv`
    * `activity.export_cashflow_excel`
    * `activity.export_transactions_csv`
    * `activity.export_transactions_excel`
    * `activity.export_pnl_pdf`
    * `activity.export_trial_balance_excel`
    * `activity.export_ar_aging_excel`
    * `activity.export_business_expenses_excel`
    * `activity.export_business_income_excel`
    * `activity.export_business_mileage_excel`
    * `activity.export_personal_expenses_excel`
    * `activity.export_personal_income_excel`
    * `activity.export_personal_mileage_excel`
    * `activity.export_time_tracking_excel`
    * `activity.export_schedule_c_excel`
    * `activity.generate_tax_packet`
  </Tab>

  <Tab title="SMS Events">
    SMS events use the `sms.*` namespace.

    **Example payload:**

    ```json theme={null}
    {
      "id": "sms_message_received_SM1234567890",
      "type": "sms.message_received",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "message_id": "SM1234567890",
        "direction": "RECEIVED",
        "body": "Classify this as utilities",
        "phone_number": "+15551234567",
        "delivery_status": null,
        "at": "2026-03-31T16:48:55Z"
      }
    }
    ```

    * `sms.message_received`
    * `sms.message_delivered`
    * `sms.message_delivery_failed`
  </Tab>

  <Tab title="Bookkeeping Events">
    Bookkeeping webhooks notify you about onboarding completion, first-month purchase date changes, and bookkeeping context events. A bookkeeping context event is a normalized audit-style event, so many bookkeeping actions share the same webhook type, `bookkeeping_event.created`; use `data.resource_type` and `data.action` to distinguish what happened.

    ## Event types

    * `bookkeeping_onboarding.completed`
    * `bookkeeping_purchase_date.update`
    * `bookkeeping_event.created`

    ## `bookkeeping_onboarding.completed`

    Sent at the end of a business's Layer bookkeeping onboarding call, when their bookkeeping configuration's `onboarding_date` is set for the first time.

    **Example payload:**

    ```json theme={null}
    {
      "id": "bookkeeping_onboarding_completed_a43f6b83-8932-4ced-b6b1-0199313274ca_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
      "type": "bookkeeping_onboarding.completed",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "bookkeeping_configuration_id": "a43f6b83-8932-4ced-b6b1-0199313274ca",
        "onboarding_date": "2026-05-07",
        "first_month_purchased_date": "2026-01-01",
        "activation_at": "2026-01-01T05:00:00Z"
      }
    }
    ```

    ### Payload Fields

    | Field                               | Type                  | Description                                                                                                                                                   |
    | ----------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                                | string                | Unique identifier for this webhook event                                                                                                                      |
    | `type`                              | string                | Always `bookkeeping_onboarding.completed`                                                                                                                     |
    | `business_id`                       | string (UUID)         | The Layer business ID                                                                                                                                         |
    | `business_external_id`              | string or null        | Your external identifier for the business, if set                                                                                                             |
    | `data.bookkeeping_configuration_id` | string (UUID)         | The ID of the bookkeeping configuration that completed onboarding                                                                                             |
    | `data.onboarding_date`              | string (date)         | The date when bookkeeping onboarding was completed, in `YYYY-MM-DD` format                                                                                    |
    | `data.first_month_purchased_date`   | string (date) or null | The business's first purchased bookkeeping month, in `YYYY-MM-DD` format. `null` when no first-month-purchased value is set on the bookkeeping configuration. |
    | `data.activation_at`                | string (date-time)    | The business's activation timestamp, in ISO 8601 format. Always present.                                                                                      |

    ### When This Webhook Fires

    The `bookkeeping_onboarding.completed` webhook fires when Layer updates the business's bookkeeping configuration at the end of their onboarding call.

    <Info>
      This webhook only fires when the `onboarding_date` transitions from unset (null) to a value. Subsequent updates to `onboarding_date` do not trigger additional webhooks.
    </Info>

    ## `bookkeeping_purchase_date.update`

    Sent when a business's first purchased bookkeeping month changes on its bookkeeping configuration. Use this to keep your records in sync when Layer sets or updates the `first_month_purchased_date`.

    **Example payload:**

    ```json theme={null}
    {
      "id": "bookkeeping_purchase_date_update_00000000-0000-0000-0000-000000000002_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
      "type": "bookkeeping_purchase_date.update",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "bookkeeping_configuration_id": "00000000-0000-0000-0000-000000000002",
        "first_month_purchased_date": "2024-01-01"
      }
    }
    ```

    ### Payload Fields

    | Field                               | Type                  | Description                                                                                                                             |
    | ----------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                                | string                | Unique identifier for this webhook event                                                                                                |
    | `type`                              | string                | Always `bookkeeping_purchase_date.update`                                                                                               |
    | `business_id`                       | string (UUID)         | The Layer business ID                                                                                                                   |
    | `business_external_id`              | string or null        | Your external identifier for the business, if set                                                                                       |
    | `data.bookkeeping_configuration_id` | string (UUID)         | The ID of the bookkeeping configuration whose purchase date changed                                                                     |
    | `data.first_month_purchased_date`   | string (date) or null | The business's first purchased bookkeeping month, in `YYYY-MM-DD` format. `null` when the first-month-purchased value has been cleared. |

    ### When This Webhook Fires

    The `bookkeeping_purchase_date.update` webhook fires whenever a business's `first_month_purchased_date` changes.

    <Info>
      `first_month_purchased_date` can change more than once, so you may receive this event multiple times for the same business with each event having a unique `id`.
    </Info>

    ## `bookkeeping_event.created`

    Sent when Layer records a bookkeeping context event for a business, such as a transaction categorization, task update, period status change, connected account change, adjustment entry, or closing date update.

    **Example payload:**

    ```json theme={null}
    {
      "id": "bookkeeping_event_created_4d2df66e-ae15-4241-9f6b-9c4bdf19f83e",
      "type": "bookkeeping_event.created",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "id": "4d2df66e-ae15-4241-9f6b-9c4bdf19f83e",
        "resource_type": "BOOKKEEPING_PERIOD",
        "resource_id": "77d54b21-d7d7-4bfc-8f33-2845e4f8e07a",
        "action": "PERIOD_STATUS_CHANGED",
        "summary": "Bookkeeper status changed period",
        "actor": "MANUAL_BOOKKEEPER",
        "count": null,
        "event_at": "2026-03-31T16:52:44Z",
        "accounting_date": "2026-03-31T04:59:59.999999999Z",
        "previous_state": "TO_DO",
        "new_state": "DONE"
      }
    }
    ```

    ### Bookkeeping context fields

    | Field             | Description                                          |
    | ----------------- | ---------------------------------------------------- |
    | `id`              | Unique bookkeeping context event ID.                 |
    | `resource_type`   | Bookkeeping resource affected by the event.          |
    | `resource_id`     | ID of the affected resource, when applicable.        |
    | `action`          | Specific bookkeeping action that occurred.           |
    | `summary`         | Human-readable event summary.                        |
    | `actor`           | Actor that caused the event.                         |
    | `count`           | Count associated with batch events, when applicable. |
    | `event_at`        | Timestamp when the event occurred.                   |
    | `accounting_date` | Accounting-effective timestamp, when applicable.     |
    | `previous_state`  | Previous value or state, when applicable.            |
    | `new_state`       | New value or state, when applicable.                 |

    ### Bookkeeping context actions

    | Resource type              | Actions                                                                                                                                               |
    | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `BANK_TRANSACTION`         | `CATEGORIZED`, `RECATEGORIZED`                                                                                                                        |
    | `BANK_TRANSACTION_BATCH`   | `BATCH_CATEGORIZED`                                                                                                                                   |
    | `TASK`                     | `TASK_CREATED`, `TASK_ANSWERED`, `TASK_COMPLETED`                                                                                                     |
    | `BOOKKEEPING_PERIOD`       | `PERIOD_STATUS_CHANGED`                                                                                                                               |
    | `BOOKKEEPING_STEP`         | `STEP_COMPLETED`                                                                                                                                      |
    | `CONNECTED_ACCOUNT`        | `ACCOUNT_CONNECTED`, `ACCOUNT_DISCONNECTED`, `ACCOUNT_NEEDS_REPAIR`, `ACCOUNT_REPAIRED`, `ACCOUNT_CREATED`, `ACCOUNT_ARCHIVED`, `ACCOUNT_REACTIVATED` |
    | `ADJUSTMENT_ENTRY`         | `CUSTOM_ENTRY_CREATED`, `CLOSING_ACTION_CREATED`                                                                                                      |
    | `ACCOUNTING_CONFIGURATION` | `CLOSING_DATE_UPDATED`                                                                                                                                |

    ### Actors

    `actor` can be `USER`, `AI_BOOKKEEPER`, `MANUAL_BOOKKEEPER`, `SYSTEM`, or `UNKNOWN`.
  </Tab>

  <Tab title="External Account Events">
    External account events use the `external_accounts.*` namespace.
    These events include the current count of external accounts that need repair for the business.

    **Example payload:**

    ```json theme={null}
    {
      "id": "external_accounts_account_connected_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
      "type": "external_accounts.account.connected",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "provider": "plaid",
        "at": "2026-03-31T16:50:29Z",
        "link_id": "719b0d31-ba7b-4f1b-982a-c6334b0a544b",
        "external_link_id": "plaid_item_123",
        "account_ids": [
          "92762148-f10b-42a5-b37f-b1e23fa3faca"
        ],
        "external_account_ids": [
          "plaid_account_456"
        ],
        "accounts_needing_repair_count": 0
      }
    }
    ```

    ### Payload Fields

    | Field                                | Type               | Description                                                                                                                                                                                        |
    | ------------------------------------ | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                                 | string             | Unique identifier for this webhook event.                                                                                                                                                          |
    | `type`                               | string             | The external account event type (e.g., `external_accounts.account.connected`).                                                                                                                     |
    | `business_id`                        | string (UUID)      | The Layer business ID                                                                                                                                                                              |
    | `business_external_id`               | string or null     | Your external identifier for the business, if set                                                                                                                                                  |
    | `data.provider`                      | string             | The external account provider (e.g., `plaid`).                                                                                                                                                     |
    | `data.at`                            | string (date-time) | ISO 8601 timestamp when the event occurred.                                                                                                                                                        |
    | `data.link_id`                       | string (UUID)      | Layer's internal ID for the external account link.                                                                                                                                                 |
    | `data.external_link_id`              | string             | The provider's ID for the link (e.g., Plaid Item ID).                                                                                                                                              |
    | `data.account_ids`                   | array              | Layer IDs of the affected external accounts.                                                                                                                                                       |
    | `data.external_account_ids`          | array              | Provider IDs of the affected external accounts.                                                                                                                                                    |
    | `data.accounts_needing_repair_count` | integer            | Number of external accounts across the business that currently need repair. Only counts accounts where the parent bank account has `notify_when_disconnected` enabled. Excludes archived accounts. |

    ### Event types

    * `external_accounts.link.connected`
    * `external_accounts.link.disconnected`
    * `external_accounts.link.archived`
    * `external_accounts.link.reactivated`
    * `external_accounts.link.needs_repair`
    * `external_accounts.link.repaired`
    * `external_accounts.account.connected`
    * `external_accounts.account.archived`
    * `external_accounts.account.reactivated`
    * `external_accounts.account.needs_repair`
    * `external_accounts.account.repaired`
  </Tab>

  <Tab title="Plaid Events">
    Plaid-specific events use the `plaid.*` namespace.

    **Example payload:**

    ```json theme={null}
    {
      "id": "plaid_link_token_created_Aim3b8jJC9eRyfy",
      "type": "plaid.link.token_created",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "created_at": "2026-03-31T16:50:29Z",
        "plaid_request_id": "Aim3b8jJC9eRyfy"
      }
    }
    ```

    * `plaid.link.token_created`

    ### Payload Fields

    | Field                   | Type               | Description                                                                                                                          |
    | ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
    | `id`                    | string             | Unique identifier for this webhook event. Suffixed with the Plaid request id.                                                        |
    | `type`                  | string             | Always `plaid.link.token_created`                                                                                                    |
    | `business_id`           | string (UUID)      | The Layer business ID                                                                                                                |
    | `business_external_id`  | string or null     | Your external identifier for the business, if set                                                                                    |
    | `data.created_at`       | string (date-time) | When the link token was created                                                                                                      |
    | `data.plaid_request_id` | string             | The Plaid `request_id` returned by Plaid for the link-token-create call. Useful when correlating with Plaid logs or support tickets. |

    ### When This Webhook Fires

    The `plaid.link.token_created` webhook fires whenever Layer mints a Plaid link token for a business. This corresponds to the user initiating the Plaid Link flow (e.g. clicking "Add Account" or starting an update-mode reconnect). The event fires before the user selects an institution or completes the flow, so it can be used as a click-level signal. To know when a connection is actually established, listen for `external_accounts.link.connected`.
  </Tab>

  <Tab title="Call Booking Events">
    Call booking events use the `call_booking.*` namespace. They notify you when a call booked through Calendly is scheduled, rescheduled, or canceled.

    **Example payload:**

    ```json theme={null}
    {
      "id": "call_booking_scheduled_00000000-0000-0000-0000-000000000001_03f6c94f-574d-42ca-a6cd-fecf2a2aeccb",
      "type": "call_booking.scheduled",
      "business_id": "8e7a359e-7af5-4f6e-b786-6ddfd1807c32",
      "business_external_id": "biz_101",
      "data": {
        "calendly_event_uri": "https://api.calendly.com/scheduled_events/76b3fb2d-b5d8-4d60-b969-cef8bd2900de",
        "invitee_name": "Jane Provider",
        "invitee_email": "jane@example.com",
        "event_start_at": "2024-01-15T12:00:00Z",
        "event_end_at": "2024-01-15T12:30:00Z",
        "purpose": "BOOKKEEPING_ONBOARDING",
        "previous_calendly_event_id": null
      }
    }
    ```

    ### Event types

    * `call_booking.scheduled`
    * `call_booking.rescheduled`
    * `call_booking.canceled`

    ### Payload Fields

    | Field                             | Type                       | Description                                                                                       |
    | --------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------- |
    | `id`                              | string                     | Unique identifier for this webhook event.                                                         |
    | `type`                            | string                     | The call booking event type (for example, `call_booking.scheduled`).                              |
    | `business_id`                     | string (UUID)              | The Layer business ID.                                                                            |
    | `business_external_id`            | string or null             | Your external identifier for the business, if set.                                                |
    | `data.calendly_event_uri`         | string or null             | Calendly scheduled-event API URI for the call.                                                    |
    | `data.invitee_name`               | string or null             | Name of the invitee who booked the call. Contains personally identifiable information (PII).      |
    | `data.invitee_email`              | string or null             | Email of the invitee who booked the call. Contains PII.                                           |
    | `data.event_start_at`             | string (date-time)         | ISO 8601 start time of the call. Required.                                                        |
    | `data.event_end_at`               | string (date-time) or null | ISO 8601 end time of the call.                                                                    |
    | `data.purpose`                    | string                     | Purpose of the call: `BOOKKEEPING_ONBOARDING` or `ADHOC`. Required.                               |
    | `data.previous_calendly_event_id` | string or null             | Calendly event ID of the booking that was replaced. Populated only on `call_booking.rescheduled`. |

    ### When This Webhook Fires

    * `call_booking.scheduled` fires for a new booking.
    * `call_booking.rescheduled` fires when an existing booking moves to a new time.
    * `call_booking.canceled` fires when an existing booking is canceled without being rescheduled.

    <Info>
      A reschedule is delivered as a single `call_booking.rescheduled` event. Layer does not also send `call_booking.canceled` and `call_booking.scheduled` events for the same reschedule.
    </Info>
  </Tab>

  <Tab title="Export Events">
    Export events use the `export.*` namespace and notify you when an [async export](/guides/async-reports) finishes.

    These events are **client-scoped**: the payload includes `id`, `type`, and `data`, and does not include top-level `business_id` / `business_external_id`.

    **Example payload:**

    ```json theme={null}
    {
      "id": "export_completed_00000000-0000-0000-0000-000000000006",
      "type": "export.completed",
      "data": {
        "export_id": "00000000-0000-0000-0000-000000000006",
        "business_id": null,
        "export_type": "billing_report",
        "status": "completed",
        "error": null
      }
    }
    ```

    * `export.completed`
    * `export.failed`

    After `export.completed`, call [Fetch export](/api-reference/v1/fetch-export) to retrieve the `download_url`.
  </Tab>
</Tabs>
