KinaStore API
A simple REST API for ordering Discord decorations, nameplates, effects and bundles. Find an item, place an order, get the gift link.
> order Alt Raccoon # POST /api/v1/orders { "id": "KS-B125312C…", "total": 1.43, "status": "paid" } ○ preparing gift link… ✓ { "status": "delivered", "links": ["https://discord.gift/AbCd…"] }
Orders are charged from your wallet balance at the shop price, in EUR. Get API access.
Plans & access
API access is prepaid. Buy a plan from your wallet balance in Account → API. Your first purchase gives you an API key. Buying again while a plan is active adds the days to the time you have left, and your key stays the same.
What's included
Search, order and track with your key.
Top up once with crypto. Every order is charged automatically, no checkout.
Your key works the moment you buy a plan.
Gift links come back in the API response and are emailed to you.
When the plan runs out, every request returns 403 plan_expired until you renew. Plans only cover API access: orders are paid separately from your balance.
Quickstart
Buy a plan and copy your key from Account → API, place an order, then poll until it is delivered.
# place the order (charges your balance)
curl -X POST {BASE}/api/v1/orders \
-H "Authorization: Bearer ks_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-order-001" \
-d '{"links": "https://discord.com/shop#itemSkuId=1545192554469920779"}'
# {"order": {"id": "KS-B125312CBAC8", "status": "paid", "total": 1.43, ...}, "balance": 39.64}
# poll until delivered, then read the links
curl {BASE}/api/v1/orders/KS-B125312CBAC8 \
-H "Authorization: Bearer ks_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Authentication
Send your key in the Authorization header on every request (X-API-Key works too). A key without an active plan returns 403. Keep the key server-side: it can spend your balance. If it leaks, use Reset key in Account → API and the old key stops working at once.
Authorization: Bearer ks_live_xxxxxxxxxxxxxxxxxxxxxxxx
Idempotency
Send an Idempotency-Key header with a unique value per order (your own order ID works well). A retry with the same key returns the original order with "replayed": true and never charges you twice. Up to 100 characters of A-Z a-z 0-9 _ . : -.
/api/v1/catalogSearch items and their current price. All parameters are optional.
qstringSearch text, e.g. raccoon.kindstringDecoration, Nameplate, Effect, Frame or Bundle.categorystringCollection name.sortstringprice_asc, price_desc or name.pagenumberPage number, from 1.sizenumberItems per page.curl "{BASE}/api/v1/catalog?q=raccoon" \
-H "Authorization: Bearer ks_live_..."
# 200 OK
{
"currency": "EUR",
"items": [{ "sku": "1545192554469920779", "name": "Alt Raccoon", "kind": "Decoration",
"category": "All Ears", "price": 1.43, "orig": 4.99, "image": "https://cdn.discordapp.com/..." }],
"total": 1, "page": 1, "pages": 1
}
/api/v1/items/{sku}One item with its current price, as { "currency", "item" }. Returns 404 unknown_item if the SKU isn't sold.
/api/v1/ordersCharges your balance and processes the order right away. Gift links in stock come back in the response; the rest follow, so poll the status endpoint until it is delivered. Send either items or links.
itemsarrayItems to order: { "sku": string, "qty": 1-10 }.linksstring | arrayDiscord shop links or bare SKUs. Repeat a link to order it more than once.Idempotency-KeystringOptional, recommended. Makes retries safe.curl -X POST {BASE}/api/v1/orders \
-H "Authorization: Bearer ks_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-order-002" \
-d '{"items": [{"sku": "1545192554469920779", "qty": 2}]}'
# 201 Created
{
"order": {
"id": "KS-B125312CBAC8",
"status": "delivered",
"total": 2.86,
"items": [{ "sku": "1545192554469920779", "name": "Alt Raccoon", "qty": 2, "price": 1.43,
"links": ["https://discord.gift/xxxxxxxxxxxxxxxx", "https://discord.gift/xxxxxxxxxxxxxxxx"],
"missing": 0 }]
},
"balance": 39.64
}
# 402 if your balance is too low (nothing is charged)
{ "error": "Not enough balance. Top up your wallet first.", "code": "insufficient_balance" }
order.idstringPass it to the status endpoint.order.statusstringpaid or delivered, see statuses.order.totalnumberAmount charged to your balance.order.items[].linksarrayDelivered discord.gift links for that item.order.items[].missingnumberLinks still being prepared for that item.balancenumberYour balance after the charge.replayedbooleanOnly present when an Idempotency-Key matched an earlier order./api/v1/orders/{id}Poll every 30 to 60 seconds until the status is delivered, then read the links from items[].links. You can only read your own orders. Links are also emailed to your account; redeem each within 47 hours.
curl {BASE}/api/v1/orders/KS-B125312CBAC8 \
-H "Authorization: Bearer ks_live_..."
# 200 OK
{
"order": {
"id": "KS-B125312CBAC8",
"status": "delivered",
"total": 2.86,
"createdAt": 1793071787921,
"deliveredAt": 1793071787925,
"items": [{ "sku": "1545192554469920779", "name": "Alt Raccoon", "qty": 2,
"links": ["https://discord.gift/xxxxxxxxxxxxxxxx", "https://discord.gift/xxxxxxxxxxxxxxxx"],
"missing": 0 }]
}
}
/api/v1/ordersYour orders, newest first.
limitnumber1 to 100, default 20.beforenumberFor the next page: the createdAt of the last order you received.# 200 OK
{ "orders": [{ "id": "KS-B125312CBAC8", "status": "delivered", "total": 2.86, "items": 2,
"createdAt": 1793071787921, "deliveredAt": 1793071787925 }] }
/api/v1/meYour account, balance and plan. Use it to check when your plan expires.
# 200 OK
{
"email": "[email protected]",
"balance": 39.64,
"currency": "EUR",
"plan": { "plan": "monthly", "expiresAt": 1795665420406, "active": true }
}
/api/v1/balanceJust the balance: { "balance": 39.64, "currency": "EUR" }.
Order statuses
missing > 0).items[].links and were emailed to you.delivered is terminal. Stop polling once you see it.
Errors
Errors return a non-2xx status and a JSON body with a readable error and a stable code.
Rate limits
Up to 120 requests and 30 orders per minute per account. Each order takes at most 10 of the same item and 50 items in total. On a 429, back off and retry.