MarketDB API: Difference between revisions

Created page with "== MarketDB API == The MarketDB API serves pre-generated JSON snapshot files for vending, buying and trend data. This endpoint is snapshot-based: * API requests do ''not'' execute live database queries. * Responses are served from JSON files which are usually refreshed every 5 minutes. == Endpoint == Typical request format: <pre> https://flux.muhro.eu/?module=marketdb&action=api&name=<dataset> </pre> == Query Parameters == {| class="wikitable" ! Parameter !..."
 
No edit summary
 
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
== MarketDB API ==
== MuhRO Web API ==
 
The MuhRO Web API serves pre-generated JSON snapshot files from the control panel. There are two parts:


The MarketDB API serves pre-generated JSON snapshot files for vending, buying and trend data.
* '''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.


This endpoint is snapshot-based:
Both parts are snapshot-based:
* API requests do ''not'' execute live database queries.
* API requests do ''not'' execute live database queries.
* Responses are served from JSON files which are usually refreshed every 5 minutes.
* Responses are served from JSON files and carry cache headers, so clients should honour <code>ETag</code> and <code>Cache-Control</code>.
 
== Base URL ==


== Endpoint ==
<pre>
https://flux.muhro.eu/?module=<module>&action=<action>[&parameters]
</pre>


Typical request format:
All endpoints use the query form. The <code>key</code> parameter is accepted everywhere but currently not required.
 
== MarketDB API ==
 
=== Endpoint ===


<pre>
<pre>
https://flux.muhro.eu/?module=marketdb&action=api&name=&lt;dataset&gt;
https://flux.muhro.eu/?module=marketdb&action=api&name=<dataset>
</pre>
</pre>


== Query Parameters ==
=== Query Parameters ===


{| class="wikitable"
{| class="wikitable"
Line 28: Line 39:
| <code>key</code>
| <code>key</code>
| No
| No
| currently not used
| Currently not used.
|}
|}


== Available Datasets ==
=== Available Datasets ===


{| class="wikitable"
{| class="wikitable"
Line 83: Line 94:
|}
|}


== Example Requests ==
=== Example Requests ===


<pre>
<pre>
Line 93: Line 104:
https://flux.muhro.eu/?module=marketdb&action=api&name=vending_trend_hourly_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
https://flux.muhro.eu/?module=marketdb&action=api&name=vending_last_sales_latest
</pre>
== 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 ===
{| class="wikitable"
! Endpoint
! Description
|-
| <code>?module=api&action=itemdata</code>
| Full item list. Returns <code>{generated_at, count, items: [...]}</code> with compact rows.
|-
| <code>?module=api&action=itemdata&id=<item id></code>
| One item with all details (see below).
|-
| <code>?module=api&action=monsterdata</code>
| Full monster list. Returns <code>{generated_at, count, monsters: [...]}</code> with compact rows.
|-
| <code>?module=api&action=monsterdata&id=<monster id></code>
| One monster with all details (see below).
|-
| <code>?module=api&action=itemgroups</code>
| All item groups (boxes): <code>{groups: {<group name>: {containers: [...], contents: [...]}}}</code>.
|-
| <code>?module=api&action=gamedbmeta</code>
| Snapshot metadata: <code>generated_at</code>, <code>server</code>, item and monster counts, <code>exp_rates</code>, <code>drop_rates</code>. Poll this to detect a new snapshot.
|}
=== Item list row ===
<code>id</code>, <code>aegis_name</code>, <code>name</code>, <code>type</code>, <code>subtype</code>, <code>price_buy</code>, <code>price_sell</code>, <code>weight</code>, <code>attack</code>, <code>magic_attack</code>, <code>defense</code>, <code>range</code>, <code>slots</code>, <code>refineable</code>, <code>view</code>, <code>equip_locations[]</code>, <code>custom</code>
=== Item detail ===
{| class="wikitable"
! Field
! Description
|-
| Base fields
| Everything from the list row plus <code>alias_name</code>, <code>gender</code>, <code>weapon_level</code>, <code>armor_level</code>, <code>equip_level_min</code>, <code>equip_level_max</code>, <code>gradable</code>, <code>jobs[]</code>, <code>classes[]</code>, <code>trade_restrictions[]</code>, <code>flags[]</code>, <code>nouse[]</code>, <code>delay</code>, <code>stack</code>, <code>script</code>, <code>equip_script</code>, <code>unequip_script</code>.
|-
| <code>description</code>, <code>description_info</code>
| Item description as shown in the client and the extra info block from the control panel.
|-
| <code>item_group</code>, <code>group_contents[]</code>
| For boxes: the group name and its contents (<code>item_id</code>, <code>name</code>, <code>amount</code>, <code>rate</code>, <code>subgroup</code>, <code>algorithm</code>).
|-
| <code>contained_in[]</code>
| Boxes that can give this item (<code>item_id</code>, <code>name</code>, <code>aegis_name</code>, <code>group</code>).
|-
| <code>npc_shops[]</code>
| NPC shops that sell the item: <code>npc_id</code>, <code>npc_name</code>, <code>shop_type</code>, <code>map</code>, <code>x</code>, <code>y</code>, <code>price</code>, <code>currency</code>, <code>quantity</code> (market shops) and <code>cost_items[]</code> (barter shops).
|-
| <code>barter_ingredient_for[]</code>
| Barter shops that take the item as payment, with <code>reward_item_id</code> and <code>reward_item_name</code>.
|-
| <code>itemshop_cost</code>
| Control panel item shop price, if any.
|-
| <code>drops[]</code>
| Monsters that drop the item, sorted by chance. See drop entries below.
|-
| <code>images</code>
| <code>icon</code> and <code>collection</code> image URLs.
|}
=== Monster list row ===
<code>id</code>, <code>sprite</code>, <code>name</code>, <code>name_japanese</code>, <code>level</code>, <code>hp</code>, <code>size</code>, <code>race</code>, <code>element</code>, <code>element_level</code>, <code>base_exp</code>, <code>job_exp</code>, <code>mvp_exp</code>, <code>mvp</code>, <code>custom</code>
=== Monster detail ===
{| class="wikitable"
! Field
! Description
|-
| Base fields
| Everything from the list row plus <code>sp</code>, <code>attack</code>, <code>attack2</code>, <code>defense</code>, <code>magic_defense</code>, <code>resistance</code>, <code>magic_resistance</code>, <code>str</code>, <code>agi</code>, <code>vit</code>, <code>int</code>, <code>dex</code>, <code>luk</code>, <code>attack_range</code>, <code>skill_range</code>, <code>chase_range</code>, <code>race_groups[]</code>, <code>walk_speed</code>, <code>attack_delay</code>, <code>attack_motion</code>, <code>damage_motion</code>, <code>damage_taken</code>, <code>ai</code>, <code>class</code>, <code>boss</code>, <code>modes[]</code>.
|-
| <code>base_exp_rated</code>, <code>job_exp_rated</code>, <code>mvp_exp_rated</code>
| Exp with the server exp rates applied. The unsuffixed fields are the raw database values.
|-
| <code>drops[]</code>
| The normal drop slots: <code>slot</code>, <code>item_id</code>, <code>aegis_name</code>, <code>name</code>, <code>item_type</code>, <code>rate_raw</code>, <code>rate</code>, <code>steal</code>, <code>option</code>, <code>index</code>.
|-
| <code>mvp_drops[]</code>
| The MVP reward slots, same fields. <code>rate</code> already accounts for the earlier slots being rolled first.
|-
| <code>extra_drops[]</code>
| Additional drops from the server drop table (<code>item_id</code>, <code>name</code>, <code>rate_raw</code>, <code>rate</code>).
|-
| <code>map_drops[]</code>
| Map specific drops (<code>map</code>, <code>item_id</code>, <code>name</code>, <code>rate_raw</code>, <code>rate</code>).
|-
| <code>skills[]</code>
| Monster skills with cast conditions, if the server publishes them.
|-
| <code>spawns[]</code>
| Spawn points: <code>map</code>, <code>x</code>, <code>y</code>, <code>respawn_min</code>, <code>respawn_max</code>, <code>quantity</code>.
|-
| <code>image</code>
| Sprite image URL.
|}
=== Drop entries on items ===
Each entry in an item's <code>drops[]</code> has <code>monster_id</code>, <code>monster_name</code>, <code>monster_level</code>, <code>monster_race</code>, <code>monster_element</code>, <code>monster_element_level</code>, <code>boss</code>, <code>type</code>, <code>rate_raw</code>, <code>rate</code>, <code>steal</code> and, for map drops, <code>map</code>.
{| class="wikitable"
! <code>type</code>
! Meaning
|-
| <code>normal</code>
| One of the ten regular drop slots.
|-
| <code>mvp</code>
| MVP reward slot.
|-
| <code>extra</code>
| Additional server drop.
|-
| <code>map</code>
| Map specific drop on the map named in <code>map</code>.
|}
=== Drop chances ===
* <code>rate</code> is 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).
* <code>rate_raw</code> is 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 <code>gamedbmeta</code> as <code>drop_rates</code> and <code>exp_rates</code>.
* Drops whose item is not in the item database have <code>item_id</code> set to <code>null</code>.
=== Example Requests ===
<pre>
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
</pre>
Example drop entry from a monster:
<pre>
{"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}
</pre>
</pre>


Line 105: Line 267:
|-
|-
| <code>Cache-Control</code>
| <code>Cache-Control</code>
| Public cache header with <code>max-age</code> from <code>MarketDbCache.ApiCacheSeconds</code>.
| Public cache header with <code>max-age</code>: 300 seconds for MarketDB, 3600 seconds for Game DB.
|-
|-
| <code>ETag</code>
| <code>ETag</code>
| Entity tag based on the snapshot file and modification time.
| Entity tag based on the snapshot file and modification time. Send it back as <code>If-None-Match</code>.
|-
|-
| <code>Last-Modified</code>
| <code>Last-Modified</code>
| Snapshot file modification timestamp in GMT.
| Snapshot file modification timestamp in GMT. Game DB endpoints also answer <code>If-Modified-Since</code>.
|-
|-
| <code>Content-Encoding</code>
| <code>Content-Encoding</code>
| Set to <code>gzip</code> when gzip is enabled and supported by the client.
| Set to <code>gzip</code> when the client sends <code>Accept-Encoding: gzip</code>. The full item list is about 11 MB raw and under 1 MB gzipped, so always request gzip for the list endpoints.
|-
| <code>Access-Control-Allow-Origin</code>
| <code>*</code> on Game DB endpoints, so they can be called from browser scripts on other sites.
|}
|}


Default cache TTL:
== Rate Limits ==
* <code>MarketDbCache.ApiCacheSeconds = 300</code> (5 minutes)


== Authentication, Rate Limits, and Compression ==
{| class="wikitable"
 
! API
=== Rate Limiting ===
! Limit
 
|-
Simple per-IP rate limiting is controlled by <code>MarketDbCache.ApiRatePerMinute</code>.
| MarketDB
 
| 120 requests per minute per IP.
Default setting:
|-
* <code>120</code> requests per minute
| Game DB
| 240 requests per minute per IP.
|}


=== Gzip Compression ===
Fetch the list endpoints once and cache them; the game data only changes about weekly and <code>gamedbmeta</code> tells you when.
 
If <code>MarketDbCache.ApiEnableGzip</code> is enabled and the client sends <code>Accept-Encoding: gzip</code>, the API returns a gzipped response body.


== Status Codes ==
== Status Codes ==
Line 144: Line 308:
| <code>304</code>
| <code>304</code>
| The client cache is still valid for the current <code>ETag</code>.
| The client cache is still valid for the current <code>ETag</code>.
|-
| <code>400</code>
| Invalid <code>id</code> parameter (Game DB).
|-
|-
| <code>403</code>
| <code>403</code>
Line 149: Line 316:
|-
|-
| <code>404</code>
| <code>404</code>
| Unknown dataset name or snapshot file missing.
| Unknown dataset name, unknown item or monster id or snapshot file missing.
|-
|-
| <code>429</code>
| <code>429</code>
Line 155: Line 322:
|-
|-
| <code>500</code>
| <code>500</code>
| MarketDb cache configuration is missing.
| MarketDB cache configuration is missing.
|-
| <code>503</code>
| Game DB API disabled.
|}
|}
Game DB errors are returned as JSON: <code>{"error": "..."}</code>.