Widget with API Customization

Combine widget UI with API-powered customization

For advanced use cases, you can combine the OZZOBiT Widget (for the user-facing UI) with the Whitelabel API (for server-side customization). This hybrid approach gives you the best of both worlds: a polished, maintained UI with full backend control.

When to Use This Approach

ScenarioBenefit
Dynamic pricingFetch real-time quotes from API and pre-fill widget amounts
Custom KYC flowHandle KYC via API but use widget for payment
Order managementCreate orders via API, let widget handle payment collection
User data syncPre-populate widget using data fetched from your backend
Rate limitingServer-side quote caching reduces API calls from client

Implementation Pattern

Fetch Data Server-Side

quote-api-route.tstypescript
// app/api/OZZOBiT/quote/route.ts
import { NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url)
  const cryptoCurrency = searchParams.get('crypto') || 'ETH'
  const fiatAmount = searchParams.get('amount') || '100'
  const countryCode = searchParams.get('country') || 'US'

  // Call OZZOBiT Lookup API for quote
  const quoteResponse = await fetch(
    `https://OZZOBiT.com/api/api/v2/lookup/quote?${new URLSearchParams({
      partnerApiKey: process.env.OZZOBiT_PUBLIC_KEY!,
      fiatCurrency: 'USD',
      cryptoCurrency,
      fiatAmount,
      network: 'ethereum',
      quoteCountryCode: countryCode,
    })}`
  )

  const quote = await quoteResponse.json()

  // Apply your custom business logic
  const adjustedQuote = {
    ...quote,
    // Add your markup or discount
    yourFee: calculateYourFee(quote.fiatAmount),
    displayPrice: applyPricingRules(quote),
  }

  return Response.json(adjustedQuote)
}

Render Widget with Customized Parameters

BuyCryptoSection.tsxtsx
// components/BuyCryptoSection.tsx
'use client'

import { useState, useEffect } from 'react'
import dynamic from 'next/dynamic'

const OZZOBiTWidget = dynamic(() => import('./OZZOBiTWidget'), { ssr: false })

interface BuyCryptoProps {
  walletAddress: string
}

export default function BuyCryptoSection({ walletAddress }: BuyCryptoProps) {
  const [quote, setQuote] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    async function fetchQuote() {
      try {
        const res = await fetch('/api/OZZOBiT/quote?crypto=ETH&amount=100')
        const data = await res.json()
        setQuote(data)
      } finally {
        setLoading(false)
      }
    }
    fetchQuote()
  }, [])

  if (loading) return <div>Loading pricing...</div>

  return (
    <div>
      {/* Your custom UI showing quote info */}
      {quote && (
        <div className="quote-display">
          <p>1 ETH = ${quote.responseValue?.toFixed(2)} USD</p>
          <p>Your price includes a small platform fee</p>
        </div>
      )}

      {/* Launch OZZOBiT Widget with pre-filled values */}
      <OZZOBiTWidget
        config={{
          apiKey: process.env.NEXT_PUBLIC_OZZOBiT_API_KEY!,
          productsAvailed: 'BUY',
          network: 'ethereum',
          defaultCryptoCurrency: 'ETH',
          defaultFiatCurrency: 'USD',
          walletAddress,
          fiatAmount: quote?.fiatAmount || 100,
          partnerOrderId: generatePartnerOrderId(),
        }}
        onSuccess={handleSuccess}
        onFailure={handleFailure}
      />
    </div>
  )
}

function generatePartnerOrderId(): string {
  return `ORDER-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
}

Handle Events and Sync with Backend

typescripttypescript
// After widget success/failure:
async function handleSuccess(orderData: any) {
  // 1. Show success state to user
  showSuccessUI(orderData)
  
  // 2. Sync order status with your backend
  await fetch('/api/orders/sync', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      OZZOBiTOrderId: orderData.id,
      partnerOrderId: orderData.partnerOrderId,
      status: 'COMPLETED',
      cryptoAmount: orderData.cryptoAmount,
      fiatAmount: orderData.fiatAmount,
    }),
  })
  
  // 3. Trigger any post-purchase actions
  await triggerPostPurchaseHooks(orderData)
}
ℹ️
Benefits of Hybrid Approach
  • No need to build and maintain your own payment UI
  • Automatic updates when OZZOBiT adds new features/payment methods
  • Full control over data flow through your backend
  • Can implement custom business logic around quotes and orders
  • Simpler compliance - OZZOBiT handles KYC in the widget