Top-ups by player ID over an API: the fields contract, and why zone ID breaks orders
A gift card order ends with a code you can resend. A top-up ends on somebody else's game account, and it cannot be pulled back. In the API that whole difference comes down to one array: each category declares the fields you must collect — and there is exactly one correct way to handle them.
A top-up is not a code: nothing to deliver, nothing to take back
Order gift card codes through the API and the finished order carries a codes array — hand it over, resend it if the buyer loses it. A top-up order has no codes and never will: the value lands on the player's account. What comes back instead is your own input, echoed — a completed game_topup order returns category_id, offer_id and the fields you sent.
The replacement policy covers a code that does not work; it does not cover a top-up sent to a player ID typed in wrong, because by then the diamonds are on somebody's account — our FAQ says exactly that. So: collect the right fields, confirm them before charging, and write the rule into your shop terms before the first mistake.
The fields contract: the category declares, you collect
GET /api/v1/top-ups/categories/{id}/offers returns two lists: offers — the packs, already priced with your markup — and fields, the buyer inputs required to order. Each field has a key, a human label and a type. POST /api/v1/top-ups/order takes category_id, offer_id and a fields object whose keys must match fields[].key exactly; the server checks it against the declared list before the charge.
Hardcode player_id and you have built for one family of games. The docs example is PUBG Mobile (Auto) with a single player_id — an example, not a schema. Render the label, send the key, and read no meaning into a key name: in the catalogue on 8 September 2026 the same “player number” is player_id in PUBG Mobile and Free Fire, user_id in 8 Ball Pool (label “Unique ID”), and one login category ships user_id and server_id under the labels “Email” and “Password”.
The type is not always text: some categories declare a select with a fixed option list (server: Asia / Europe / America), and you must send one of those values. The same response carries note — the category's own instructions: which number to enter, which region the packs are locked to. Show it in your form.
Three families of requirements, straight from the catalogue
Against the live catalogue on 8 September 2026, every category falls into one of three groups:
- One field. PUBG Mobile (Auto) and every regional Free Fire category declare a single player_id — the case everybody builds for, and why integrations break on game two.
- ID plus server or zone. Mobile Legends (Global) and Mobile Legends (RU) declare player_id and server_id; Ace Racer declares user_id and server_id. One number missing and nothing ships.
- Access by login. Seven categories carry the “(Auto Via Login)” suffix — Genshin Impact, Solo Leveling: Arise, Tower of Fantasy, Love and Deepspace, Mongil: Star Dive, Neverness to Everness, Arknight: Endfield. They ask for no player ID at all: the account email and password, plus a UID, a Role ID or a server from a list.
Tip
“A top-up never needs the account password” holds for every ID category and fails for the Auto Via Login family, which asks for credentials by design. Do not put the two side by side in self-service: sell login categories manually and keep nothing afterwards.
Why zone ID is the number one failure
Mobile Legends identifies an account by two numbers, and the player sees them as one string: in the game profile the long number is the player ID, the short one in brackets is the zone (server) ID. The API calls that field server_id, label “Server ID”; the game and our Mobile Legends page call it zone ID. That is why buyers send one number of the two and think they are done.
Fix it in the form, not in support: two inputs, each labelled with the word the player sees in the game, plus a hint — “the short number in brackets: 123456789 (5678) means ID 123456789, zone 5678”. If you accept a pasted string, split it yourself and show the split back.
There is no player-ID validation endpoint — do this instead
Straight answer: the RSC API has no endpoint that checks whether a player ID exists. The only pre-flight check on the platform is POST /api/v1/steam-topup/check-login, for Steam wallet top-ups, not game top-ups. The first system that can tell a wrong ID from a right one is the game — after the money has moved.
So verification happens with the person who owns the account, before you charge. Echo every value back in a confirmation step — “Mobile Legends (Global) · ID 123456789 · zone 5678 · 172 diamonds” — name the game and the region, require an explicit yes, and store it with the order.
What the server says when a field is wrong
Validation is server-side and per field. A missing or blank value returns HTTP 400, an error of type invalid_request and the message “Field server_id is required (see the category's fields).” Anything longer than 200 characters returns “Field server_id is invalid.” Values travel as strings; a JSON number is coerced, anything else counts as missing.
Do not show that message to a buyer: pull the field key out, look it up in the cached fields array, and print your own line — “Server ID is required: the short number in brackets next to the ID.” And HTTP 200 does not mean delivered: if the category rejects the order at creation, the charge returns to your balance and the same response carries status “refund” with a status_reason. Branch on the status, not the HTTP code.
Region: the second reason orders fail
Many games are a shelf of regional categories, not one. On 8 September 2026 the catalogue carried fourteen regional Free Fire categories (BD, BR, CIS, EU, ID, LATAM, MENA, MY/SG, PH, PK, SG, TH, TW, VN) and twelve for Mobile Legends. The region is in the name and in note, which says outright when packs are region-locked. GET /api/v1/top-ups/brands groups the catalogue by brand and returns region and variant per subcategory.
Ask for the region before you show prices: an Indonesian pack bought for a European account is money lost exactly like a wrong ID. And read the variant — PUBG Mobile ships as (Auto), (Fast), (Manual) and (Reserve), the same player_id with very different behaviour. The Manual note states average delivery of 5–15 minutes and a success rate of roughly 50/50 depending on channel status, with a refund when it cannot be completed.
The lifecycle of a top-up order
created → processing → completed. failed means it could not be delivered; refund means the charge is back on your balance, with a ledger line and no ticket needed. POST /api/v1/top-ups/order charges immediately and returns the order; after that the source of truth is GET /api/v1/orders/{number}, which also returns status_history with a reason. There are no codes at the end.
Poll it, do not hammer it. The platform re-checks a live order every 20 seconds for the first three minutes, then once a minute up to ten minutes, then every ten minutes — a faster poll returns the same status and burns budget. A new key gets 30 requests a minute and 5,000 a day; responses carry X-RateLimit headers, a 429 carries Retry-After. Delivery is usually minutes; what you show the buyer is the status.
Who pays when the ID was wrong
A completed top-up cannot be recalled — not by us, not by the game. Our Mobile Legends page says exactly that, and the site FAQ names this as the one case the replacement policy does not cover. While the order is still unfulfilled there is a chance: a ticket in the dashboard or Telegram @supportresellcodes, and we try to cancel it.
Write one paragraph into your shop terms before the first order, not after the first argument: the buyer supplies and confirms the ID, zone and region; after that a completed top-up is not refundable; an ID mistyped by your own operator is on you. Keep the confirmation — it is your entire defence.
Building for 316 categories, not four
The catalogue held 316 categories on 8 September 2026, so a hardcoded switch over four of them is a rewrite waiting to happen. Sync GET /api/v1/top-ups/categories into your own table on a schedule, read the offers endpoint when the buyer opens a category, and cache its fields beside the price for a few minutes. Build the form at runtime: name from key, caption from label, input or dropdown from type.
- A new category from the next sync should reach the storefront without a deploy; an unknown key renders as a labelled text input, not a crash.
- Prices in offers already include your markup, and one top-up per order means two packs are two orders and two charges.
- Test end to end with a real order on an account you control: PUBG Mobile 60 UC was $0.88 in the public price table on 8 September 2026.
- Balance is prepaid in USDT (TRC-20, BEP-20, TON, Aptos) from 3 USD, so a confirmed order never waits on funding.
Integration checklist
- Read fields per category and build the form from it — nothing about a game is hardcoded except its hint text.
- Render the label, send the key; key names are identifiers with no meaning.
- Echo ID, zone, region and pack back, and require an explicit confirmation before charging.
- Map 400 field errors back to the human label; never surface the raw message.
- Branch on the order status, refund included, rather than on HTTP 200.
- Poll GET /api/v1/orders/{number} on a 20-second-and-slower schedule, watching the rate-limit headers.
- Publish your wrong-ID rule before you need it, and keep every confirmation.
Field lists, category counts and the price above are what the catalogue returned on 8 September 2026 — inputs change and prices move, so the endpoint is the source of truth. Full reference: resell.codes/docs and resell.codes/docs/reference.
Build your top-up integration on live data
Create a free account, take your API key from the dashboard and read the fields of any category before you write a single line of form code.
