Reference
Base URL: https://api.sonofutred.com.
Every request needs X-API-Key or
Authorization: Bearer <key>.
https://api.sonofutred.com
(example: POST https://api.sonofutred.com/orders).
Catalog — GET /services
Games and what each one needs in the order body (userId, zoneId, serverId, …). Unavailable games don’t show up.
Response: { "success": true, "services": [ ... ] }
Each service includes: productName, slug, gameName, required (array of field + label), status. Some lines may also include serverIdOptions or regionOptions when a server/region is required. Pack ids: Games & PIDs.
curl -X GET "https://api.sonofutred.com/services" -H "X-API-Key: YOUR_API_KEY"
GET /products and /catalog
Alias: GET /catalog returns the same payload as GET /products.
The product database for ordering: one row per active pack with a stable
id (GWPID). That value is what you pass as pid on
POST /orders. Rows include slug, gameName, serviceName, price, stock where applicable, etc.
For gamekey and giftcard (and PUBG stock packs), each row also includes
quantity = live available stock, plus inStock, quantityMin, and
quantityMax (capped by stock, max 500 per order).
curl -X GET "https://api.sonofutred.com/products" -H "X-API-Key: YOUR_API_KEY"
// gamekey / giftcard example
{
"success": true,
"products": [
{
"id": "GWPK60",
"slug": "gamekeypubg",
"gameName": "Game Keys — PUBG Mobile",
"serviceName": "60UC",
"category": "gamekeypubg",
"price": 0.858,
"quantityMin": 1,
"quantityMax": 42,
"inStock": true,
"quantity": 42,
"status": "active"
}
]
}
products[i].id from this response into the order body as pid (or PID).
GET /my-ip
Your public IP as our side sees it.
curl -X GET "https://api.sonofutred.com/my-ip" -H "X-API-Key: YOUR_API_KEY"
// { "success": true, "ip": "203.0.113.4" }
GET /balance GET
Check your account balance (USD). Read-only; top up in Telegram.
curl -X GET "https://api.sonofutred.com/balance" -H "X-API-Key: YOUR_API_KEY"
// 200
{
"success": true,
"balanceUsd": 12.5,
"currency": "USD"
}
POST /orders POST
Submit / create an order. Game is picked from the pid (catalog id).
On success you get the same invoice shape as GET /orders/:orderId.
Body (unified)
| Field | Notes |
|---|---|
pid / PID |
Required. GWPID from GET /products → id. |
trxid (or trxId, idtrx, idTrx) |
Your id for the order. New purchase → new trxid. |
userId / userID |
Required for most games (player / uid / Riot ID / live-app id / Zepeto username as defined by the line). |
zoneId |
Required for ML-style lines (numeric zone). |
serverId |
Required for GI / HSR / ZZZ / WUWA / IDV / Once Human region and similar. Once Human also accepts region shortcuts (eu, na, …). |
quantity |
Only for gamekey and giftcard kinds (1–500 per order). Over 500 → rejected with QUANTITY EXCEEDS MAX (no silent cap). |
idempotencyKey / idempotency |
Optional; if omitted, trxid is used for idempotency as implemented. |
curl -X POST "https://api.sonofutred.com/orders" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"pid":"GWPUBG60","userId":"51234567890","trxid":"ORD-1001"}'
Responses — submit / processing / completed
orderCreated: true means the order was accepted. Poll
GET /orders/:orderId while status is processing.
Stop on completed or cancelled. Empty fields may be omitted.
Accepted — still processing (200)
{
"orderCreated": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "processing",
"game": "pubg",
"packName": "60 UC",
"amountUsd": 0.99,
"durationSec": 1,
"userId": "51234567890"
}
Completed (200) — instant fulfillment, or after polling
{
"orderCreated": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "completed",
"game": "pubg",
"packName": "60 UC",
"amountUsd": 0.99,
"durationSec": 34,
"userId": "51234567890"
}
Gamekey / gift card completed (200) — includes delivered codes
{
"orderCreated": true,
"orderId": "GW-API-GK-A1B2C3-D4E5F6A7",
"status": "completed",
"game": "gamekey",
"packName": "60 UC Code",
"amountUsd": 0.95,
"durationSec": 2,
"codes": ["XXXX-XXXX-XXXX", "YYYY-YYYY-YYYY"]
}
Rejected at submit (400) — no order created
{
"orderCreated": false,
"status": "cancelled",
"game": "pubg",
"error": "INSUFFICIENT BALANCE"
}
Other submit failures
// 400
{ "success": false, "error": "INVALID BODY" }
{ "success": false, "error": "INVALID REQUEST" }
{ "success": false, "error": "UNKNOWN PID" }
{ "success": false, "error": "INVALID PACK" }
{ "success": false, "error": "GAME DISABLED" }
// 403 — trxid owned by another API user
{ "success": false, "code": "FORBIDDEN", "error": "FORBIDDEN" }
// 429 — same order still in flight
{ "success": false, "code": "DUPLICATE_IN_FLIGHT", "error": "DUPLICATE_IN_FLIGHT" }
// 503
{ "success": false, "code": "MAINTENANCE", "error": "MAINTENANCE" }
{ "success": false, "code": "API_ORDER_DISABLED", "error": "API_ORDER_DISABLED" }
Idempotent replay (200) — same trxid again
{
"orderCreated": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "completed",
"game": "pubg",
"packName": "60 UC",
"amountUsd": 0.99,
"durationSec": 120,
"userId": "51234567890",
"idempotentReplay": true
}
Walkthrough: Orders & status. Fixed subscription / special / CN PIDs: Games & PIDs.
Downtime: you may get 503 and MAINTENANCE or API_ORDER_DISABLED — see errors.
GET /history GET
Your last purchased history — recent orders for your account, newest first. Same invoice shape as
GET /orders/:orderId (and successful POST /orders). Single-order lookup:
GET /orders/:orderId.
Query: simple limit
Default limit=30 (min 1, max 200).
curl -G "https://api.sonofutred.com/history" \
-H "X-API-Key: YOUR_API_KEY" \
--data-urlencode "limit=25"
// 200
{
"success": true,
"count": 25,
"orders": [ { "orderId": "GW-API-PBG-…", "status": "completed", "game": "pubg", ... }, ... ]
}
Query: pagination
Pass page to switch to paged mode (optional pageSize, default 20, max 50). Response
includes total and hasMore.
curl -G "https://api.sonofutred.com/history" \
-H "X-API-Key: YOUR_API_KEY" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=20"
GET /orders/:orderId
after POST /orders (see
Guides: lifecycle & examples).
GET /orders/:orderId GET
Check status for one order on your account. Same invoice fields as a successful POST /orders.
curl -X GET "https://api.sonofutred.com/orders/GW-API-PBG-A1B2C3-D4E5F6A7" \
-H "X-API-Key: YOUR_API_KEY"
Still processing (200)
{
"orderCreated": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "processing",
"game": "pubg",
"packName": "60 UC",
"amountUsd": 0.99,
"durationSec": 45,
"userId": "51234567890"
}
Completed (200)
{
"orderCreated": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "completed",
"game": "pubg",
"packName": "60 UC",
"amountUsd": 0.99,
"durationSec": 52,
"userId": "51234567890"
}
Cancelled / failed after placement (200)
{
"orderCreated": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "cancelled",
"game": "pubg",
"packName": "60 UC",
"amountUsd": 0.99,
"durationSec": 18,
"userId": "51234567890",
"error": "INVALID PLAYER",
"refunded": true
}
Not found (404)
{
"success": false,
"error": "ORDER NOT FOUND"
}
404 if the id does not belong to your account or does not exist.
Redeem & verify
These endpoints charge a small fee from your wallet (or use free ML quota). They do
not place a catalog top-up order. Always send a unique trxid;
replaying the same trxid returns the cached result with
idempotentReplay: true (no second charge). Empty fields may be omitted.
| Endpoint | Price |
|---|---|
POST /pubgvvfy |
$0.0017 per call |
POST /mlvfy |
First 20/day free, then $0.02 per call |
POST /rdmpubg |
$0.0017 per call |
success in the body. A lookup/redeem failure can still return
200 with success: false and status: "cancelled" (fee may already be deducted).
POST /pubgvvfy
Resolve / verify a PUBG player id (in-game name check) without placing an order.
{
"playerId": "51234567890",
"trxid": "CHK-PUBG-001"
}
curl -X POST "https://api.sonofutred.com/pubgvvfy" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"playerId":"51234567890","trxid":"CHK-PUBG-001"}'
Also accepts playerID, userId / userID in place of playerId. PUBG UID should be numeric and start with 5.
Success (200)
{
"success": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "completed",
"playerId": "51234567890",
"playerName": "PlayerName",
"deductedBalance": 0.0017,
"durationSec": 2
}
Player not found (200) — fee deducted
{
"success": false,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "cancelled",
"playerId": "51234567890",
"deductedBalance": 0.0017,
"durationSec": 2,
"error": "PLAYER NOT FOUND"
}
Invalid player id (400)
{
"success": false,
"error": "INVALID PLAYER ID"
}
Insufficient balance (400)
{
"success": false,
"error": "INSUFFICIENT BALANCE"
}
Invalid body / missing fields (400)
{
"success": false,
"error": "INVALID BODY"
}
// or
{
"success": false,
"error": "INVALID REQUEST"
}
Idempotent replay (200)
{
"success": true,
"orderId": "GW-API-PBG-A1B2C3-D4E5F6A7",
"status": "completed",
"playerId": "51234567890",
"playerName": "PlayerName",
"deductedBalance": 0.0017,
"durationSec": 2,
"idempotentReplay": true
}
POST /mlvfy
Mobile Legends user + zone verification (region / profile + first-time bonus tiers).
{
"userId": "123456789",
"zoneId": "1234",
"trxid": "CHK-ML-001"
}
curl -X POST "https://api.sonofutred.com/mlvfy" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"userId":"123456789","zoneId":"1234","trxid":"CHK-ML-001"}'
Aliases: userID, zoneID, trxId. Both ids must be digits.
Success (200)
{
"success": true,
"orderId": "GW-API-ML-1A2B3C-4D5E6F78",
"status": "completed",
"userId": "123456789",
"zoneId": "1234",
"playerName": "PlayerName",
"region": "Philippines",
"firstTimeBonus": [
{ "tier": "50+50", "status": "available" },
{ "tier": "150+150", "status": "already_claimed" },
{ "tier": "250+250", "status": "available" },
{ "tier": "500+500", "status": "unknown" }
],
"deductedBalance": 0,
"freeUsedToday": 3,
"freeLimitDaily": 20,
"freeLeftToday": 17,
"durationSec": 3
}
firstTimeBonus[].status: available · already_claimed ·
unknown. After free quota, deductedBalance is 0.02.
Region check failed (200) — may still deduct paid fee when over free quota
{
"success": false,
"orderId": "GW-API-ML-9Z8Y7X-6W5V4U32",
"status": "cancelled",
"userId": "123456789",
"zoneId": "0000",
"firstTimeBonus": [
{ "tier": "50+50", "status": "unknown" },
{ "tier": "150+150", "status": "unknown" },
{ "tier": "250+250", "status": "unknown" },
{ "tier": "500+500", "status": "unknown" }
],
"deductedBalance": 0.02,
"freeUsedToday": 21,
"freeLimitDaily": 20,
"freeLeftToday": 0,
"durationSec": 2,
"error": "REGION CHECK FAILED"
}
Invalid request / body (400)
{
"success": false,
"error": "INVALID REQUEST"
}
// or
{
"success": false,
"error": "INVALID BODY"
}
Insufficient balance (400) — paid checks only
{
"success": false,
"error": "INSUFFICIENT BALANCE"
}
POST /rdmpubg — PUBG redemption
Redeem a UC voucher/code onto a PUBG player.
{
"playerId": "51234567890",
"code": "ABCD-EFGH-IJKL",
"trxid": "RDM-001"
}
curl -X POST "https://api.sonofutred.com/rdmpubg" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"playerId":"51234567890","code":"ABCD-EFGH-IJKL","trxid":"RDM-001"}'
Also accepts playerID, userId / userID for the player field.
Success (200)
{
"success": true,
"orderId": "GW-API-PBG-B3C4D5-E6F7A890",
"status": "completed",
"playerId": "51234567890",
"name": "PlayerName",
"ucAmount": 660,
"productName": "660 UC",
"deductedBalance": 0.0017,
"durationSec": 45
}
Redemption failed (200) — fee deducted
{
"success": false,
"orderId": "GW-API-PBG-C7D8E9-F0A1B234",
"status": "cancelled",
"playerId": "51234567890",
"deductedBalance": 0.0017,
"durationSec": 12,
"error": "REDEMPTION FAILED"
}
Invalid request / body (400)
{
"success": false,
"error": "INVALID REQUEST"
}
// or
{
"success": false,
"error": "INVALID BODY"
}
Insufficient balance (400)
{
"success": false,
"error": "INSUFFICIENT BALANCE"
}