Tài liệu Partner API.
Tích hợp Robux 120H vào shop của bạn: giá, stock, đặt đơn và đối soát.
Từ kết nối đến đơn đầu tiên
Mọi tài khoản GekiStore đang hoạt động đều có thể tự tạo key. API dùng chung số dư ví hiện tại, mỗi đơn xử lý một Gamepass, từ 10 đến 10.000 Robux trước thuế.
- Tạo key tại Dashboard API và nạp tiền vào ví GekiStore.
- Tra cứu Username, Gamepass và tier giá.
- Gọi
orders/quote, lấydata.totallàmmaxTotal. - Lưu body và Idempotency-Key ở shop, rồi gọi
orders. - Lưu orderId của GekiStore, tra cứu mỗi 15–30 giây đến khi
terminal=true.
URL gọi API
https://gekistore.com/api/partner/v1/index.php?endpoint=balance
Thay balance bằng endpoint trong bảng bên dưới. Dạng URL này hoạt động không cần cấu hình rewrite. Khi hosting bật rewrite, có thể dùng https://gekistore.com/api/partner/v1/balance.
Tích hợp giữa hai máy chủ. Không đặt API Key trong JavaScript giao diện hoặc gửi qua URL. API không mở CORS cho trình duyệt shop khác.
Authorization: Bearer
curl 'https://gekistore.com/api/partner/v1/index.php?endpoint=balance' \ -H "Authorization: Bearer $GEKISTORE_API_KEY"
Tất cả endpoint yêu cầu API Key. Mỗi tài khoản có tối đa 5 key đang hoạt động; mỗi key có hạn 365 ngày và chỉ hiện đầy đủ một lần khi tạo. Tạo key mới, cập nhật máy chủ shop rồi thu hồi key cũ khi cần thay.
Key đã thu hồi không dùng được, nhưng đơn đã thanh toán vẫn tiếp tục xử lý. Tài khoản bị khóa sẽ không thể gọi API.
Cùng rate GekiStore, ưu đãi theo doanh số Robux
shopRate dùng đúng giá đang bán ở trang Robux 120H. tierId là mã chọn mức giá; truyền lại nguyên chuỗi hoặc chọn auto. Tier chọn thủ công hết stock hoặc đổi giá sẽ trả lỗi để shop báo giá lại.
Khi tổng Robux 120H đã xác minh thành công vượt 20.000, các đơn API đặt sau đó được giảm 2%. Tổng tính toàn bộ đơn 120H của tài khoản trên web và API, theo giá trị Gamepass trước thuế. Đúng 20.000 chưa được giảm. Không tính đơn đang xử lý, thất bại, hủy, hoàn tiền hoặc chỉ có nhãn thành công chưa xác minh.
retailTotal = giá checkout Robux 120H của GekiStore discountAmount = floor(retailTotal × 2 / 100), nếu đủ điều kiện total = retailTotal − discountAmount
Tiền làm tròn nguyên VND; giao diện shop hiển thị G với cùng giá trị số. partnerRate là giá tham khảo mỗi Robux sau ưu đãi; tổng chính xác lấy từ orders/quote. Số Robux người nhận được sau thuế phụ thuộc cơ chế Roblox; không dùng giá sau thuế làm robuxAmount.
Ưu đãi không cộng dồn với chương trình khác. Đơn đưa tổng vượt mốc sẽ mở ưu đãi cho các đơn API tiếp theo sau khi được xác minh thành công.
Các chức năng hỗ trợ
| Method | endpoint= | Mô tả |
|---|---|---|
| GET | balance | Số dư ví và điều kiện ưu đãi. |
| GET | rates | Giá bán, các tier và mức giảm của tài khoản. |
| GET | stock | Tổng kho, giới hạn đơn và các tier. |
| GET | stock/detailed | tierId, shopRate, partnerRate, stock, maxOrderRobux. |
| GET | roblox/user&username=TenRoblox | Tra cứu tài khoản Roblox. |
| GET | gamepasses&username=TenRoblox | Gamepass đang bán: gamepassId, price, placeId. |
| POST | orders/quote | Kiểm tra đầu vào và báo tổng tiền; không trừ ví. |
| POST | orders | Tạo đơn, trừ ví một lần. Bắt buộc Idempotency-Key. |
| GET | orders&page=1&limit=20 | Liệt kê đơn API của tài khoản; lọc thêm clientOrderId. |
| GET | orders/{orderId} | Chi tiết một đơn API thuộc tài khoản. |
| GET | transactions&page=1&limit=20 | Biên nhận trừ/hoàn ví của đơn API; phân trang theo đơn. |
page bắt đầu từ 1, limit từ 1 đến 100. orders và transactions chỉ gồm đơn tạo qua Partner API của tài khoản hiện tại. Không cần key cũ để tra cứu đơn được tạo bởi key đó: key mới cùng tài khoản vẫn tra cứu được.
Đồng bộ dùng tiến trình đối soát GekiStore hiện có. Phiên bản này dùng polling; chưa có webhook gửi tới shop đối tác.
Báo giá trước khi trừ ví
curl 'https://gekistore.com/api/partner/v1/index.php?endpoint=orders/quote' \
-H "Authorization: Bearer $GEKISTORE_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"robloxUsername": "TenRoblox",
"gamepassId": "123456789",
"robuxAmount": 100,
"tierId": "auto"
}'| Trường | Kiểu | Quy tắc |
|---|---|---|
| robloxUsername | string | Bắt buộc; tên đăng nhập, không phải tên hiển thị. |
| gamepassId | string | Bắt buộc; ID Gamepass đang bán, thuộc đúng người nhận. |
| robuxAmount | integer | Bắt buộc; bằng giá Gamepass trước thuế, từ 10–10.000. |
| tierId | string | Mặc định auto; hoặc mã từ stock/detailed. Không gửi rate nguồn. |
| inputMethod | string | username (mặc định); manual nếu cần xác minh trực tiếp Gamepass. |
| placeId | string | Tùy chọn; ID Experience chứa Gamepass. |
| maxTotal | integer | Bắt buộc khi tạo đơn. Tổng VND cao nhất shop đồng ý trả. |
| clientOrderId | string | Tùy chọn; mã đơn riêng của shop, tối đa 80 ký tự, duy nhất trong tài khoản. |
Tạo đơn
curl 'https://gekistore.com/api/partner/v1/index.php?endpoint=orders' \
-H "Authorization: Bearer $GEKISTORE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: shop-order-20260924-0001' \
--data '{
"robloxUsername": "TenRoblox",
"gamepassId": "123456789",
"robuxAmount": 100,
"tierId": "auto",
"maxTotal": 15000,
"clientOrderId": "SHOP-0001"
}'Username, Gamepass và tổng tiền trong ví dụ là minh họa. Thay bằng dữ liệu thực và maxTotal từ báo giá. Header Idempotency-Key bắt buộc, 8–128 ký tự chữ, số hoặc . _ : -.
Phản hồi tạo đơn: HTTP 202
{
"success": true,
"data": {
"order": {
"orderId": "ORD_example123456",
"clientOrderId": "SHOP-0001",
"robloxUsername": "TenRoblox",
"gamepassId": "123456789",
"robuxAmount": 100,
"amount": 14700,
"currency": "VND",
"retailAmount": 15000,
"discountPercent": 2,
"discountAmount": 300,
"status": "processing",
"terminal": false,
"refundAmount": 0
},
"replayed": false
},
"error": null,
"requestId": "gkp_example",
"timestamp": "2026-09-24T00:00:00Z"
}HTTP 202 xác nhận giao dịch đã được ghi nhận để xử lý; không có nghĩa là Robux đã giao. orderId là mã ổn định tại GekiStore. Nếu tiến trình lưu/gửi đơn bị ngắt sau khi trừ ví, hệ thống dùng biên nhận để khôi phục đúng đơn đó.
Một đơn shop, một Idempotency-Key
- Lưu key và body vào database shop trước khi gửi lần đầu.
- Mất kết nối, HTTP 409 REQUEST_IN_PROGRESS hoặc 503: gửi lại đúng key và body. Không sinh key mới.
- Cùng key và nội dung sau khi đã trừ ví: trả cùng orderId, không trừ lần hai; header
X-Idempotent-Replay: true. - Cùng key nhưng đổi username, Gamepass, số Robux, tier, maxTotal hoặc clientOrderId: HTTP 409 IDEMPOTENCY_CONFLICT.
- Key chống trùng áp dụng cho toàn bộ tài khoản, không phụ thuộc API Key. Bản ghi được giữ cùng lịch sử giao dịch, không tự hết hạn sau 24 giờ.
clientOrderIdđã dùng không được tạo lại bằng key khác. Có thể tra cứuorders&clientOrderId=SHOP-0001.- Một tài khoản chỉ có một yêu cầu tạo đơn đang chạy; các yêu cầu đồng thời nhận REQUEST_IN_PROGRESS và cần retry.
Nếu lần gọi chưa đi đến bước trừ ví (đầu vào sai, thiếu tiền, giá thay đổi), chưa có đơn được ghi nhận. Hãy xử lý lỗi trước; khi chưa rõ kết quả giao dịch, luôn giữ nguyên key và body.
Trạng thái đơn và hoàn tiền
| status | terminal | Ý nghĩa |
|---|---|---|
| processing | false | Đã ghi nhận, đang xử lý gửi đơn. |
| delivering | false | Đơn được tiếp nhận, đang giao. |
| reviewing | false | Cần xác minh/đối soát; chưa kết luận hoàn tiền. |
| completed | true | Hoàn thành đã được xác minh; không hoàn ví. |
| refunded | true | Ví đã được hoàn đúng số tiền thực trả, một lần. |
Không tự hoàn cho khách của shop chỉ vì timeout, HTTP lỗi, quá 120 giờ hoặc chưa có OrderID. Chỉ coi giao dịch đã hoàn khi API trả status=refunded và refundAmount>0.
Cơ chế đối soát và thao tác Admin hiện có của GekiStore tiếp tục áp dụng, gồm Admin tự xác minh đơn chưa có OrderID. Partner không được quyền tự xác nhận đã hoàn hay tự cộng tiền. Phiên bản API này không cung cấp endpoint hủy/hoàn trực tiếp; liên hệ hỗ trợ kèm orderId khi cần xử lý.
Giới hạn truy cập theo tài khoản
120 request/phút cho các GET thông thường; 20 request/phút dùng chung cho POST và tra cứu Roblox/Gamepass. Các API Key cùng tài khoản dùng chung hạn mức. Theo dõi X-RateLimit-* và Retry-After. Body JSON tối đa 16 KB.
| HTTP | Mã tiêu biểu | Cách xử lý |
|---|---|---|
| 401 | UNAUTHORIZED | Kiểm tra key, hạn dùng và trạng thái tài khoản. |
| 404 | ORDER_NOT_FOUND | Kiểm tra orderId thuộc đúng tài khoản và tạo qua API. |
| 409 | PRICE_CHANGED / TIER_CHANGED | Báo giá lại và xác nhận tổng tiền; ví chưa bị trừ nếu đây là lần tạo mới. |
| 409 | REQUEST_IN_PROGRESS | Đợi vài giây, retry đúng key và body. |
| 409 | IDEMPOTENCY_CONFLICT / CLIENT_ORDER_EXISTS | Tra cứu đơn cũ; không tạo key mới để đặt lại. |
| 409 | GAMEPASS_ORDER_PENDING | Gamepass đã có đơn chưa kết thúc của tài khoản. |
| 422 | INVALID_* / INSUFFICIENT_BALANCE | Sửa đầu vào hoặc nạp thêm tiền. |
| 423 | SALES_LOCKED | Cửa hàng đang tạm khóa nhận đơn mới. |
| 429 | RATE_LIMITED | Chờ số giây trong Retry-After. |
| 503 | WALLET_BUSY / SERVICE_UNAVAILABLE | Retry đúng key và body; không tự kết luận chưa trừ tiền. |
{
"success": false,
"data": null,
"error": {"code": "INSUFFICIENT_BALANCE", "message": "Số dư ví GekiStore không đủ.", "details": {}},
"requestId": "gkp_example",
"timestamp": "2026-09-24T00:00:00Z"
}Lưu requestId để gửi hỗ trợ khi có lỗi. Không ghi API Key vào log.
PHP cURL trên máy chủ shop
<?php
// Chạy trên máy chủ shop. Lưu key trong biến môi trường.
$key = getenv('GEKISTORE_API_KEY');
function requestGeki(string $endpoint, ?array $body = null, string $idem = ''): array {
global $key;
$url = 'https://gekistore.com/api/partner/v1/index.php?endpoint=' . rawurlencode($endpoint);
$ch = curl_init($url);
$headers = ['Authorization: Bearer ' . $key, 'Accept: application/json'];
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
if ($idem !== '') $headers[] = 'Idempotency-Key: ' . $idem;
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body, JSON_THROW_ON_ERROR));
}
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers, CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 90, CURLOPT_FOLLOWLOCATION => false]);
$raw = curl_exec($ch);
if ($raw === false) {
curl_close($ch);
throw new RuntimeException('Kết nối gián đoạn: tra cứu hoặc retry cùng key + body.');
}
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['http' => $http, 'body' => json_decode($raw, true, 512, JSON_THROW_ON_ERROR)];
}
$cart = ['robloxUsername' => 'TenRoblox', 'gamepassId' => '123456789',
'robuxAmount' => 100, 'tierId' => 'auto'];
$quote = requestGeki('orders/quote', $cart);
if (empty($quote['body']['success'])) {
throw new RuntimeException('Chưa có báo giá hợp lệ; không tạo đơn.');
}
$body = $cart + ['maxTotal' => $quote['body']['data']['total'],
'clientOrderId' => 'SHOP-0001'];
$idem = 'shop-order-20260924-0001';
// BẮT BUỘC lưu $body + $idem vào DB shop TRƯỚC lần gửi đầu tiên.
// Khi retry, nạp đúng body và key đã lưu, không tạo key mới.
$result = requestGeki('orders', $body, $idem);
if (!empty($result['body']['success'])) {
$orderId = $result['body']['data']['order']['orderId'];
// Lưu $orderId; job nền gọi requestGeki('orders/' . $orderId) mỗi 15–30 giây.
}