MarketDB API
MuhRO Web API
The MuhRO Web API serves JSON snapshots from the control panel. There are three parts:
- MarketDB API: vending, buying and sales trend data. Snapshots are refreshed about every 5 minutes.
- Game DB API: item and monster data as shown on the item and monster pages, including drops, drop chances, NPC shops, spawns and item groups. Snapshots are rebuilt when the game database is updated, which is about once a week.
- Private Account API: your own characters, inventories, carts, account/master storages and vending/buying shops. Requires a scoped private key. Background snapshots refresh every minute.
All three parts serve snapshots without querying the game database on API requests. Public MarketDB and Game DB responses support cache validation with ETag and Cache-Control. Private responses require authorization on every request and use Cache-Control: private, no-store.
Base URL
https://flux.muhro.eu/?module=<module>&action=<action>[¶meters]
All endpoints use the query form. Public MarketDB and Game DB endpoints currently do not require a key. The Private Account API requires an Authorization: Bearer or X-API-Key header and rejects keys in URLs. Use the canonical https://flux.muhro.eu/ address directly to avoid redirects when sending credentials.
MarketDB API
Endpoint
https://flux.muhro.eu/?module=marketdb&action=api&name=<dataset>
Query Parameters
| Parameter | Required | Description |
|---|---|---|
name
|
Yes | Dataset to fetch. |
key
|
No | Currently not used. |
Available Datasets
| Dataset | Description | Notes |
|---|---|---|
vendings
|
Current vendor shop list. | Shop-level snapshot. |
v_vending
|
Items currently for sale. | Full rows from the vending cache view. |
v_buying
|
Items currently being bought. | Full rows from the buying cache view. |
buyingstores
|
Current buying shop list. | Shop-level snapshot. |
vending_trend_daily
|
Full daily sales trend dataset. | Includes all available day buckets and items. |
vending_trend_hourly
|
Full hourly sales trend dataset. | Includes all available hour buckets and items. |
vending_last_sales
|
Latest sales log snapshot. | Currently limited to 1000 rows. |
vending_trend_daily_latest
|
Rolling summary for the last 24 hours. | Ordered by sales_count descending.
|
vending_trend_hourly_latest
|
Rolling summary for the last 60 minutes. | Ordered by sales_count descending.
|
vending_last_sales_latest
|
Latest sales feed. | Currently the same 1000-row payload as vending_last_sales.
|
meta
|
Snapshot metadata. | Includes generated_at and server.
|
Example Requests
https://flux.muhro.eu/?module=marketdb&action=api&name=vendings https://flux.muhro.eu/?module=marketdb&action=api&name=v_vending https://flux.muhro.eu/?module=marketdb&action=api&name=v_buying https://flux.muhro.eu/?module=marketdb&action=api&name=buyingstores https://flux.muhro.eu/?module=marketdb&action=api&name=vending_trend_daily_latest https://flux.muhro.eu/?module=marketdb&action=api&name=vending_trend_hourly_latest https://flux.muhro.eu/?module=marketdb&action=api&name=vending_last_sales_latest
Game DB API
The Game DB API exposes the same item and monster data as the control panel item and monster pages. Drop chances and exp values are already adjusted with the server rates, so the numbers match what the web pages show.
Endpoints
| Endpoint | Description |
|---|---|
?module=api&action=itemdata
|
Full item list. Returns {generated_at, count, items: [...]} with compact rows.
|
?module=api&action=itemdata&id=<item id>
|
One item with all details (see below). |
?module=api&action=monsterdata
|
Full monster list. Returns {generated_at, count, monsters: [...]} with compact rows.
|
?module=api&action=monsterdata&id=<monster id>
|
One monster with all details (see below). |
?module=api&action=itemgroups
|
All item groups (boxes): {groups: {<group name>: {containers: [...], contents: [...]}}}.
|
?module=api&action=gamedbmeta
|
Snapshot metadata: generated_at, server, item and monster counts, exp_rates, drop_rates. Poll this to detect a new snapshot.
|
Item list row
id, aegis_name, name, type, subtype, price_buy, price_sell, weight, attack, magic_attack, defense, range, slots, refineable, view, equip_locations[], custom
Item detail
| Field | Description |
|---|---|
| Base fields | Everything from the list row plus alias_name, gender, weapon_level, armor_level, equip_level_min, equip_level_max, gradable, jobs[], classes[], trade_restrictions[], flags[], nouse[], delay, stack, script, equip_script, unequip_script.
|
description, description_info
|
Item description as shown in the client and the extra info block from the control panel. |
item_group, group_contents[]
|
For boxes: the group name and its contents (item_id, name, amount, rate, subgroup, algorithm).
|
contained_in[]
|
Boxes that can give this item (item_id, name, aegis_name, group).
|
npc_shops[]
|
NPC shops that sell the item: npc_id, npc_name, shop_type, map, x, y, price, currency, quantity (market shops) and cost_items[] (barter shops).
|
barter_ingredient_for[]
|
Barter shops that take the item as payment, with reward_item_id and reward_item_name.
|
itemshop_cost
|
Control panel item shop price, if any. |
drops[]
|
Monsters that drop the item, sorted by chance. See drop entries below. |
images
|
icon and collection image URLs.
|
Monster list row
id, sprite, name, name_japanese, level, hp, size, race, element, element_level, base_exp, job_exp, mvp_exp, mvp, custom
Monster detail
| Field | Description |
|---|---|
| Base fields | Everything from the list row plus sp, attack, attack2, defense, magic_defense, resistance, magic_resistance, str, agi, vit, int, dex, luk, attack_range, skill_range, chase_range, race_groups[], walk_speed, attack_delay, attack_motion, damage_motion, damage_taken, ai, class, boss, modes[].
|
base_exp_rated, job_exp_rated, mvp_exp_rated
|
Exp with the server exp rates applied. The unsuffixed fields are the raw database values. |
drops[]
|
The normal drop slots: slot, item_id, aegis_name, name, item_type, rate_raw, rate, steal, option, index.
|
mvp_drops[]
|
The MVP reward slots, same fields. rate already accounts for the earlier slots being rolled first.
|
extra_drops[]
|
Additional drops from the server drop table (item_id, name, rate_raw, rate).
|
map_drops[]
|
Map specific drops (map, item_id, name, rate_raw, rate).
|
skills[]
|
Monster skills with cast conditions, if the server publishes them. |
spawns[]
|
Spawn points: map, x, y, respawn_min, respawn_max, quantity.
|
image
|
Sprite image URL. |
Drop entries on items
Each entry in an item's drops[] has monster_id, monster_name, monster_level, monster_race, monster_element, monster_element_level, boss, type, rate_raw, rate, steal and, for map drops, map.
type
|
Meaning |
|---|---|
normal
|
One of the ten regular drop slots. |
mvp
|
MVP reward slot. |
extra
|
Additional server drop. |
map
|
Map specific drop on the map named in map.
|
Drop chances
rateis the chance in percent with the server drop rates applied, the same number the item and monster pages show. Cards are fixed at 0.20% (0.04% from bosses).rate_rawis the untouched database value: 1/100 percent for normal, MVP and extra drops and 1/1000 percent for map drops.- The rates used are published in
gamedbmetaasdrop_ratesandexp_rates. - Drops whose item is not in the item database have
item_idset tonull.
Example Requests
https://flux.muhro.eu/?module=api&action=itemdata&id=501 https://flux.muhro.eu/?module=api&action=monsterdata&id=1002 https://flux.muhro.eu/?module=api&action=itemdata https://flux.muhro.eu/?module=api&action=monsterdata https://flux.muhro.eu/?module=api&action=itemgroups https://flux.muhro.eu/?module=api&action=gamedbmeta
Example drop entry from a monster:
{"slot":1,"item_id":909,"aegis_name":"Jellopy","name":"Jellopy","item_type":"Etc",
"rate_raw":7000,"rate":93.37,"steal":true,"option":null,"index":0}
Private Account API
The Private Account API is available on LIVE. It gives a tool read access to the data owned by the master account that created its key. It cannot change game data or access another owner's data.
Create a private key
- Open Private API keys or follow the Private API keys link on your master account page.
- Use your normal Flux login. If you are already signed in, no separate API login is needed.
- Enter a label, select the required read scopes and choose an expiry of 7, 30, 90 or 365 days.
- Copy the key immediately. The full key is shown only once.
- Allow up to one minute for the first background refresh before requesting data.
You can have up to ten active keys. Revoke a key in the same manager when a tool no longer needs access. Revocation takes effect for subsequent requests immediately. Keep keys out of URLs, logs, public websites and distributed application binaries. The normal Flux key manager can revoke keys during a replica outage.
Endpoint and authentication
GET https://flux.muhro.eu/?module=api&action=private&name=<dataset> Authorization: Bearer YOUR_PRIVATE_KEY
Alternatively send X-API-Key: YOUR_PRIVATE_KEY. Send keys only in headers over HTTPS. A conflicting pair of authentication headers is rejected. The key and token query parameters are rejected.
Example with the key already set in an environment variable:
curl --header "Authorization: Bearer $MUHRO_PRIVATE_KEY" \ 'https://flux.muhro.eu/?module=api&action=private&name=inventories'
Datasets and scopes
The name parameter also names the read scope required on the key.
| name / scope | Complete dataset |
|---|---|
characters |
Current owned characters with account IDs, levels, saved zeny and online status. |
inventories |
All inventory item instances on owned characters. |
carts |
All cart item instances on owned characters. |
storages |
All owned account and master storage items. Guild storage is excluded. |
shops |
All owned vending and buying shops with nested item listings. |
Deleted characters are excluded. Item rows use nameid for the item type; nested shop listings use item_id. Item-instance details include amount, equipment flags, identification, refine, cards, random options, enchant grade, binding, expiry and unique ID where applicable. Use the public Game DB API to resolve item names and descriptions.
Complete responses
Every successful response contains the entire matching dataset. There is no pagination, continuation token or silent truncation. Do not send page or page_size; they are rejected. A resource limit causes an unavailable response rather than a partial dataset.
| Field | Meaning |
|---|---|
dataset |
Dataset name. |
generated_at |
Snapshot generation time in UTC. |
expires_at |
Snapshot expiry time in UTC. |
filters |
Applied filters, or an empty object when none were supplied. |
count |
Number of returned rows after filtering. |
data |
Array containing all matching rows. Each shop row contains an items array.
|
Example response with fictional character data:
{
"dataset": "characters",
"generated_at": "2026-10-21T08:00:00Z",
"expires_at": "2026-10-21T08:02:00Z",
"filters": {},
"count": 1,
"data": [
{
"char_id": "12345", "account_id": "2000001", "char_num": "0",
"name": "Example Merchant", "class": "5", "base_level": "100",
"job_level": "50", "zeny": "100000", "online": "0"
}
]
}
Numeric database fields are returned as strings. In particular preserve zeny, prices and item unique IDs as strings or use an integer type that can represent their full range. JavaScript Number cannot represent every possible value exactly.
Optional filters
Omit filters to receive the full dataset. Filters combine with AND and only narrow the owner's cached data. Unknown or inapplicable filters return 400. Filters do not run database queries or trigger a refresh.
| Flag | Applies to | Meaning |
|---|---|---|
account_id |
All datasets | Exact game account ID. Excludes master storage rows because those belong to the master account. |
char_id |
characters, inventories, carts, shops | Exact character ID. |
item_id |
inventories, carts, storages, shops | Exact item type. |
equipped=0 or equipped=1 |
inventories, carts, storages | No equipment flags or any equipment flag. |
bound=0 or bound=1 |
inventories, carts, storages | Unbound or any binding type. |
identified=0 or identified=1 |
inventories, carts, storages | Unidentified or identified. |
min_refine, max_refine |
inventories, carts, storages | Inclusive refine range. |
storage_type=account or storage_type=master |
storages | Account or master storage. |
storage_name |
storages | Exact storage name returned in the data. URL-encode spaces and other special characters. |
shop_type=vending or shop_type=buying |
shops | Vending or buying shops. |
For shops, item_id filters the nested listings and removes shops with no matching item. Other shop filters preserve every listing in each matching shop.
Examples below still require an authentication header:
https://flux.muhro.eu/?module=api&action=private&name=inventories&char_id=12345&equipped=1 https://flux.muhro.eu/?module=api&action=private&name=inventories&min_refine=10&bound=0 https://flux.muhro.eu/?module=api&action=private&name=storages&storage_type=master&item_id=501 https://flux.muhro.eu/?module=api&action=private&name=storages&storage_name=Master%20I https://flux.muhro.eu/?module=api&action=private&name=shops&shop_type=vending&item_id=501
Refreshes, privacy and main database load
- Private API data requests read local key state and private snapshot files only, even when you have an active Flux login cookie.
- Key creation, listing and revocation use the normal Flux account page and session. This interactive management page may query the main database for account checks. The keys remain in local storage and existing keys continue to work.
- Background snapshot refreshes query only a verified read-only replica connection. Private API data requests issue no queries to the main game database.
- Background refresh runs every minute for owners with active keys. Requests and cache misses never trigger a refresh or fall back to the main database.
- Snapshots and authorization expire 120 seconds after refresh starts. The replica must have running replication threads and no more than 15 seconds of lag. Unavailable or expired data returns
503; expired snapshots are not served as a fallback. - Password, account restrictions and ownership changes become visible through the replica. Their visibility can be delayed by up to about 135 seconds. Local key revocation applies immediately to subsequent requests.
- Data reflects saved game state that has reached the replica. Shop data uses the same database approximation of active shops as MarketDB.
All private success and error responses use Cache-Control: private, no-store, max-age=0. Private responses do not use ETag/304 cache validation and do not enable cross-origin browser access. Do not put them in shared caches.
Zero main database queries for API data requests does not mean zero server resource usage: the private API still uses web-server CPU and disk. Interactive key management and ordinary website pages use their normal Flux database connections.
Private API limits and errors
Data requests are limited to 60 per minute per owner, shared across that owner's keys. Key creation is limited to five attempts per 15 minutes per owner. Sign-in uses the normal Flux authentication controls. A key can only use its selected scopes.
Errors return JSON such as {"error":"snapshot_unavailable"}.
| Status | Meaning / action |
|---|---|
200 |
Complete matching dataset returned. An empty match has count: 0 and data: [].
|
400 |
Invalid dataset/filter or a key supplied in the URL. Fix the request. |
401 |
Missing, invalid, expired or revoked key. Check the header or create a new key if needed. |
403 |
Required scope is missing or the owner is unavailable. |
405 |
The data endpoint only accepts GET. |
429 |
Rate limit exceeded. Honor Retry-After: 60.
|
503 |
No fresh snapshot/authorization, a busy cache or another unavailable dependency. Honor Retry-After: 60. Repeated requests do not force a refresh.
|
Response Headers
This table applies to the public MarketDB and Game DB APIs. Private response headers are described above.
| Header | Description |
|---|---|
Content-Type
|
application/json; charset=utf-8
|
Cache-Control
|
Public cache header with max-age: 300 seconds for MarketDB, 3600 seconds for Game DB.
|
ETag
|
Entity tag based on the snapshot file and modification time. Send it back as If-None-Match.
|
Last-Modified
|
Snapshot file modification timestamp in GMT. Game DB endpoints also answer If-Modified-Since.
|
Content-Encoding
|
Set to gzip when the client sends Accept-Encoding: gzip. The full item list is about 11 MB raw and under 1 MB gzipped, so always request gzip for the list endpoints.
|
Access-Control-Allow-Origin
|
* on Game DB endpoints, so they can be called from browser scripts on other sites.
|
Rate Limits
| API | Limit |
|---|---|
| MarketDB | 120 requests per minute per IP. |
| Game DB | 240 requests per minute per IP. |
| Private Account API | 60 requests per minute per owner across all keys. |
For the public APIs fetch the list endpoints once and cache them; the game data only changes about weekly and gamedbmeta tells you when.
Status Codes
This table applies to the public APIs. See the Private API limits and errors section above for private responses.
| Status | Meaning |
|---|---|
200
|
Snapshot returned successfully. |
304
|
The client cache is still valid for the current ETag.
|
400
|
Invalid id parameter (Game DB).
|
403
|
Invalid or missing API key when key protection is enabled. |
404
|
Unknown dataset name, unknown item or monster id or snapshot file missing. |
429
|
Rate limit exceeded. |
500
|
MarketDB cache configuration is missing. |
503
|
Game DB API disabled. |
Game DB errors are returned as JSON: {"error": "..."}.