Event Types
- Data Entity Events
- User Activity Events
- SMS Events
- Bookkeeping Events
- External Account Events
- Plaid Events
- Call Booking Events
- Export Events
Data entity events follow
EntityName.operation and generally use thin payloads.Example payload:{
"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 | 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 | 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.Show BankTransaction example payload
Show BankTransaction example payload
{
"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"
}
}
}
BusinessTask lifecycle webhooks include the current active task count for the business in addition to the standard lifecycle entity fields.Show BusinessTask example payload
Show BusinessTask example payload
{
"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
}
}
User activity events use the
activity.* namespace.Example payload:{
"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_transactionactivity.load_pnlactivity.load_balance_sheetactivity.load_cashflow_statementactivity.create_custom_accountactivity.archive_custom_accountactivity.reactivate_custom_accountactivity.upload_custom_account_csvactivity.export_pnl_csvactivity.export_pnl_excelactivity.export_pnl_comparison_csvactivity.export_pnl_month_over_monthactivity.export_pnl_line_item_excelactivity.export_balance_sheet_csvactivity.export_balance_sheet_excelactivity.export_cashflow_csvactivity.export_cashflow_excelactivity.export_transactions_csvactivity.export_transactions_excelactivity.export_pnl_pdfactivity.export_trial_balance_excelactivity.export_ar_aging_excelactivity.export_business_expenses_excelactivity.export_business_income_excelactivity.export_business_mileage_excelactivity.export_personal_expenses_excelactivity.export_personal_income_excelactivity.export_personal_mileage_excelactivity.export_time_tracking_excelactivity.export_schedule_c_excelactivity.generate_tax_packet
SMS events use the
sms.* namespace.Example payload:{
"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_receivedsms.message_deliveredsms.message_delivery_failed
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,
Sent at the end of a business’s Layer bookkeeping onboarding call, when their bookkeeping configuration’s
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
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:
bookkeeping_event.created; use data.resource_type and data.action to distinguish what happened.Event types
bookkeeping_onboarding.completedbookkeeping_purchase_date.updatebookkeeping_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:{
"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
Thebookkeeping_onboarding.completed webhook fires when Layer updates the business’s bookkeeping configuration at the end of their onboarding call.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.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:{
"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
Thebookkeeping_purchase_date.update webhook fires whenever a business’s first_month_purchased_date changes.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.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:{
"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.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:{
"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.connectedexternal_accounts.link.disconnectedexternal_accounts.link.archivedexternal_accounts.link.reactivatedexternal_accounts.link.needs_repairexternal_accounts.link.repairedexternal_accounts.account.connectedexternal_accounts.account.archivedexternal_accounts.account.reactivatedexternal_accounts.account.needs_repairexternal_accounts.account.repaired
Plaid-specific events use the
plaid.* namespace.Example payload:{
"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
Theplaid.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.Call booking events use the
call_booking.* namespace. They notify you when a call booked through Calendly is scheduled, rescheduled, or canceled.Example payload:{
"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.scheduledcall_booking.rescheduledcall_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.scheduledfires for a new booking.call_booking.rescheduledfires when an existing booking moves to a new time.call_booking.canceledfires when an existing booking is canceled without being rescheduled.
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.Export events use the
export.* namespace and notify you when an async export 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:{
"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.completedexport.failed
export.completed, call Fetch export to retrieve the download_url.