Overview
The FoxReload REST API is the backbone of any automated digital goods operation. Whether you're building a standalone storefront, a Telegram bot, or a WooCommerce plugin, every feature routes through the same set of API endpoints. This guide is a technical reference for the integration points that matter most when selling Google Play Gift Cards.
Base URL: https://api.foxreload.com/api/v1
All requests must use HTTPS. HTTP is rejected at the transport layer.
Authentication
FoxReload uses Bearer token authentication. Your API key is issued when your wholesale account is approved.
Authorization: Bearer fr_live_xxxxxxxxxxxxxxxxxxxxxxxx
Key Types
| Key Prefix | Environment | Use Case |
|---|---|---|
fr_live_ |
Production | Real orders, real money |
fr_test_ |
Sandbox | Integration testing, no charges |
Always develop and test with fr_test_ keys. Switch to fr_live_ only when going to production.
Key Security Rules
- Store keys in environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault)
- Rotate keys every 90 days minimum
- Never log raw API keys โ mask them in application logs
- Create separate keys per integration (bot, web shop, admin panel) so you can revoke individually
Core Endpoints
GET /catalog
Returns available products with current prices and stock.
GET /api/v1/catalog?category=google-play&in_stock=true
Use for: building your product listing, syncing prices and stock.
Poll frequency: every 15โ30 minutes for stock; every 30โ60 minutes for prices.
GET /catalog/:id
Returns a single product by its FoxReload ID.
GET /api/v1/catalog/gp-usd-25
Use for: pre-order stock check on checkout page.
POST /orders
Places an order and receives codes in the response (for in-stock, instant-delivery items).
POST /api/v1/orders
Content-Type: application/json
{
"product_id": "gp-usd-25",
"quantity": 1,
"external_order_id": "myshop-ord-00492",
"webhook_url": "https://myshop.com/webhooks/foxreload"
}
Critical fields:
| Field | Required | Description |
|---|---|---|
product_id |
Yes | FoxReload catalog ID |
quantity |
Yes | Number of codes (1โ50 per request) |
external_order_id |
Recommended | Your internal order ID for reconciliation |
webhook_url |
Optional | Override default webhook for this order |
GET /orders/:id
Check the status of an existing order.
GET /api/v1/orders/fr-ord-98712
{
"order_id": "fr-ord-98712",
"external_order_id": "myshop-ord-00492",
"status": "completed",
"product_id": "gp-usd-25",
"quantity": 1,
"codes": [
{ "code": "ABCD-EFGH-IJKL-MNOP", "serial": "SN789012" }
],
"created_at": "2026-05-27T14:30:00Z",
"completed_at": "2026-05-27T14:30:01Z"
}
GET /balance
Returns your current wholesale account balance.
GET /api/v1/balance
{
"balance": 1250.00,
"currency": "USD",
"credit_limit": 0
}
Use for: pre-flight check before large orders; dashboard balance display.
Idempotency โ Critical for Order Reliability
If your order request times out, do not simply retry. You might place the same order twice and be charged twice. Use the Idempotency-Key header:
POST /api/v1/orders
Idempotency-Key: myshop-ord-00492-attempt-1
If you send the same Idempotency-Key within 24 hours, the API returns the original response instead of creating a duplicate order. Always generate the idempotency key from your internal order ID.
import hashlib
def idempotency_key(order_id: str, attempt: int = 1) -> str:
raw = f"{order_id}-attempt-{attempt}"
return hashlib.sha256(raw.encode()).hexdigest()[:32]
Rate Limits
| Endpoint | Limit |
|---|---|
| GET /catalog | 60 requests/minute |
| POST /orders | 30 requests/minute |
| GET /orders/:id | 120 requests/minute |
| GET /balance | 30 requests/minute |
Rate limit headers are returned on every response:
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27
X-RateLimit-Reset: 1748347800
If you exceed limits, implement exponential backoff:
import time, random
def request_with_backoff(fn, max_retries=5):
for attempt in range(max_retries):
response = fn()
if response.status_code == 429:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
else:
return response
raise Exception("Max retries exceeded")
Error Codes Reference
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Account balance too low to fulfill this order.",
"details": {
"required": 22.75,
"available": 10.00
}
}
}
| Code | HTTP Status | Resolution |
|---|---|---|
INVALID_API_KEY |
401 | Regenerate key in dashboard |
INSUFFICIENT_BALANCE |
402 | Top up wholesale account |
PRODUCT_NOT_FOUND |
404 | Re-sync catalog |
OUT_OF_STOCK |
409 | Check inventory, retry later |
RATE_LIMIT_EXCEEDED |
429 | Back off and retry |
ORDER_DUPLICATE |
409 | Idempotency key already used |
INTERNAL_ERROR |
500 | Retry with backoff; contact support if persistent |
Webhooks vs Polling
For order status, prefer webhooks over polling:
| Webhooks | Polling | |
|---|---|---|
| Latency | < 1 second | Up to poll interval |
| Server load | Low | High at scale |
| Complexity | Medium (signature verification) | Low |
| Reliability | Requires public endpoint | Works anywhere |
See the dedicated webhooks guide for implementation details.
Integration Checklist
- Use
fr_test_key during development - Always send
external_order_idfor reconciliation - Implement idempotency keys on all POST /orders calls
- Handle 402 (balance) and 409 (out of stock) gracefully
- Implement rate-limit backoff
- Verify webhook signatures before trusting payloads
- Monitor your balance and set auto-alerts at a minimum threshold
See Also
- How to connect Google Play Gift Cards to your shop via API
- How to set up webhooks for digital code delivery
- How to implement instant delivery for Google Play Gift Cards
Get your API key today. Apply for a FoxReload wholesale account and start building your integration with full sandbox access.

