Implement Bill Navigator

Overview

This guide explains how to enable Bill Navigator for an end user through Pinwheel's SDK.

Bill Navigator allows users to connect their existing bank accounts and credit cards and automatically identifies recurring bills & subscriptions and offers a rich set of features to help manage bills including one-click bill switch to existing accounts/cards and cancelling bills.

Prerequisites

Link SDK versions

In order to use Bill Navigator, the Link SDKs used in your application must be installed/upgraded to use the following minimum versions:

  • React (web): 3.3.x
  • iOS: 3.4.x
  • Android: 3.4.x
  • React Native: 3.5.x

We recommend upgrading to the latest version for maximum conversion.

API and Webhook Version v2025-07-08

The use of Bill Navigator requires version v2025-07-08 or higher. Breaking changes for each API version upgrade are listed in our Change Management page. Functionality of older API versions can be found by using the API version dropdown in the top left corner of this page.

Step 1: Set up access to external account transactions

In order to identify an end user's recurring bills and subscriptions, Pinwheel needs access to transaction data from external user accounts that those bills are paid out of. Pinwheel supports the Plaid banking aggregator for retrieving transaction data from external bank and credit card accounts.

If you have already incorporated Plaid into your existing solution, Pinwheel can get access to transaction data through your account as a Plaid partner. Plaid partners get access via Plaid Processor tokens, which are tightly scoped to allow a specific partner access to a specific data stream - in this case, transaction data. The benefits of this approach are that you will continue to own and manage the Plaid account, and in most cases if a user has already connected an external account elsewhere in your app, they don't need to reconnect it for Pinwheel. However, there is some extra development work to support this approach. To learn more about this integration path, see Integrating Pinwheel with your Plaid account.

If you do not already use Plaid, then you can simply use Pinwheel's own Plaid account to identify bills and subscriptions.

Step 2: Create a Pinwheel Link token

Once access to transactions is squared away, you're ready to focus on the real-time Bill Navigator user experience.

Start by creating a Link Token for Bill Navigator. To do so, you'll need to provide the following:

  • The solution field must be set to "Bill Navigator"
  • The features field must specify "bill_switch" if you want to enable bill switching and bill cancellation functionality.
    • If you do not include the "bill_switch" feature, Bill Navigator will still identify recurring bills and subscriptions and offer all the subscription-management features and benefits outlined in the Overview. In this scenario, it is not necessary to add cards or allocation data in the link token request (see below).
  • A unique identifier for the user that you can resolve to your own internal user model
  • Debit/credit card details for the bank account(s) that the user can choose to switch bills to (if enabled)
  • Details for the bank account(s) that the user can choose for ACH payment methods, e.g. type, routing number, account number, and an account nickname when applicable (if enabled)

See Link Token Creation docs for full details on required fields.

POST /v1/link_tokens
Host: api.getpinwheel.com
Content-Type: application/json
Pinwheel-Version: 2025-07-08
x-api-secret: YOUR-API-SECRET
{
  "org_name": "YOUR APP NAME",
  "end_user_id": "my_user_12345",
  "allocation": {
    "targets": [
      {
        "name": "My Checking Account",
        "type": "checking",
        "routing_number": "07464755",
        "account_number": "193464372203"
      }
    ]
  },
 "cards": [
   {
      "card_name": "Card Name",
      "card_number": "12345678912345",
      "cvc": "111",
      "expiration_date": "05/29",
      "name_on_card": "Jane Doe",
      "card_zip_code": "12345",
      "billing_address": "123 Lane St",
      "billing_address2": "Apt 987",
      "city": "New York",
      "state": "NY"
    }
  ],
  "solution": "Bill Navigator",
  "features": [
  	"bill_switch",
  ]
}
POST /v1/link_tokens
Host: api.getpinwheel.com
Content-Type: application/json
Pinwheel-Version: 2025-07-08
x-api-secret: YOUR-API-SECRET
{
  "org_name": "YOUR APP NAME",
  "end_user_id": "my_user_12345",
  "end_user": {
    "platform_matching": {
      "first_name": "John",
      "last_name": "Smith",
      "email": "[email protected]"
    }
  },
  "solution": "Bill Navigator",
  "features": []
}

Step 3: Initialize Link

Use the Link token to open the Link modal in your client application. In addition to passing in the token, you can optionally pass several callback handlers.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.getpinwheel.com/pinwheel-v2.3.js"></script>
    <script>
      Pinwheel.open({
        linkToken: "INSERT LINK TOKEN",
          onSuccess: (result) => {
            console.log("Job succeeded!");
        },
      });
    </script>
  </head>
  <body></body>
</html>

The onSuccess callback handler is executed on job success and contains metadata about the bill switch or bill cancellation job. It is important to note that multiple bill switch/cancellation jobs can be executed within a single Pinwheel link flow.

{  
  "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",  // user's account on the platform
  "platform_id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256", // merchant (e.g. Netflix)
  "job": "bill_switch",  
  "params": {  
    "payment_method": {
      "type": "card",
      "card": {  
        "card_name": "Card Name",
        "card_num_last4": "2345",
      }  
    }  
  }  
}
{  
  "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",  // user's account on the platform
  "platform_id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256", // merchant (e.g. Netflix)
  "job": "bill_cancellation"
}

Step 4: Respond to Webhook Events

account.added

For both bill switches and bill cancellations, after a user successfully logs into the merchant, an account.added webhook event is published. An account_id is provided that represents the end user's account with the merchant they are switching/cancelling.

Using either the end_user_id or the link_token_id, you can associate the account with the user who logged in with Link. For example:

{
  "event": "account.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
    "end_user_id": "my_user_12345",
    "link_token_id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256",
    "platform_id": "fce3eee0-285b-496f-9b36-30e976194736", // refers to the merchant (e.g. Netflix)
    "platform_name": "Netflix",
    "created_at": "2021-01-12T02:36:01.287148+00:00",
    "connected": true
  }
}

See webhook specification for account.added for more details here.

bill_switch.added

Once the user has completed a bill switch, a bill_switch.added webhook event is published. For example:

{
  "event": "bill_switch.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d", // users's account with the merchant
    "end_user_id": "my_user_12345",
    "link_token_id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256",
    "name": "bill_switch",
    "platform_id": "fce3eee0-285b-496f-9b36-30e976194736", // refers to the merchant (e.g. Netflix)
    "platform_name": "Netflix",
    "timestamp": "2021-01-12T02:36:01.287148+00:00",
    "outcome": "success",
    "params": {  
      "is_integrated_switch": true,
      "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
    }  
  }
}

See webhook specification for bill_switch.added for more details here.

bill_switch.cancelled

Once the user has completed a bill cancellation, a bill_switch.cancelled webhook event is published. For example:

{
  "event": "bill_switch.cancelled",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d", // users's account with the merchant
    "end_user_id": "my_user_12345",
    "link_token_id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256",
    "name": "bill_switch",
    "platform_id": "fce3eee0-285b-496f-9b36-30e976194736", // refers to the merchant (e.g. Netflix)
    "platform_name": "Netflix",
    "timestamp": "2021-01-12T02:36:01.287148+00:00",
    "outcome": "success",
    "params": {  
      "is_integrated_cancellation": true,
    }  
  }
}

See webhook specification for bill_switch.cancelled for more details here.

Step 5: Returning users

Pinwheel will use end_user_id passed in the Link token to keep track of returning users for recurring transaction monitoring and continued updating. Users who have previously connected an account will maintain their list of recurring transactions. For this use case a link token can be created exactly as above.