Console →
Example Integrations

VoiceShift AI (Voice AI Integration Example)

VoiceShift (ChangeVoice) is a stunning, high-fidelity AI video dubbing workspace built to showcase a complete real-world integration of the SettleSettle SDK. It manages idempotent user profile syncing, dynamic credits-based billing, multi-rail checkouts (Paystack + Solana), and rewarded ad fallbacks.

All billing rates, package sizes, and lookups are fetched dynamically from the SettleSettle cloud dashboard to ensure zero hardcoded values in the codebase.

View the Repository on GitHub →

Core Integration Blueprint#

  • Dynamic Cost Resolution: Costs are queried live from the active rules defined in your SettleSettle dashboard (e.g. charging 10 credits per minute of video processed).
  • Debit-Before-Processing (The Gatekeeper): Enforces credit validation *before* executing expensive AI dubbing GPU/CPU tasks. If the wallet drops below the threshold, the SDK throws InsufficientCreditsError (402).
  • Usage Tracking Telemetry: Emits a non-blocking asynchronous usage event after successful execution, allowing zero-latency performance.
  • Flexible Refills: Supports traditional card payments via Paystack and next-gen Solana Web3 USDC peer-to-peer transfers.

Step-by-Step Integration Recipes#

1. Setup Singleton Client#

Configure SettleSettle in a dedicated file (lib/settle.ts) to avoid duplicate connections in local Next.js HMR:

typescript
import { SettleSettle } from 'settlesettle'

// 1. Declare 'settle' in the global scope so it's typed everywhere
declare global {
  var settle: SettleSettle;
}

// 2. Resolve singleton instance (preventing double instantiation in Next.js HMR development mode)
const settleInstance =
  globalThis.settle ||
  new SettleSettle({
    apiKey: process.env.SETTLESETTLE_API_KEY!,
    baseUrl: process.env.SETTLESETTLE_BASE_URL,
  })

// 3. Assign to globalThis so it is globally accessible directly as 'settle'
globalThis.settle = settleInstance

// 4. Export it for standard import patterns as well
export const settle = settleInstance

2. Sync User Idempotently#

Sync the logged-in user profile with SettleSettle's directory:

typescript
// app/api/settle/sync-user/route.ts
import { settle } from '@/lib/settle'
import { NextResponse } from 'next/server'

export async function POST() {
  const user = await settle.users.sync({
    externalUserId: 'voiceshift_demo_user',
    email: 'demo@voiceshift.dev',
    name: 'Demo Creator',
  })
  return NextResponse.json({ ok: true, data: user })
}

3. Debit-Before-Processing & Telemetry Metering#

typescript
// app/api/settle/dub/route.ts
import { settle } from '@/lib/settle'
import { InsufficientCreditsError } from 'settlesettle'
import { NextResponse } from 'next/server'

export async function POST(req: Request) {
  const userId = 'voiceshift_demo_user'
  
  try {
    const { videoUrl, language, durationMinutes } = await req.json()
    const duration = Math.ceil(Number(durationMinutes))

    // 1. Fetch live rules from bootstrap configuration
    const bootstrapData = await settle.billing.bootstrap(userId)
    const activeRules = bootstrapData.walletState?.activeRules || []
    
    // Find the rule for event billing
    const billingRule = activeRules.find(r => r.eventType === 'VIDEO_MINUTE_PROCESSED')
    const costPerMinute = billingRule ? billingRule.cost : 10
    const creditsRequired = duration * costPerMinute

    // 2. Enforce pre-debit check
    await settle.wallet.debit(userId, {
      amount: creditsRequired,
      description: `Dubbed ${duration} min video → ${language.toUpperCase()}`,
    })

    // 3. Process video dubbing (GPU/CPU action)
    const result = await processAIDubbing(videoUrl, language, durationMinutes)

    // 4. Emit non-blocking usage event
    settle.events.track({
      userId,
      eventType: 'VIDEO_MINUTE_PROCESSED',
      quantity: duration,
    })

    return NextResponse.json({ ok: true, data: result })

  } catch (error) {
    if (error instanceof InsufficientCreditsError) {
      return NextResponse.json({
        code: 'INSUFFICIENT_CREDITS',
        currentBalance: error.currentBalance,
      }, { status: 402 })
    }
    return NextResponse.json({ error: error.message }, { status: 500 })
  }
}

Clone & Run Locally#

To spin up VoiceShift locally:

  1. Clone the repository and navigate inside:
bash
git clone https://github.com/Ek0m/changevoice.git
cd changevoice
  1. Install dependencies:
bash
npm install
  1. Configure your local environment in .env.local:
env
SETTLESETTLE_API_KEY=ss_live_xxxxxxxxxxxxxxxxxxxxxxxx
SETTLESETTLE_BASE_URL=https://api.settlesettle.uno/v1
  1. Run the Next.js development server:
bash
npm run dev