/** * 01 — Quickstart: catalog → checkout → status * * Minimum viable flow for a guest checkout. Run with: * * GAMECORE_API_KEY=gc_live_... bun run examples/01-quickstart.ts * * Don't put `apiKey` in client-side bundles — proxy through your own * backend (Next.js route, Express, ElysiaJS, etc.). */ import { GameCoreClient } from "@gamecore-api/sdk"; const gc = new GameCoreClient({ apiKey: process.env.GAMECORE_API_KEY!, baseUrl: "https://api.gamecore-api.tech", }); // 1. Browse the catalog (first 12 in-stock games) const { data: games } = await gc.catalog.getGames({ limit: 12, inStockOnly: true, }); console.log( "games:", games.map((g) => g.slug), ); // 2. Open a game detail page — pick the first in-stock game from the list const game = games[0]; if (!game) { console.log("No in-stock games for this site. Done."); process.exit(0); } await gc.catalog.getGame(game.slug); // detail page lookup (returns GameDetail) // 3. Pull products for that game — getGame returns metadata, not products. const products = await gc.catalog.getProducts(game.slug); const product = products[0]; if (!product) { console.log(`Game ${game.slug} has no products. Done.`); process.exit(0); } console.log("picked product:", product.id, product.name, "price:", product.price); // 4. Create checkout (guest — pass email; no Telegram/VK login required). // For balance-based payment, the user must be authenticated first. // // The SDK's `CheckoutRequest.items` type currently marks several // fields optional, but the API's body schema (TypeBox) rejects // requests that omit them: // • productId — REQUIRED, the supplier product // • gameId — REQUIRED, the game slug. Drives routing for // Steam top-ups, SuperPass bundles, and // Robux-via-pass; the backend also reads it // directly outside those paths. // • gameName — REQUIRED by body validation (maxLength 500). // • productName — REQUIRED by body validation (maxLength 500). // • deliveryData — REQUIRED object (can be `{}`). For Steam / // Roblox / login-required products it carries // account name, server id, top-up currency, etc. // • amount — optional. Quantity for fixed-price items // (default 1) OR the top-up amount in local // currency for Steam / variable-amount products. const checkout = await gc.checkout.create({ email: "buyer@example.com", items: [ { productId: product.id, gameId: game.slug, gameName: game.name, productName: product.name, amount: 1, deliveryData: {}, }, ], paymentMethod: "antilopay", // gateway slug from checkout.getPaymentMethods() }); if (!checkout.payment) { console.error("Checkout did not return a payment record:", checkout); process.exit(1); } console.log("payment code:", checkout.payment.code); console.log("payment URL:", checkout.payment.paymentUrl); // 5. Poll status until the user pays (or 5 minutes pass) for (let i = 0; i < 30; i++) { const status = await gc.checkout.getStatus(checkout.payment.code); console.log(`[${i}] status=${status.payment.status}`); if ( status.payment.status === "completed" || status.payment.status === "failed" || status.payment.status === "cancelled" ) { console.log( "orders:", status.orders.map((o) => ({ code: o.code, status: o.status })), ); break; } await new Promise((r) => setTimeout(r, 10_000)); }