For customers of Bill Manager, Pinwheel provides detection-based webhooks that notify you about a user's recurring bills and subscriptions as we identify and track changes to them over time. These webhooks are fired automatically when Pinwheel detects changes in the user's transaction data.
Note: Pinwheel can also send these webhooks to customers of Switch Kit and Bill Switch products. Please talk to your Pinwheel account executive to enable.
bill.added
Fired when a new subscription or bill is detected for a user. The first time a user connects to Bill Manager, we'll fire bill.added for each recurring bill or subscription we detect.
Payload Schema
| Payload Param | Type | Description |
|---|---|---|
id | UUID | Unique identifier for this bill record |
end_user_id | string | The end user's unique identifier |
platform_id | UUID | Platform/merchant identifier |
platform_name | string | Display name of the platform/merchant (e.g. "Netflix") |
reported_platform_name (optional) | string | If the user attempts a bill switch/cancellation against a merchant we don't track, the platform_name will be "Other (merchant)" and this field will contain the reported name of the merchant. |
reserved_platform_id (optional) | string | Similar to reported_platform_name, this field holds the UUID of the merchant/platform if we add it in the future. |
detection_method | string | Whether this bill was detected from an external account (external_plaid), uploaded transaction data (first_party), or created manually by the user (manual). |
frequency | string | Billing frequency: weekly, bi-weekly, monthly, bi-monthly, quarterly, semi-yearly, yearly, or other |
next_payment_amount_cents | integer | Next payment amount in cents. If this bill was manually added by the user, will be set to 0 |
next_payment_date(optional) | datetime | Next scheduled payment date (if known) |
last_payment_date(optional) | datetime | Most recent payment date (if known) |
first_seen_at | datetime | When this bill was first detected |
payment(optional) | object | Payment method information (if known, see below) |
Payment Schema
The payment is only available for bills and subscriptions we detect. Bills that are manually added by the user will not have this information.
| Parameter | Type | Description |
|---|---|---|
type | string | card for credit/debit cards payments, or ach for ACH payments |
institution_name | string | Name of the financial institution associated with the card or bank account |
card_name(optional) | string | Name of the card (if type is card) |
last_four_card_number(optional) | string | Last 4 digits of card number (if type is card) |
account_name(optional) | string | Name of the bank account (if type is ach) |
last_four_account_number(optional) | string | Last 4 digits of account number (if type is ach) |
Sample Webhook Event - Monthly Bill Detected (Card Payment)
{
"event": "bill.added",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_amount_cents": 1599,
"next_payment_date": "2026-02-15T00:00:00Z",
"last_payment_date": "2026-01-15T00:00:00Z",
"first_seen_at": "2026-01-29T18:30:00Z",
"payment": {
"type": "card",
"institution_name": "Acme Bank",
"card_name": "Checking Debit",
"last_four_card_number": "4242"
}
}
}Sample Webhook Event - Monthly Bill Detected (ACH Payment)
{
"event": "bill.added",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_amount_cents": 1599,
"next_payment_date": "2026-02-15T00:00:00Z",
"last_payment_date": "2026-01-15T00:00:00Z",
"first_seen_at": "2026-01-29T18:30:00Z",
"payment": {
"type": "ach",
"institution_name": "Acme Bank",
"account_name": "My Checking Account",
"last_four_account_number": "4242"
}
}
}Sample Webhook Event - Monthly Bill Detected (Manually Added)
{
"event": "bill.added",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"detection_method": "manual",
"frequency": "other",
"next_payment_amount_cents": 0,
"first_seen_at": "2026-01-29T18:30:00Z"
}
}Sample Webhook Event - Monthly Bill Detected - untracked merchant
{
"event": "bill.added",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "0cc073dc-f3f7-4a9e-a287-fb34a43cb71e",
"platform_name": "Other (merchant)",
"reported_platform_name": "Smalltown Life Insurance Co",
"reserved_platform_id": "5d426d0e-0618-46ea-945a-b8ca679ac39f",
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_amount_cents": 1599,
"next_payment_date": "2026-02-15T00:00:00Z",
"last_payment_date": "2026-01-15T00:00:00Z",
"first_seen_at": "2026-01-29T18:30:00Z",
"payment": {
"type": "card",
"institution_name": "Acme Bank",
"card_name": "Checking Debit",
"last_four_card_number": "4242"
}
}
}bill.updated
Fired when data about the bill has been updated. This webhook schema is the same as bill.added, except that it adds the changed_fields field, which contains a list of the fields that have changed since the last webhook we sent about this bill.
Note: the data in the this webhook's payload reflects the updated values. If you need the previous values for your use case, you'll need to store the data from these webhooks on an ongoing basis. Prior to updating with the values in this webhook, retrieve the previous values from your data store.
Payload Schema
| Payload Param | Type | Description |
|---|---|---|
id | UUID | Unique identifier for this bill record |
end_user_id | string | The end user's unique identifier |
platform_id | UUID | Platform/merchant identifier |
platform_name | string | Display name of the platform/merchant (e.g. "Netflix") |
reported_platform_name (optional) | string | If the user attempts a bill switch/cancellation against a merchant we don't track, the platform_name will be "Other (merchant)" and this field will contain the reported name of the merchant. |
reserved_platform_id (optional) | string | Similar to reported_platform_name, this field holds the UUID of the merchant/platform if we add it in the future. |
detection_method | string | Whether this bill was detected from an external account (external_plaid), uploaded transaction data (first-party), or created manually by the user (manual). |
frequency | string | Billing frequency: weekly, bi-weekly, monthly, bi-monthly, quarterly, semi-yearly, yearly, or other |
next_payment_amount_cents | integer | Next payment amount in cents. If this bill was manually added by the user, will be set to 0 |
next_payment_date(optional) | datetime | Next scheduled payment date (if known) |
last_payment_date(optional) | datetime | Most recent payment date (if known) |
first_seen_at | datetime | When this bill was first detected |
changed_fields | array | List of the fields that have changed since the last webhook we sent |
payment(optional) | object | Payment method information (if known, see below) |
Payment Schema
The payment is only available for bills and subscriptions we detect. Bills that are manually added by the user will not have this information.
| Parameter | Type | Description |
|---|---|---|
type | string | card for credit/debit cards payments, or ach for ACH payments |
institution_name | string | Name of the financial institution associated with the card or bank account |
card_name(optional) | string | Name of the card (if type is card) |
last_four_card_number(optional) | string | Last 4 digits of card number (if type is card) |
account_name(optional) | string | Name of the bank account (if type is ach) |
last_four_account_number(optional) | string | Last 4 digits of account number (if type is ach) |
Sample Webhook Event - Bill Payment Amount and Dates Updated
{
"event": "bill.updated",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_amount_cents": 1699,
"next_payment_date": "2026-03-15T00:00:00Z",
"last_payment_date": "2026-02-15T00:00:00Z",
"first_seen_at": "2026-01-29T18:30:00Z",
"changed_fields": ["next_payment_amount_cents", "next_payment_date", "last_payment_date"],
"payment": {
"type": "card",
"institution_name": "Acme Bank",
"card_name": "Checking Debit",
"last_four_card_number": "4242"
}
}
}Sample Webhook Event - Bill Payment Method Updated
{
"event": "bill.updated",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_amount_cents": 1599,
"next_payment_date": "2026-02-15T00:00:00Z",
"last_payment_date": "2026-01-15T00:00:00Z",
"first_seen_at": "2026-01-29T18:30:00Z",
"changed_fields": ["payment.institution_name", "payment.card_name", "payment.last_four_card_number"],
"payment": {
"type": "card",
"institution_name": "Acme Bank",
"card_name": "Debit card",
"last_four_card_number": "7878"
}
}
}bill.removed
Fired when a bill or subscription is no longer being detected or tracked. If you receive this webhook, you will no longer receive webhooks for this bill unless it becomes active again.
Payload Schema
| Payload Param | Type | Description |
|---|---|---|
id | UUID | Unique identifier for this bill record |
end_user_id | string | The end user's unique identifier |
platform_id | UUID | Platform/merchant identifier |
platform_name | string | Display name of the platform/merchant (e.g. "Netflix") |
reported_platform_name (optional) | string | If the user attempts a bill switch/cancellation against a merchant we don't track, the platform_name will be "Other (merchant)" and this field will contain the reported name of the merchant. |
reserved_platform_id (optional) | string | Similar to reported_platform_name, this field holds the UUID of the merchant/platform if we add it in the future. |
removed_at | datetime | When the bill was removed |
Sample Webhook Event
{
"event": "bill.removed",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"removed_at": "2026-01-15T00:00:00Z",
}
}bill.reminder
Fired when a payment is upcoming (within 5 days of the next payment date).
Payload Schema
The schema for this webhook is identical to that of bill.added.
Sample Webhook Event
{
"event": "bill.reminder",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"end_user_id": "user_12345",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_amount_cents": 1599,
"next_payment_date": "2026-02-15T00:00:00Z",
"last_payment_date": "2026-01-15T00:00:00Z",
"first_seen_at": "2026-01-29T18:30:00Z",
"payment": {
"type": "card",
"institution_name": "Acme Bank",
"card_name": "Checking Debit",
"last_four_card_number": "4242"
}
}
}