Skip to content

upbudgetdev/belvo-js

Repository files navigation

@upbudget/belvo-js

React and Next.js SDK for Belvo's Open Finance widget integration.

Installation

pnpm add @upbudget/belvo-js swr
npm install @upbudget/belvo-js swr
yarn add @upbudget/belvo-js swr

Quick Start

Next.js (Recommended)

// app/providers.tsx
'use client';

import { BelvoNextProvider } from '@upbudget/belvo-js/nextjs';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <BelvoNextProvider
      getAccessToken={async () => {
        const res = await fetch('/api/belvo/access-token');
        return res.json();
      }}
    >
      {children}
    </BelvoNextProvider>
  );
}
// app/connect/page.tsx
'use client';

import { useBelvoNextWidget } from '@upbudget/belvo-js/nextjs';

export default function ConnectPage() {
  const { connect, scriptReady } = useBelvoNextWidget({
    external_id: 'user-123',
    onSuccess: (link, institution) => {
      console.log('Connected:', link, institution);
    },
  });

  return (
    <button onClick={() => connect()} disabled={!scriptReady}>
      Connect Bank Account
    </button>
  );
}

React

// App.tsx
import { BelvoWidgetProvider } from '@upbudget/belvo-js/react';

function App() {
  return (
    <BelvoWidgetProvider
      getAccessToken={async () => {
        const res = await fetch('/api/belvo/access-token');
        return res.json();
      }}
    >
      <ConnectButton />
    </BelvoWidgetProvider>
  );
}
// ConnectButton.tsx
import { useBelvoWidget } from '@upbudget/belvo-js/react';

function ConnectButton() {
  const { connect, scriptReady } = useBelvoWidget({
    external_id: 'user-123',
    onSuccess: (link, institution) => {
      console.log('Connected:', link, institution);
    },
  });

  return (
    <button onClick={() => connect()} disabled={!scriptReady}>
      Connect Bank Account
    </button>
  );
}

Analytics Integration

Track widget events with any analytics provider (PostHog, Segment, Amplitude, etc.):

import posthog from 'posthog-js';
import { BelvoNextProvider, BelvoEvents } from '@upbudget/belvo-js/nextjs';

<BelvoNextProvider
  getAccessToken={getAccessToken}
  analytics={{
    track: (event, properties) => posthog.capture(event, properties),
  }}
>
  {children}
</BelvoNextProvider>

Available Events

Event Description
belvo_widget_opened Widget was opened
belvo_connection_success User successfully connected an account
belvo_connection_exit User closed the widget
belvo_widget_event Generic widget event
belvo_script_loaded Belvo SDK script loaded
belvo_script_error Failed to load Belvo SDK script
belvo_token_fetch_start Started fetching access token
belvo_token_fetch_success Access token fetched successfully
belvo_token_fetch_error Failed to fetch access token

Pre-built Button Component

Use the included button component with custom styling via asChild:

import { BelvoConnectButton } from '@upbudget/belvo-js/nextjs';

// Default button
<BelvoConnectButton
  config={{
    external_id: 'user-123',
    onSuccess: (link, institution) => console.log(link, institution),
  }}
/>

// Custom button with asChild
<BelvoConnectButton
  asChild
  config={{ external_id: 'user-123' }}
>
  <MyCustomButton>Link your bank</MyCustomButton>
</BelvoConnectButton>

API Reference

Provider Props

interface BelvoWidgetProviderProps {
  children: ReactNode;
  getAccessToken: () => Promise<{ access: string; refresh: string }>;
  analytics?: {
    track(event: string, properties?: Record<string, unknown>): void;
  };
}

Widget Configuration

interface BelvoWidgetProps {
  locale?: 'pt' | 'en';
  integration_type?: 'openfinance';
  external_id?: string;
  refresh_rate?: '6h' | '12h' | '24h';
  mode?: 'webapp' | 'single';
  brand?: {
    logoUrl?: string;
    primaryColor?: string;
  };
  onSuccess?: (link: string, institution: string) => void;
  onExit?: (data: unknown) => void;
  onEvent?: (data: unknown) => void;
}

Hooks

Next.js

import { useBelvoNext, useBelvoNextWidget } from '@upbudget/belvo-js/nextjs';

// Low-level access
const { open, scriptReady, scriptError } = useBelvoNext();

// With default config
const { connect, scriptReady, scriptError } = useBelvoNextWidget(config);

React

import { useBelvo, useBelvoWidget } from '@upbudget/belvo-js/react';

// Low-level access
const { open, scriptReady, scriptError } = useBelvo();

// With default config
const { connect, scriptReady, scriptError } = useBelvoWidget(config);

Backend Setup

Your backend needs to provide an endpoint that returns Belvo access tokens:

// app/api/belvo/access-token/route.ts (Next.js App Router)
import { NextResponse } from 'next/server';

export async function GET() {
  const response = await fetch('https://api.belvo.com/api/token/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      id: process.env.BELVO_SECRET_ID,
      password: process.env.BELVO_SECRET_PASSWORD,
    }),
  });

  const data = await response.json();
  return NextResponse.json(data);
}

Requirements

  • React 18.3.1+
  • Next.js 13.5.7+ (for Next.js integration)
  • SWR 2.2.0+

License

MIT

About

Belvo Hosted Widget SDK

Resources

License

Stars

Watchers

Forks

Contributors