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",
"delivered": true,
"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...",
"delivered": true,
"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.
deliveredboolean
true for "auto" orders. For "manual" orders it is false until the admin delivers the
order (and stays false if
refunded). Poll this endpoint to find out when it flips.
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.