Back to samples
Pinnacle Financial logo
Finance

Pinnacle Financial

Card controls, statements, branches — over RCS

4 min read

Note: the visuals in this demo recording have since been refreshed with sharper brand assets. The conversation flow is identical to what you'll get from a fresh clone.

What's inside

  • View account balance, recent payments, and credit/debit cards
  • Lock and unlock cards inline
  • Pull recent monthly statements with downloadable PDFs
  • ATM and branch finder with hours and location cards
  • Configurable bank brand assets via env vars

A banking services chatbot that runs over RCS. Customers can view recent payments, manage their cards (lock, unlock, activate, report fraud), pull recent statements, make a payment, view branch hours, and find ATM and branch locations — all from inside the messages app.

This guide walks you from a fresh clone to a working bank demo on your phone in under 10 minutes.

What you'll build

  • A Pinnacle RCS agent for self-service banking
  • Card management — view, lock, unlock, activate, report fraud — inline
  • Recent statements with downloadable PDFs and a "more statements" view
  • Payment + transaction history flow
  • ATM and branch finder with hours and location cards
  • All brand assets (logo, cards, statement PDFs) editable from one file

Prerequisites

1. Clone and install

Bash
git clone https://github.com/pinnacle-samples/Pinnacle-Financial
cd Pinnacle-Financial
npm install

2. Configure environment

Bash
cp .env.example .env
env
PINNACLE_API_KEY=your_pinnacle_api_key_here
PINNACLE_AGENT_ID=your_agent_id_here
PINNACLE_SIGNING_SECRET=your_signing_secret_here
TEST_MODE=false
PORT=3000

Brand assets (logo, card images, statement PDFs, branch photos) are all hardcoded in lib/brand/data.ts. Edit that file directly to swap in your own URLs.

3. Expose your webhook

Bash
ngrok http 3000

4. Connect the webhook

In the Webhooks dashboard:

  1. Add https://<your-tunnel-domain>/webhook
  2. Attach it to your RCS agent
  3. Copy the signing secret into PINNACLE_SIGNING_SECRET

5. Run it

Bash
npm run dev

Send MENU or START to your agent. You'll see the Pinnacle Financial main menu with My Card, Payments, Statements, Branches & ATMs, and more.

How the pieces fit together

Pinnacle-Financial/
├── server.ts              # Express bootstrap
├── router.ts              # /webhook POST — verifies + dispatches
├── lib/
│   ├── rcsClient.ts       # PinnacleClient instance
│   ├── baseAgent.ts       # Shared send + typing helpers
│   ├── typing.ts          # Fire-and-forget typing indicator
│   ├── agent.ts           # Agent — every action handler
│   └── brand/
│       ├── data.ts        # Business info, payments, statements, locations, cards
│       └── types.ts       # Card, Payment, Statement, Location

Action handlers

ActionWhat it does
showMainMenuLanding card with all entry points
viewCardActive card carousel
lockCard / unlockCard / activateCardCard state mutations
reportFraudFraud report flow
viewPaymentsRecent transactions
makePayment / processPaymentBill / transfer payment flow
viewStatements / moreStatementsStatement list with pagination
viewLocations / viewHoursATM and branch finder + hours

Customize the bank brand

Everything brand-specific lives in lib/brand/data.ts:

  • business — bank name, logo, address
  • recentPayments — seed data for transaction history
  • statements — monthly statement metadata + PDF URLs
  • locations — ATMs and branches with hours and lat/lng
  • cards — credit and debit cards with last-4 and lock state
  • hours — branch hours image used in the location cards

Edit any of these constants in lib/brand/data.ts to rebrand the bank end-to-end.

Card lock flow

Locking and unlocking a card is the simplest example of mutating state in this sample. Look at lib/agent.ts to see how the action handler updates the in-memory cards array, then re-renders the card carousel with the new state.

Going to production

  • NEVER transmit real account numbers, balances, or PII without a signed BAA / DPA
  • Wire the cards/statements/payments to your core banking platform via authenticated API calls
  • Set TEST_MODE=false and submit your agent for carrier approval
  • Replace the in-memory state with your real customer database

Resources

© 2026 Pinnacle Software Development, Inc.