Documentation
API reference and operating rules for this shop. Every number below describes actual behaviour.
1. Authentication
X-API-Key: mcrx_...- Keys are issued by the shop operator and shown once; only a SHA-256 hash is stored.
- Revocation is immediate: the next request gets
403. - A key belongs to your client. Purchases charge your wallet, exactly as buying on the web does.
- Missing key:
401. Revoked key:403.
2. Endpoints
GET /sale/count — stock available
| Field | Type | Description |
|---|---|---|
day | int | Day bucket (section 3). Default 0. |
GET /sale/count?day=7
{"ok":true,"data":{"sum":92}}POST /sale/claim — buy
Delivers the goods and charges the wallet. All or nothing: if stock is short, nothing is charged and the response is 409.
| Field | Type | Required | Description |
|---|---|---|---|
quantity | int | yes | 1 to 10000. |
day | int | no | Day bucket, default 0. |
order_ref | string | no | Your order id. Repeating the same value is treated as the same order and never charges twice. |
buyer_ref | string | no | Your own customer label. |
check_2fa, cookie | int | no | 1 to include 2FA/cookie in the result. |
POST /sale/claim
Content-Type: application/json
{"quantity":2,"day":0,"order_ref":"BUY-001","buyer_ref":"customer-01"}
{"ok":true,"data":{
"batch_id":"3f2c...","order_ref":"BUY-001",
"requested":2,"delivered":2,
"products":[{"product":"user1|pass1|..."},{"product":"user2|pass2|..."}]
}}POST /sale/release — return goods
Puts claimed goods back for an order. The shop calls it automatically when a delivery comes up short; use it only if you cancel an order yourself.
POST /sale/release
{"order_ref":"BUY-001"}
{"ok":true,"data":{"released":2}}GET /orders/{ref}/download
Web session only (cookie), not an API key. Only the buyer or the owning client can download; anybody else gets 404.
Error codes
| Code | Meaning |
|---|---|
400 | Bad parameters (quantity out of range, malformed JSON, invalid discount code). |
401 / 403 | Missing or invalid key; also unverified email or locked account. |
402 | Wallet balance too low. Nothing charged. |
409 | Not enough stock. Nothing charged. |
502 | Sales service unavailable; any charge is refunded. |
3. Day buckets — exact
Buckets never overlap and cover all time. Dates are in Asia/Ho_Chi_Minh.
day | Actual range | Read as |
|---|---|---|
0 | 6 days ago → today | last 7 days, today included |
1 | today | today only |
7 | 20 → 7 days ago | 7 to 20 days old |
20 | 29 → 21 days ago | 21 to 29 days old, not "20" |
30 | 30 days ago and earlier | 30 days or older |
any other N | exactly day N | one single day |
Verified on sample data: day 0/1/7/20/30 returned 58/4/92/60/88 from the API, identical to direct database counts.
4. Product types
| Kind | Goods come from | Who supplies them |
|---|---|---|
x_accounts | X account pool, filtered by day bucket | Accounts registered by the system |
stock_item | shop.product_stock, one row per unit | You paste them in the panel → Stock |
Manual stock (gmail, outlook, software keys…)
- Where:
shop.product_stock—product_code,secret,state(available/sold/void),order_refonce sold. - Adding: panel → Stock → pick a product → one unit per line.
Gmail:
email|password. Keys: the key string itself. Up to 20,000 lines per import. - On purchase: the oldest
availablerows are taken (FIFO), markedsoldwith the order id, returned verbatim, and mailed. If stock is short, no row is taken at all. - Cancelling: only rows still
available. Sold rows are never deleted.
Images and unit description
- JPG/PNG/WEBP up to 2MB, uploaded when creating or editing a product, stored under
UPLOAD_DIRand served from/uploads/…. Replacing an image deletes the old file. - A "what one unit contains" line is shown under the description so buyers know the delivery format before paying.
5. Discount codes
Entered next to the Buy button. Checked in order; failing any step charges nothing:
- The code exists
- It is enabled
- It has not expired
- The order meets its minimum value
- It has uses left
- The discount is smaller than the order (a code that zeroes the order is refused)
percent applies a percentage (floored to the cent); fixed subtracts a set amount.
A use is recorded only after the order completes, so a failed purchase never burns a use. Managed in panel → Discount codes.
6. Email
- Registration sends a verification link (48 hours, single use, token stored hashed).
- Unverified accounts cannot buy (
403); browsing and topping up stay open. - Resend from the home page, or
POST /verify/resendwhen signed in. - A completed order also emails the delivered file.
7. Panel map
| Page | What it is for |
|---|---|
| Overview | "Needs attention": charged-but-undelivered orders, stale top-ups, ledger drift, low stock |
| Products | Create/edit/delete, day bucket, image, unit description, on/off |
| Stock | Filter by product with exact counts, bulk import, void unsold rows, paging |
| Orders | Search by ref or email; charged/refunded, delivery lines, ledger; refund; download the file |
| Top-ups | Mark paid when the gateway never called back (idempotent), cancel |
| Customers | Balance, orders, ledger, reset password, sign out sessions, lock, adjust balance, unlink Telegram |
| Discount codes | Create, uses, expiry, enable/disable |
| Stats | Orders, units, revenue, customers, top-ups, refunds, wallet liabilities |
| Audit log | Every money-moving action: who, when, why |
Never edit balances with SQL — use "adjust balance" so there is a ledger entry and an audit row. Never delete a product that has sales — switch it off instead.