Install
Install the package in your app or partner integration:
npm install @crossabc/reloadpi-browse-sdkDead simple rules
Use the SDK on the backend
Initialize and call the SDK from your server, route handlers, or API routes.
Do not expose private API keys
Keep API keys on the server. The frontend should only call your own API endpoints.
Fetch catalog from your own route
Your frontend should call your own route like /api/catalog/vouchers/offers.
Redirect users to ReloadPi
Users browse inside your app, then click Buy and complete the purchase on ReloadPi.
Integration flow
Recommended integration pattern for Next.js and similar apps:
Backend setup
Create one shared SDK instance on the server. A good place is lib/reloadpi/sdk.ts.
import { ShoppiBrowseSDK } from "@crossabc/reloadpi-browse-sdk";
const sdk = new ShoppiBrowseSDK({
baseUrl: process.env.RELOADPI_API_BASE_URL!,
apiKey: process.env.RELOADPI_API_KEY!,
shopUrl: process.env.NEXT_PUBLIC_RELOADPI_SHOP_URL || "https://reloadpi.com",
referralCode: process.env.NEXT_PUBLIC_RELOADPI_REFERRAL_CODE,
});
export default sdk;API route example
Expose your own API route. Your frontend should fetch from this route instead of calling ReloadPi directly.
Example file: app/api/catalog/vouchers/offers/route.ts
import { NextRequest, NextResponse } from "next/server";
import sdk from "@/lib/reloadpi/sdk";
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url);
const country = searchParams.get("country") || undefined;
const brand = searchParams.get("brand") || undefined;
const limit = Number(searchParams.get("limit") || 12);
const offset = Number(searchParams.get("offset") || 0);
const result = await sdk.vouchers.searchOffers({ country, brand, limit, offset });
return NextResponse.json({
items: result.items ?? [],
total: result.total ?? 0,
});
} catch (error) {
const message = error instanceof Error ? error.message : "Failed to load catalog.";
return NextResponse.json({ error: message }, { status: 500 });
}
}Frontend fetch example
In your client component, fetch from your own route and render the catalog items.
"use client";
import { useEffect, useState } from "react";
type Offer = { offerId: string; brandName?: string; brand?: string; name?: string; country?: string; };
export default function VoucherGrid() {
const [items, setItems] = useState<Offer[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function load() {
try {
const res = await fetch("/api/catalog/vouchers/offers?country=NG&limit=12", { cache: "no-store" });
const data = await res.json();
setItems(data.items ?? []);
} finally { setLoading(false); }
}
load();
}, []);
if (loading) return <p>Loading offers…</p>;
return (
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
{items.map((item) => (
<div key={item.offerId} className="rounded-xl border p-4">
<h3 className="font-semibold">{item.brandName ?? item.brand ?? item.name ?? item.offerId}</h3>
{item.country ? <p className="mt-1 text-sm text-stone-500">{item.country}</p> : null}
</div>
))}
</div>
);
}Buy link example
Use the SDK to generate the final ReloadPi product link with your referral code attached.
import sdk from "@/lib/reloadpi/sdk";
// Gift card / voucher
const voucherUrl = sdk.getBuyUrl("vouchers", "AMAZON_NG_001");
// → https://reloadpi.com/vouchers/offer/AMAZON_NG_001?ref=PARTNER_ABC
// Mobile top-up
const topupUrl = sdk.getBuyUrl("topups", "TOPUP_OFFER_ID");
// → https://reloadpi.com/topups/offer/TOPUP_OFFER_ID?ref=PARTNER_ABC
// eSIM — MUST use "esims" (plural). Using "esim" (singular) → 404 on ReloadPi.
const esimUrl = sdk.getBuyUrl("esims", "ESIM_OFFER_ID");
// → https://reloadpi.com/esims/offer/ESIM_OFFER_ID?ref=PARTNER_ABCprice.fixed or priceAmount are in the smallest currency unit (e.g. cents). Always divide by priceCurrencyDivisor (defaults to 100) before displaying: const displayPrice = offer.price.fixed / (offer.priceCurrencyDivisor ?? 100); A raw value of 3500 with divisor 100 → $35.00, not $3,500.getBuyUrl(), the ?ref= parameter is handled automatically by ReloadPi. The checkout happens on ReloadPi — do not build your own checkout.Available modules
🎟️ Vouchers
Gift card offers by brand, country, and filters.
searchOffers()getOfferById()listBrands()📱 Top-ups
Mobile top-up offers by country and operator.
searchOffers()getOfferById()listOperators()📶 eSIMs
eSIM plans and country-based browsing. Use sdk.esims.
⚠️ Price fields (price, cost) are in minor units (e.g. cents). Always divide: price / (priceCurrencyDivisor ?? 100) before displaying. Raw 3500 ÷ 100 = $35.00.
⚠️ Buy links: use getBuyUrl("esims", ...) — plural. Singular "esim" → 404.
Environment variables
Recommended environment variables for a Next.js integration:
# Server-only — never expose to the browser
RELOADPI_API_BASE_URL=https://shoppi-backend.onrender.com/api/catalog/
RELOADPI_API_KEY=your_private_api_key
# Safe to expose to the browser
NEXT_PUBLIC_RELOADPI_SHOP_URL=https://reloadpi.com
NEXT_PUBLIC_RELOADPI_REFERRAL_CODE=PARTNER_ABCRELOADPI_API_KEY— keep server-side only. Never in client bundles.NEXT_PUBLIC_RELOADPI_SHOP_URL— safe to expose, used for referral link generation.NEXT_PUBLIC_RELOADPI_REFERRAL_CODE— safe to expose for browser-visible referral flows.API access notes
CORS: partner domains may need to be whitelisted before direct access is allowed. Use the SDK server-side to avoid CORS issues entirely.
Authentication: the SDK sends your API key on requests automatically. Keep the key on the server.
Header used: x-api-key
shoppi-backend.onrender.com — this is intentional. The shopUrl config defaults to https://reloadpi.comso all referral links point to the consumer storefront correctly.Rate limits
Expecting higher volume? Contact us before launch.
Keys are scoped, rate-limited, and revocable at any time.
Troubleshooting
Quick summary
The simplest way to think about this SDK:
The SDK handles authentication using your configured API key, and ReloadPi handles referral attribution when you generate buy links.