Next.js Gift Card Store: From API Key to Live Sales
Resellers building a web storefront today increasingly reach for Next.js: React-driven pages on the front, API route handlers on the back, and instant global deployment on Vercel. The FazerCards REST API maps cleanly onto this stack — catalog fetches run server-side to keep your API key out of the browser, and a simple route handler doubles as your webhook endpoint. This walkthrough covers five practical steps, from an empty repository to a store that fetches live product data, processes orders, and delivers codes automatically.
Prerequisites
You need Node.js 18+, a package manager, and an active FazerCards account. Start a free 5-day Gold trial if you have not subscribed yet — it gives full API and catalog access with no credit card required. Install the official Node SDK by running npm install fazercards in your project root, and add your API key to a .env.local file — Next.js keeps variables without the NEXT_PUBLIC_ prefix out of client bundles, so as long as the key stays in server code, the X-Api-Key header never touches the browser. Keep the API reference open alongside this guide.
If the interplay between REST calls and async webhook delivery is new territory, this overview of the API and webhooks is a quick read before you write your first request.
Step 1: Bootstrap the project and configure secrets
Run npx create-next-app to scaffold a new App Router project. Once the scaffold is ready, create .env.local at the root with two entries:
- FAZERCARDS_API_KEY — your API key from the FazerCards dashboard
- WEBHOOK_SECRET — the signing secret configured in your webhook settings
In a Client Component such a variable is simply undefined, so the key cannot leak by accident — just never give it the NEXT_PUBLIC_ prefix. For a stronger guard, add the server-only package to your API helper module: importing that module from a Client Component then fails the build. All FazerCards requests — catalog fetches, order placement, balance checks — must live in Server Components, Server Actions, or Route Handlers. Run npm run dev to confirm the scaffold starts before moving on.
Step 2: Fetch and display the catalog
Gift card products are accessed via two calls: GET /giftcards to retrieve a list of categories, then GET /giftcards/cards?category_id=… to retrieve the offers within a category. Each offer carries a card_id, a price_usd, and a stock count. Top-up products follow the same pattern via GET /topups then GET /topups/offers.
Build a Server Component that calls these endpoints and renders a product grid. Because the fetch runs on the server, the page is fully rendered on first load — fast on mobile, indexable by search engines, and free of client-side spinners. Cache these fetches with a revalidate window of a few minutes so each visitor does not trigger its own API call, and re-check stock right before checkout. Link each product to its own detail page using Next.js dynamic segments. The FazerCards catalog and gift card service overview are worth linking from your store's landing section so buyers can see the full product range.
Step 3: Place orders from a Server Action
Collect any required account fields — typically a player ID for top-up products — and take payment first. Server Actions are public endpoints, so never let one place an order on the buyer's word alone: call FazerCards only after your payment provider confirms the charge, otherwise anyone could spend your balance. That server-side code calls POST /giftcards/order (fields: category_id, card_id, quantity) or POST /topups/order (fields: category_id, offer_id, plus the account identifier fields). Include an Idempotency-Key header on every order call — a UUID you generate once per purchase and persist — so that a duplicate submission returns the original order instead of charging twice. Keys stay valid for seven days.
The API responds immediately. Fast products return with status completed and the codes inline; show them to the buyer right away. Slower products return as processing — the webhook in the next step handles delivery. If the status is failed, the wholesale amount normally goes back to your balance: tell the buyer and refund them or offer another product. Contact FazerCards support with the order ID if a failed order is not credited back, or if a delivered code later fails to redeem; verified cases get a replacement or a balance credit. For top-up product families, see platform top-up services. Check your funding at any time via GET /balance.
Step 4: Verify signatures and deliver codes via webhook
For orders, FazerCards sends two webhook events: order.created when an order is recorded, and order.status_changed when the status updates. The event body carries the order_id, type, status, and previous_status — it carries no codes. When you receive an order.status_changed event with status completed, call GET /orders/:orderId to retrieve the codes and deliver them to your customer.
Create a Route Handler at app/api/webhooks/fazercards to receive these events. Every incoming request must be verified before you act on it:
- Read the raw request body with await request.text() before parsing JSON — the signature is computed over the exact bytes received.
- Compute HMAC-SHA256 of that raw body using your WEBHOOK_SECRET — or use the verification helper in the fazercards package.
- Compare the hex result to the X-Webhook-Signature header (formatted as sha256= followed by the lowercase hex digest), using a constant-time comparison.
- Reject the request with a 401 response if the signatures do not match; return 200 to acknowledge a valid event.
FazerCards retries unacknowledged deliveries after 1, 5, and 30 minutes, using the same event_id each time. Make your handler idempotent — check whether the order was already delivered before writing codes to your database or triggering a notification. Full signature details are in the webhooks reference.
Step 5: Deploy to production and run your first live test
Push the repository to GitHub and connect it to Vercel. Under Project → Environment Variables, add FAZERCARDS_API_KEY and WEBHOOK_SECRET as Production variables — .env.local stays local and is never uploaded. After deployment, paste your production webhook URL into the FazerCards webhook settings panel.
Place a small test order through your live store. There is no sandbox: every order is a live transaction on your FazerCards balance, so use a low-value product for the initial test. Check Vercel's Functions logs to confirm the webhook arrives, verify the X-Webhook-Signature comparison passes, and confirm that the codes appear in your delivery flow. See /docs for the full order status reference.
One thing to watch on serverless hosting: the FazerCards API sits behind DDoS protection, and serverless platforms send requests from shared, changing IP addresses, so an order call can occasionally be answered with a 403 challenge page instead of JSON. Log the status of every API response and treat that case as an order that was not placed. If it repeats, contact FazerCards support with the outgoing IP, or run the API calls from a small server with a fixed address.
For resilient production traffic, consider inserting a lightweight queue between the webhook receiver and your delivery logic — receive and persist the raw event immediately, then process delivery asynchronously. This protects against downstream timeouts.
What you have at the end
After these five steps you have a Next.js storefront that serves a live gift card catalog, places orders securely server-side, verifies webhook signatures, and delivers codes automatically. The same architecture extends to new product types, additional regions, and higher order volumes — just add product families through the catalog API; categories are split by brand and region, so you choose which ones to list.
Claim your free 5-day Gold trial — no credit card required, full API access from day one, and live delivery to verify your integration end to end. If you are still choosing your channel, the who FazerCards is for page is a quick overview.