API
← Shop

KinaStore API

A simple REST API for ordering Discord decorations, nameplates, effects and bundles. Find an item, place an order, get the gift link.

connected
> 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…"] }
Base URL
AuthBearer API key, every request
FormatJSON over HTTPS
Billingcharged to your balance, per order
Accessprepaid plan, weekly or monthly

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 in Account → API, either from your wallet balance or straight away in crypto (no top up needed). Once the plan is active you get your API key. Buying again while a plan is active adds the days to the time you have left, and your key stays the same.

Loading plans…

What's included

Full API access

Search, order and track with your key.

Prepaid balance

Top up once with crypto. Every order is charged automatically, no checkout.

Instant activation

Your key works the moment you buy a plan.

Automatic delivery

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 _ . : -.

GET/api/v1/catalog

Search items and their current price. All parameters are optional.

QueryTypeDescription
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
}
GET/api/v1/items/{sku}

One item with its current price, as { "currency", "item" }. Returns 404 unknown_item if the SKU isn't sold.

POST/api/v1/orders

Charges 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.

Body fieldTypeDescription
itemsarrayItems to order: { "sku": string, "qty": 1-10 }.
linksstring | arrayDiscord shop links or bare SKUs. Repeat a link to order it more than once.
HeaderTypeDescription
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" }
ResponseTypeDescription
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.
GET/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 }]
  }
}
GET/api/v1/orders

Your orders, newest first.

QueryTypeDescription
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 }] }
GET/api/v1/me

Your 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 }
}
GET/api/v1/balance

Just the balance: { "balance": 39.64, "currency": "EUR" }.

Order statuses

Charged. Some links are still being prepared (missing > 0).
DeliveredDone. All links are in 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.

StatusCodeMeaning
400invalid_requestMissing or invalid body, unknown SKU, or quantity out of range.
400unknown_itemA Discord shop link didn't match any item.
401missing_api_keyNo key was sent.
401invalid_api_keyWrong key, or it was reset.
402insufficient_balanceTop up your wallet. Nothing was charged.
403plan_expiredKey is valid but there's no active plan.
404order_not_foundUnknown order ID, or not one of yours.
429rate_limitedToo many requests. Back off and retry.
503shop_pausedBuying is paused. Retry shortly.

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.