JSFiddle - React, Tailwind, and code Playground
HTML
<div class="container">
<header>
<h1>Donut Auction Orders API</h1>
<p>
Example usage of
<code>GET https://api.donut.auction/orders</code>.
The API is cursor-paginated using <code>nextCursor</code>.
This endpoints returns the current active orders on donutsmp.
You may fetch orders once every 30 minutes.
</p>
<h3>Python</h3>
<pre><code>
import requests
url = "https://api.donut.auction/orders"
params = {}
while True:
r = requests.get(url, params=params)
data = r.json()
for order in data.get("orders", []):
print(order["userName"], order["item"]["itemId"])
if not data.get("nextCursor"):
break
params["cursor"] = data["nextCursor"]
</code></pre>
<h3>JavaScript</h3>
<pre><code>
const url = "https://api.donut.auction/orders";
let cursor = null;
while (true) {
const res = await fetch(
cursor ? `${url}?cursor=${cursor}` : url
);
const data = await res.json();
data.orders.forEach(o =>
console.log(o.userName, o.item.itemId)
);
if (!data.nextCursor) break;
cursor = data.nextCursor;
}
</code></pre>
</header>
<div class="status">
<span id="loading">Idle</span>
<span id="pages">Pages downloaded: 0</span>
</div>
<ul id="orders" class="orders"></ul>
<div class="pagination">
<button id="prev" disabled>Prev</button>
<span id="pageInfo"></span>
<button id="next" disabled>Next</button>
</div>
</div>
CSS
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
background: #0f1115;
color: #e6e6e6;
margin: 0;
padding: 20px;
}
.container {
max-width: 900px;
margin: auto;
}
header {
background: #161a22;
padding: 16px 20px;
border-radius: 8px;
margin-bottom: 16px;
}
header h1 {
margin: 0 0 8px;
font-size: 1.4rem;
}
header p {
margin: 0;
color: #b5b9c5;
font-size: 0.95rem;
}
code {
background: #22283a;
padding: 2px 6px;
border-radius: 4px;
}
.status {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
font-size: 0.9rem;
color: #aab0c0;
}
.orders {
list-style: none;
padding: 0;
margin: 0;
}
.orders li {
display: grid;
grid-template-columns: 64px 1fr;
gap: 12px;
background: #161a22;
padding: 12px;
border-radius: 8px;
margin-bottom: 10px;
}
.orders img {
width: 64px;
height: 64px;
image-rendering: pixelated;
}
.order-meta {
font-size: 0.9rem;
color: #cfd3df;
}
.order-meta strong {
font-size: 1rem;
color: #fff;
}
.pagination {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 16px;
}
button {
background: #22283a;
color: #fff;
border: none;
padding: 8px 14px;
border-radius: 6px;
cursor: pointer;
}
button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
JavaScript
const url = "https://api.donut.auction/orders";
let pages = [];
let cursors = [null];
let pageIndex = 0;
const listEl = document.getElementById("orders");
const prevBtn = document.getElementById("prev");
const nextBtn = document.getElementById("next");
const pageInfo = document.getElementById("pageInfo");
const loadingEl = document.getElementById("loading");
const pagesEl = document.getElementById("pages");
async function loadPage(index) {
if (pages[index]) {
render(pages[index], index);
return;
}
loadingEl.textContent = "Fetching…";
const cursor = cursors[index];
const query = cursor ? `?cursor=${cursor}` : "";
const res = await fetch(url + query);
const data = await res.json();
pages[index] = data;
cursors[index + 1] = data.nextCursor || null;
pagesEl.textContent = `Pages downloaded: ${pages.length}`;
loadingEl.textContent = "Idle";
render(data, index);
}
function render(data, index) {
listEl.innerHTML = "";
(data.orders || []).forEach(order => {
const li = document.createElement("li");
const itemId = order.item.itemId;
const imgUrl = `https://cdn.donut.auction/1.21.11/items/minecraft/${itemId}.webp`;
li.innerHTML = `
<img src="${imgUrl}" alt="${itemId}">
<div class="order-meta">
<strong>${order.userName}</strong><br>
Item: ${itemId}<br>
Price: ${order.itemPrice}<br>
Amount: ${order.amountDelivered}/${order.amountOrdered}<br>
Created: ${order.creationDate}
</div>
`;
listEl.appendChild(li);
});
prevBtn.disabled = index === 0;
nextBtn.disabled = !data.nextCursor;
pageInfo.textContent = `Page ${index + 1}`;
}
prevBtn.onclick = () => {
pageIndex--;
loadPage(pageIndex);
};
nextBtn.onclick = () => {
pageIndex++;
loadPage(pageIndex);
};
loadPage(0);