For customers of Switch Kit, Bill Switch, and Bill Manager, the webhooks in this section inform you when a user has attempted a bill switch or cancellation. You must also register for account.added webhooks to correlate information provided about the merchant the user switched/cancelled payment info for.
bill_switch.added
A bill_switch job completed. Pinwheel sends this event to your webhook endpoint when the merchant attempts to update your customer's payment method. The event is delivered whether the attempt ultimately succeeds or fails. Check the outcome field in the payload to determine if the bill switch was successful or failed.
Payload Schema
| Payload Param | Type | Description |
|---|---|---|
account_id | string | UUID of the account connected by the end user. |
platform_id | UUID | Platform/merchant identifier |
platform_name | string | Display name of the platform/merchant (e.g. "Netflix") |
end_user_id | string | The user identifier you provided when initializing Link for this user (if provided). |
outcome | string | The outcome of the job, either success, error, or pending. If pending you will receive another webhook with outcome as success or error within 24 hours. |
error_code (optional) | string | On error, a string describing the error. |
error_type (optional) | string | On error, a high level classification of the error. |
timestamp | string | ISO 8601 timestamp of job completion. |
name | string | Name of the job, which is bill_switch. |
link_token_id | string | UUID of the Link token used to initialize Link. You should use account_id as the main identifier. |
params (optional) | object | Parameters of the job, if applicable. Contains payment method information when available. |
params.bill_id | string | UUID of the user's recurring bill. This corresponds to the id field in the Bill Detection webhooks (e.g. bill.added). |
params.is_integrated_switch | boolean | Whether this is an integrated switch flow (true) or guided flow (false). |
params.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). |
params.type (optional) | string | The type of payment method switch, such as card for card-based payments. Only present for integrated flows. |
params.payment (optional) | object | Payment method details. See Payment Schema below for object structure. May be absent for guided flows if card details are unavailable. |
params.frequency (optional) | string | The billing frequency for the payment, such as monthly, weekly, or annually. |
params.next_payment_date (optional) | string | ISO 8601 timestamp of the next scheduled payment date. |
params.next_payment_amount_cents (optional) | number | The amount of the next payment in cents. |
params.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. |
params.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. |
id | string | Deprecated. UUID of the job. You should use account_id as the main identifier. |
Payment Schema
| Parameter | Type | Description |
|---|---|---|
card_name (optional) | string | Name on the card for card-based payments. |
last_four_card_number (optional) | string | Last four digits of the card number for card-based payment |
Sample Webhook Event - Integrated Flow (Card Payment)
{
"event_id": "4a939000-b43f-489d-ab32-4a0b1b9ba7a2",
"event": "bill_switch.added",
"payload": {
"id": "c4ccfd24-5e5c-4b22-8191-6f1384fc8db1",
"name": "bill_switch",
"timestamp": "2025-01-03T12:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_switch": true,
"detection_method": "external_plaid",
"type": "card",
"payment": {
"card_name": "CARD NAME",
"last_four_card_number": "4242"
},
"frequency": "monthly",
"next_payment_date": "2025-09-26T12:00:00+00:00",
"next_payment_amount_cents": 1234
}
}
}Sample Webhook Event - Guided Flow (With Payment Details)
{
"event_id": "7b212456-c89e-4f1a-bc54-8e9f3b4c7d21",
"event": "bill_switch.added",
"payload": {
"id": "d5eef035-7f6d-5c33-9202-7g2495gd9ec2",
"name": "bill_switch",
"timestamp": "2025-01-03T12:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"is_integrated_switch": false,
"detection_method": "external_plaid",
"payment": {
"card_name": "CARD NAME",
"last_four_card_number": "4242"
},
"frequency": "monthly",
"next_payment_date": "2025-09-26T12:00:00+00:00",
"next_payment_amount_cents": 1234
}
}
}Sample Webhook Event - Guided Flow (Without Payment Details)
{
"event_id": "8c323567-d90f-5g2b-cd65-9f0g4c5d8e32",
"event": "bill_switch.added",
"payload": {
"id": "e6ffg146-8g7e-6d44-0313-8h3506he0fd3",
"name": "bill_switch",
"timestamp": "2025-01-03T12:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_switch": false,
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_date": "2025-09-26T12:00:00+00:00",
"next_payment_amount_cents": 1234
}
}
}Sample Webhook Event - Guided Flow using untracked merchant
{
"event_id": "8c323567-d90f-5g2b-cd65-9f0g4c5d8e32",
"event": "bill_switch.added",
"payload": {
"id": "e6ffg146-8g7e-6d44-0313-8h3506he0fd3",
"name": "bill_switch",
"timestamp": "2025-01-03T12:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "0cc073dc-f3f7-4a9e-a287-fb34a43cb71e",
"platform_name": "Other (merchant)",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_switch": false,
"detection_method": "external_plaid",
"payment": {
"card_name": "CARD NAME",
"last_four_card_number": "4242"
},
"frequency": "monthly",
"next_payment_date": "2025-09-26T12:00:00+00:00",
"next_payment_amount_cents": 1234,
"reported_platform_name": "Smalltown Life Insurance Co",
"reserved_platform_id": "5d426d0e-0618-46ea-945a-b8ca679ac39f",
}
}
}Sample Webhook Event - Failed Bill Switch
{
"event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
"event": "bill_switch.added",
"payload": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "bill_switch",
"timestamp": "2025-01-03T12:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "error",
"error_code": "platformError",
"error_type": "platformError",
"link_token_id": "4787acbc-11cf-4db3-998c-5ea7c4feebcd",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_switch": false,
"detection_method": "external_plaid",
"frequency": "monthly",
"next_payment_date": "2025-09-26T12:00:00+00:00",
"next_payment_amount_cents": 1234
}
}
}bill_switch.cancelled
A bill_cancellation job completed. Pinwheel sends this event to your webhook endpoint when the merchant attempts to cancel a stored payment method or a recurring payment for your customer. The event is delivered whether the attempt ultimately succeeds or fails. Check the outcome field in the payload to determine if the payment cancellation was successful or failed.
Payload Schema
| Payload Param | Type | Description |
|---|---|---|
account_id | string | UUID of the account connected by the end user. |
platform_id | UUID | Platform/merchant identifier |
platform_name | string | Display name of the platform/merchant (e.g. "Netflix") |
end_user_id | string | The user identifier you provided when initializing Link for this user (if provided). |
outcome | string | The outcome of the job, either success, error, or pending. If pending you will receive another webhook with outcome as success or error within 24 hours. |
error_code (optional) | string | On error, a string describing the error. |
error_type (optional) | string | On error, a high level classification of the error. |
timestamp | string | ISO 8601 timestamp of job completion. |
name | string | Name of the job, which is bill_cancellation. |
link_token_id | string | UUID of the Link token used to initialize Link. You should use account_id as the main identifier. |
params (optional) | object | Parameters of the job, if applicable. |
params.bill_id | string | UUID of the user's recurring bill. This corresponds to the id field in the Bill Detection webhooks (e.g. bill.added). |
params.is_integrated_cancellation | boolean | Whether this is an integrated cancellation flow (true) or guided flow (false). |
params.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). |
id | string | Deprecated. UUID of the job. You should use account_id as the main identifier. |
Sample Webhook Event - Integrated Flow (Successful Cancellation)
{
"event_id": "689fcb7c-4378-4516-a489-3efd16f83d6d",
"event": "bill_switch.cancelled",
"payload": {
"id": "828a62b9-07ed-40aa-9c43-71c2df0f1fee",
"name": "bill_cancellation",
"timestamp": "2023-06-15T14:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_cancellation": true,
"detection_method": "external_plaid"
}
}
}Sample Webhook Event - Guided Flow (Successful Cancellation)
{
"event_id": "9d434678-e01g-6h3c-de76-0g1h5e6f9g43",
"event": "bill_switch.cancelled",
"payload": {
"id": "939b73c0-18fe-51bb-0d54-82d3eg1g2gff",
"name": "bill_cancellation",
"timestamp": "2023-06-15T14:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_cancellation": false,
"detection_method": "external_plaid"
}
}
}Sample Webhook Event - Guided Cancellation using untracked merchant
{
"event_id": "9d434678-e01g-6h3c-de76-0g1h5e6f9g43",
"event": "bill_switch.cancelled",
"payload": {
"id": "939b73c0-18fe-51bb-0d54-82d3eg1g2gff",
"name": "bill_cancellation",
"timestamp": "2023-06-15T14:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "0cc073dc-f3f7-4a9e-a287-fb34a43cb71e",
"platform_name": "Other (merchant)",
"end_user_id": "my_user_12345",
"outcome": "success",
"link_token_id": "3b35ba10-48cf-4a6a-b038-1572e8e93e98",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"is_integrated_cancellation": false,
"detection_method": "external_plaid",
"reported_platform_name": "Smalltown Life Insurance Co",
"reserved_platform_id": "5d426d0e-0618-46ea-945a-b8ca679ac39f"
}
}
}Sample Webhook Event - Failed Cancellation
{
"event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
"event": "bill_switch.cancelled",
"payload": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "bill_cancellation",
"timestamp": "2023-06-15T14:30:00+00:00",
"account_id": "792f2d1f-abcd-42b7-ae45-01dd80ceae28",
"platform_id": "28b38a67-240e-44be-8df0-0582a4b64a62",
"platform_name": "Netflix",
"end_user_id": "my_user_12345",
"outcome": "error",
"error_code": "systemError",
"error_type": "systemError",
"link_token_id": "4787acbc-11cf-4db3-998c-5ea7c4feebcd",
"params": {
"bill_id": "550e8400-e29b-41d4-a716-446655440000",
"detection_method": "external_plaid"
}
}
}