REST Architecture
A strictly typed, highly atomic engine. Securely drain wallet balances and synchronously map dynamic admin-altered constraints into your SaaS.
Target Instance
https://api.bunaistore.shop/v1
Authentication
Every request must include the X-API-Key
header. Keys are generated per-user inside the Telegram bot. Empty, whitespace-only, or
revoked keys return 401.
-H "X-API-Key: shop:12312..."
Type & Error Constraints
-
401
Unauthorized HeaderX-API-Key is invalid, blank, missing, or compromised.
-
402
Insufficient Funds (NSF)Volatile balance calculation failed the lock. Refuse service.
-
403
Forbidden / SuspendedAccount permanently banned. API globally suspended for token.
-
404
Not FoundProduct deleted by admin, or order doesn't belong to you.
-
409
Stock ConflictRace condition: stock was purchased by another buyer between your catalog read and checkout.
-
429
Rate LimitedToo many requests. GET endpoints: 60/min. POST endpoints: 20/min. Per API key. Retry after the
Retry-Afterheader value. -
503
Service UnavailableMarketplace Maintenance Mode active or API globally disabled by admin.
-
502
Bad GatewayUpstream provider failed — virtual number purchase could not be completed. Balance is NOT deducted.
Rate Limits
All /v1/
endpoints are rate-limited per API key. GET responses include Cache-Control: public, max-age=30
headers — clients should respect these to reduce unnecessary calls.
60 req / min
20 req / min
/v1/me
curl -X GET "https://api.bunaistore.shop/v1/me" \
-H "X-API-Key: YOUR_KEY"
{
"user_id": 12345678,
"display_name": "Premium Dev",
"balance": 1500.50,
"api_orders": 45,
"api_spent": 142.00
}
Data Dictionary
user_idinteger
display_namestring |
nullnull if the user has no Telegram
display name set.balancefloat
api_ordersinteger
api_spentfloat
/v1/products
curl -X GET \
"https://api.bunaistore.shop/v1/products?view=variants&type=auto&limit=10" \
-H "X-API-Key: YOUR_KEY"
[
{
"product_id": "ab360422",
"group_id": "d8b627d5",
"group_name": "Amazon Prime",
"variant_name": "1 month",
"display_name": "Amazon Prime > 1 month",
"price": 1.00,
"stock_type": "manual",
"stock_count": 11,
"infinite_stock": false,
"warranty_hours": 1,
"has_promo": false,
"group_share_path": "/group_d8b627d5",
"plan_share_path": "/plan_ab360422_d8b627d5"
}
]
Query Parameters
viewstring |
default: variantsvariants for exact purchasable
plans or groups for grouped
collection cards.
typestring |
optional"auto" or "manual". Omit to return all types.
Any other value is silently ignored and returns everything.
include_noteboolean |
default: falsetrue,
appends the heavy HTML-formatted product descriptions to each object. Off by default to
optimize bandwidth.offsetinteger |
default: 0limit
for pagination.limitinteger |
default: 50100.
Any value above 100 is silently clamped down.Response Fields
group_id /
variant_namestring
group_share_path /
plan_share_pathstring |
nullapi.bunaistore.shop
for collections and exact plans.stock_typeenum
string"auto" = instant digital delivery
(accounts/keys). "manual" = admin
fulfills the order externally after purchase.stock_countinteger
9999 when infinite_stock is true. Otherwise
reflects real-time available stock. Products with 0 stock are automatically pruned from
results.
infinite_stockboolean
true,
unlimited supply. Ignore stock_count.
Admin can toggle this live, switching between unlimited and finite.warranty_hoursinteger
0 = no warranty. Otherwise, the
number of hours the warranty covers from purchase time.has_promoboolean
/v1/products/{id} to inspect the
actual tier breakpoints./v1/product-groups
Use this for collection-level
browsing. Grouped products such as Amazon Prime or Netflix families appear once here, with
optional embedded plans via include_variants=true.
curl -X GET \
"https://api.bunaistore.shop/v1/product-groups?include_variants=true&limit=10" \
-H "X-API-Key: YOUR_KEY"
/v1/products/{id}
curl -X GET \
"https://api.bunaistore.shop/v1/products/PRD_ajS8x" \
-H "X-API-Key: YOUR_KEY"
{
"product_id": "PRD_ajS8x",
"name": "Netflix Premium",
"note": "Read TOS before buying.",
"price": 3.50,
"stock_type": "auto",
"stock_count": 12,
"infinite_stock": false,
"warranty_hours": 720,
"promo_active": true,
"promo_cb": 5.0,
"promo_tiers": {"5": 5.0, "10": 12.0}
}
Extra Properties (vs List)
notestring
"" (empty string) if not configured
— never null. Admin can update this at any time. Always display to end users before
checkout.promo_activeboolean
promo_tiers has data, discounts only
apply when this is true.promo_cbfloat
0.0 if disabled.promo_tiersobject |
{}{"min_qty": discount_%}. Example:
{"5": 5.0} = buying 5+ items gives
5% off. Returns empty {} when no
tiers configured.
/v1/orders
curl -X POST "https://api.bunaistore.shop/v1/orders" \ -H "X-API-Key: YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "product_id": "PRD_XYZ", "qty": 1 }'
{
"status": "success",
"order": {
"order_id": "ORDx8kLm2Qp",
"product_id": "PRD_ajS8x",
"product_name": "Netflix Premium",
"qty": 3,
"timestamp": "2024-06-19T14:32:07",
"base_price": 10.50,
"total_paid": 9.98,
"discount_applied": 0.52,
"stock_type": "auto",
"items": [
"Full account details...\nRegion: US\nPlan: Premium...",
"Full account details...\nRegion: CA\nPlan: Premium...",
"Full account details...\nRegion: UK\nPlan: Premium..."
],
"warranty_expires": "2024-07-19T14:32:07",
"refunded": false,
"after_note": "Use CA VPN for login."
}
}
Each string in
the items array can be hundreds of lines long — full account
credentials, license keys, multi-paragraph instructions, or delivery blobs with
\n newlines embedded. Buying
qty: 12 of a text-heavy
product can produce a response exceeding 50KB+. Always handle items as arbitrarily long
strings. Do not truncate or assume single-line values.
Payload Architecture
qtyinteger |
default: 11. Values ≤ 0 trigger
400.
include_after_noteboolean |
default: falsetrue,
appends the post-purchase setup instructions to the response. Off by default to save
transit bandwidth.timestampISO
stringbase_pricefloat
price × qty.total_paidfloat
discount_appliedfloat
base_price - total_paid. Returns
0.0 if no promo was active.
itemsarray<string>
qty. Each string is one delivered
item — can range from a short email:password to a multi-paragraph blob exceeding 1KB+ with embedded \n newlines (full account details,
license keys, instructions, etc). Always iterate the full array and render each item
independently. Do not assume single-line format.Manual products: Always returns
[] — admin fulfills externally via
bot.warranty_expiresISO string |
nullnull if warranty_hours was 0 at purchase
time.refundedboolean
false.after_notestring
"" (empty
string) if unset or if admin later deletes the product entirely. Do NOT cache — re-fetch
via /v1/orders/{id} for latest
instructions./v1/orders/{id}
curl -X GET \
"https://api.bunaistore.shop/v1/orders/ORD_1A..." \
-H "X-API-Key: YOUR_KEY"
{
"order": {
"order_id": "ORD_1A...",
"product_id": "PRD_ajS8x",
"product_name": "Netflix Premium",
"qty": 1,
"timestamp": "2024-06-19T...",
"total_paid": 3.50,
"stock_type": "auto",
"items": ["email:pass"],
"warranty_expires": "2024-07-19T...",
"refunded": false,
"after_note": "Use Canada VPN."
}
}
Key Differences vs POST
total_paidfloat
base_price and
discount_applied, the lookup only
returns the final paid amount.
after_notestring
"" if the product was deleted.refundedboolean
false to true if admin issues a refund after
the original purchase.Developer
Identity
Manage your
developer profile. All endpoints require X-API-Key authentication.
/v1/developer/me
Returns your API key and live wallet balance — all in one call. No separate balance endpoint needed.
curl -X GET "https://api.bunaistore.shop/v1/developer/me" \
-H "X-API-Key: YOUR_KEY"
{
"user_id": 12345678,
"api_key": "sk_live_a1b2...",
"balance": 142.50 // live, always current
}
Swagger UI Playground
Authorize with your API Key and execute live HTTP requests directly from your browser. Responses will print natively below.