Limitz Store API Resellerv2.0
OpenAPI JSON Masuk & ambil API key

API Reseller Limitz Store

Jual produk Limitz Store dari website, bot WhatsApp, bot Telegram, spreadsheet, atau aplikasi apa pun. Saldo yang dipakai = Saldo Akun kamu, harga mengikuti level akunmu.

BASE https://limitzstore.com/api/v2
1
Ambil API key
Masuk, buka Pengaturan Akun, tekan Reset Api Key.
2
Atur keamanan
Isi Whitelist IP server kamu dan Callback URL (untuk notifikasi status).
3
Panggil API
Kirim header X-API-Key di setiap permintaan.
curl -X POST https://limitzstore.com/api/v2/balance \
  -H "X-API-Key: API_KEY_KAMU"

Semua endpoint menerima POST dengan body JSON (Content-Type: application/json) atau form biasa. Endpoint yang hanya membaca data juga boleh GET dengan parameter di URL. Endpoint order wajib POST.

Autentikasi & keamanan

CaraContoh
Header (dianjurkan)X-API-Key: MG-1a2b3c...
Header BearerAuthorization: Bearer MG-1a2b3c...
Field body{"api_key": "LZ-1a2b3c..."} (untuk alat yang tidak bisa mengatur header)

API key = akses ke saldo kamu. Simpan di server/environment variable, jangan di aplikasi HP, kode JavaScript halaman web, atau chat. Bocor? Tekan Reset Api Key, key lama langsung mati.

Whitelist IP

Isi IP publik server yang memanggil API di Pengaturan Akun. Bisa lebih dari satu (pisahkan koma) dan boleh CIDR, mis. 203.0.113.10, 198.51.100.0/24. Kosong = semua IP boleh (tidak dianjurkan). Tidak tahu IP server kamu? Panggil /profile, lihat your_ip.

Batas permintaan

JenisBatas
Semua endpoint120 permintaan / menit / akun
/order30 order / menit / akun
/check-id30 cek / menit / akun

Lewat batas = HTTP 429 kode RATE_LIMITED; tunggu beberapa detik lalu coba lagi.

IP kami

Webhook dikirim dari IP server kami 36.50.77.116. Bila server kamu memakai firewall, izinkan IP ini ke Callback URL. Selalu verifikasi tanda tangan, jangan hanya mengandalkan IP.

Format respons & kode error

Setiap respons berupa JSON dengan HTTP status yang sesuai.

// berhasil
{ "status": true,  "message": "OK", "data": { ... } }

// gagal
{ "status": false, "message": "Saldo tidak mencukupi. Total bayar Rp 21.500", "error": { "code": "INSUFFICIENT_BALANCE" }, "data": null }
HTTPerror.codeArti & tindakan
401MISSING_API_KEY, INVALID_API_KEYHeader API key tidak ada / salah.
403IP_NOT_WHITELISTEDIP pemanggil belum di whitelist (IP-nya ada di error.ip).
403ACCOUNT_DISABLEDAkun dinonaktifkan, hubungi admin.
402INSUFFICIENT_BALANCESaldo kurang, isi saldo dulu.
404ORDER_NOT_FOUND, GAME_NOT_FOUND, ENDPOINT_NOT_FOUNDData tidak ditemukan / alamat salah.
405METHOD_NOT_ALLOWEDOrder harus POST.
409OUT_OF_STOCKStok produk habis.
422INVALID_TARGETID tujuan kosong / tidak ditemukan / region tidak dilayani.
422PRODUCT_REQUIRED, PRODUCT_UNAVAILABLE, INVALID_REF_ID, MISSING_USER_ID, ORDER_REJECTEDPeriksa isi permintaan, pesan detail ada di message.
429RATE_LIMITEDTerlalu cepat, tunggu sebentar.
503PRICE_UPDATINGHarga produk sedang diperbarui, coba beberapa saat lagi.

Status pesanan

statusArtiFinal?
ProcessingSedang dikirim ke providerBelum
SuccessBerhasil, SN/kode ada di snYa
PartialSebagian berhasil (produk berisi beberapa kode)Ya
Canceled / FailedGagal; saldo dikembalikan otomatis (status lalu menjadi Refunded)Ya
RefundedGagal dan saldo sudah dikembalikanYa

Alur order yang benar

/games→/products→/check-id (opsional)→/order + ref_id→webhook / /status
  1. Ambil daftar produk sekali lalu simpan (cache) beberapa menit; jangan memanggil /products di setiap pesan pembeli.
  2. Buat ref_id unik untuk setiap pesanan (nomor invoice di sistemmu). Koneksi putus atau timeout? Kirim ulang ref_id yang sama: kamu akan menerima pesanan yang sama, saldo tidak terpotong dua kali.
  3. Order diproses di belakang layar (asinkron). Respons pertama berstatus Processing.
  4. Tunggu webhook untuk status final. Tanpa webhook? Cek /status tiap 10-30 detik, berhenti saat status final.

Profil akun

GETPOST /profile

Info akun pemilik API key. Alias lama: /account.

{
  "status": true, "message": "OK",
  "data": {
    "username": "tokobudi", "level": "Gold", "level_name": "Gold", "balance": 1250000,
    "whatsapp": "08123456789", "callback_url": "https://tokobudi.com/mg-webhook",
    "ip_whitelist": ["203.0.113.10"], "your_ip": "203.0.113.10"
  }
}

Saldo

GETPOST /balance
{ "status": true, "message": "OK", "data": { "balance": 1250000 } }

Daftar game

GETPOST /games

Game yang bisa dipesan beserta kolom tujuan (fields) yang harus dikirim saat order. key = nama field di /order.

ParameterTipeKeterangan
qstringOpsional, cari nama/slug game.
{
  "status": true, "message": "OK",
  "data": [{
    "game": "Mobile Legends", "slug": "mobile-legends", "category": "Top Up Game", "products": 120,
    "fields": [
      { "key": "user_id", "title": "User ID", "type": "number", "required": true },
      { "key": "zone_id", "title": "Server",  "type": "number", "required": true }
    ],
    "check_id": true
  }, {
    "game": "Genshin Impact", "slug": "genshin-impact", "products": 18,
    "fields": [
      { "key": "user_id", "title": "UID", "type": "number", "required": true },
      { "key": "zone_id", "title": "Pilih Server", "type": "select", "required": true,
        "options": [{ "value": "asia", "label": "Asia" }, { "value": "euro", "label": "Europe" }] }
    ],
    "check_id": false
  }]
}

Daftar produk & harga

GETPOST /products

Harga sudah mengikuti level akunmu. Hanya produk yang bisa dipesan lewat API yang muncul. Alias lama: /product.

ParameterTipeKeterangan
gamestringOpsional, slug / nama / id game, mis. mobile-legends. Dianjurkan diisi supaya respons kecil.
categorystringOpsional, nama kategori produk persis.
qstringOpsional, cari nama produk, mis. diamond.
product_idintegerOpsional, satu produk saja.
{
  "status": true, "message": "OK",
  "data": [{
    "product_id": 1201, "game": "Mobile Legends", "game_slug": "mobile-legends", "category": "Diamond",
    "product": "86 Diamonds", "price": 21500, "original_price": null,
    "stock": null, "max_qty": 1, "need_target": true
  }]
}

stock null = tidak dibatasi; angka = stok tersisa (produk voucher/akun). max_qty > 1 = boleh beli banyak sekaligus lewat qty.

Cek ID / nickname

POST /check-id

Cek ID akun game sebelum order (game dengan check_id: true). Order juga mengecek ID otomatis, jadi endpoint ini untuk menampilkan nickname ke pembeli. Alias lama: /check_nick.

ParameterTipeKeterangan
product_id atau gameinteger / stringwajib salah satu. Pakai product_id supaya region produk ikut dicek.
user_idstringwajib
zone_idstringServer/zone bila game memintanya.
{ "status": true, "message": "OK", "data": { "valid": true, "status": "valid", "nickname": "BudiGG", "region": "ID", "message": "" } }

valid: true ditemukan, false tidak ditemukan / region tidak dilayani, null belum bisa dicek (coba lagi) atau game tidak mendukung.

Order

POST /order

Saldo dipotong saat pesanan diterima (HTTP 201). Gagal di provider = saldo dikembalikan otomatis.

ParameterTipeKeterangan
product_idintegerwajib, dari /products.
user_idstringKolom tujuan pertama (lihat fields di /games). Wajib bila need_target.
zone_idstringKolom tujuan kedua (server/zone).
field_3, field_4stringKolom tujuan berikutnya (jarang).
targetstringAlternatif semua kolom dalam satu teks dipisah koma: "12345678,1234".
qtyintegerJumlah (hanya produk dengan max_qty > 1). Bawaan 1.
ref_idstringSangat dianjurkan. Nomor unik dari sistemmu, huruf/angka/tanda hubung, maks 40. ref_id sama = pesanan sama.
curl -X POST https://limitzstore.com/api/v2/order \
  -H "X-API-Key: API_KEY_KAMU" \
  -H "Content-Type: application/json" \
  -d '{"product_id": 1201, "user_id": "12345678", "zone_id": "1234", "ref_id": "INV-20261027-0001"}'

Respons

// HTTP 201 Created
{
  "status": true, "message": "Pesanan diterima dan sedang diproses",
  "data": {
    "order_id": "MG123456271026", "ref_id": "INV-20261027-0001",
    "status": "Processing", "status_text": "Sedang diproses",
    "game": "Mobile Legends", "product": "86 Diamonds", "product_id": 1201, "qty": 1,
    "user_id": "12345678", "zone_id": "1234", "nickname": "BudiGG",
    "price": 21500, "sn": "", "note": "Dalam antrian proses", "created_at": "2026-10-27 10:15:02",
    "balance": 1228500, "idempotent": false
  }
}
ref_id yang sama dikirim lagi? Respons HTTP 200 berisi pesanan yang sudah ada dengan "idempotent": true (saldo tidak dipotong lagi).

Status pesanan

GETPOST /status
ParameterTipeKeterangan
order_idstringNomor pesanan kami, atau
ref_idstringref_id yang kamu kirim saat order.
{
  "status": true, "message": "OK",
  "data": {
    "order_id": "MG123456271026", "ref_id": "INV-20261027-0001",
    "status": "Success", "status_text": "Berhasil",
    "game": "Mobile Legends", "product": "86 Diamonds", "product_id": 1201, "qty": 1,
    "user_id": "12345678", "zone_id": "1234", "nickname": "BudiGG",
    "price": 21500, "sn": "1234567890ABCDEF", "note": "", "created_at": "2026-10-27 10:15:02"
  }
}

Riwayat pesanan

GETPOST /history

Pesanan terbaru akunmu (dari web maupun API). Parameter: limit (1-50, bawaan 20), status (opsional).

Webhook (callback)

Setiap status pesanan berubah, kami mengirim POST JSON ke Callback URL di Pengaturan Akun. Balas HTTP 2xx dalam 10 detik. Callback URL harus alamat publik http(s):// milikmu.

POST https://tokobudi.com/mg-webhook
Content-Type: application/json
X-Event: order.update
X-Signature: 5f0c2b...  (hex HMAC-SHA256 dari body mentah, kunci = API key kamu)

{
  "event": "order.update", "order_id": "MG123456271026", "ref_id": "INV-20261027-0001",
  "status": "Success", "status_text": "Berhasil", "sn": "1234567890ABCDEF",
  "game": "Mobile Legends", "product": "86 Diamonds", "product_id": 1201, "qty": 1,
  "user_id": "12345678", "zone_id": "1234", "price": 21500, "timestamp": 1761534902
}

Verifikasi tanda tangan (wajib)

Siapa pun yang tahu Callback URL kamu bisa mengirim permintaan palsu. Hitung HMAC-SHA256 dari body mentah (sebelum di-parse) dengan API key kamu, bandingkan dengan header X-Signature.

<?php
// webhook.php = Callback URL kamu (isi di Pengaturan Akun)
$raw  = file_get_contents('php://input');
$sign = hash_hmac('sha256', $raw, getenv('MG_API_KEY'));
if (!hash_equals($sign, $_SERVER['HTTP_X_SIGNATURE'] ?? '')) {
    http_response_code(401);
    exit('tanda tangan salah');
}
$e = json_decode($raw, true);
// cari pesanan di sistemmu lewat $e['ref_id'] (atau $e['order_id']), lalu simpan $e['status'] & $e['sn']
http_response_code(200);
echo 'OK';
Webhook bisa datang lebih dari sekali atau tidak berurutan (mis. Canceled lalu Refunded). Simpan status terakhir berdasarkan order_id, jangan mengirim barang dua kali. Webhook gagal (server mati)? Status tetap bisa diambil lewat /status.

Bot WhatsApp

Pola untuk semua bot: bot = program kecil di servermu. Perintah dari chat → bot memanggil API; webhook masuk → bot mengirim pesan ke chat yang memesan. Simpan pasangan ref_id ↔ nomor chat supaya tahu harus membalas ke siapa.

Contoh di bawah memakai whatsapp-web.js (login dengan scan QR). Perintah: !saldo, !produk mobile-legends, !cekid 1201 12345678 1234, !beli 1201 12345678 1234, !status MG123....

// Bot WhatsApp: Node.js 18+  |  npm i whatsapp-web.js qrcode-terminal express
// Jalankan: MG_API_KEY=API_KEY_KAMU node bot-wa.js  -> scan QR dari aplikasi WhatsApp
const { Client, LocalAuth } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
const express = require('express');
const crypto = require('crypto');

const API = 'https://limitzstore.com/api/v2';
const KEY = process.env.MG_API_KEY;
const rupiah = n => 'Rp ' + Number(n).toLocaleString('id-ID');
async function mg(endpoint, data = {}) {
  const r = await fetch(`${API}/${endpoint}`, {
    method: 'POST',
    headers: { 'X-API-Key': KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });
  return r.json();
}

const wa = new Client({ authStrategy: new LocalAuth() });
const chatDariRef = new Map(); // ref_id -> nomor chat (pakai database di produksi)
wa.on('qr', qr => qrcode.generate(qr, { small: true }));
wa.on('ready', () => console.log('Bot WhatsApp siap'));

wa.on('message', async msg => {
  const [perintah, ...a] = msg.body.trim().split(/\s+/);
  switch (perintah.toLowerCase()) {
    case '!saldo': {
      const r = await mg('balance');
      return msg.reply(r.status ? `Saldo: ${rupiah(r.data.balance)}` : r.message);
    }
    case '!produk': { // !produk mobile-legends
      const r = await mg('products', { game: a[0] || '' });
      if (!r.status) return msg.reply(r.message);
      return msg.reply(r.data.slice(0, 40).map(p => `${p.product_id} | ${p.product} | ${rupiah(p.price)}`).join('\n') || 'Produk tidak ditemukan');
    }
    case '!cekid': { // !cekid 1201 12345678 1234
      const r = await mg('check-id', { product_id: a[0], user_id: a[1], zone_id: a[2] || '' });
      return msg.reply(r.status && r.data.valid ? `ID valid: ${r.data.nickname}` : (r.data?.message || r.message));
    }
    case '!beli': { // !beli 1201 12345678 1234
      const ref = 'WA' + Date.now();
      chatDariRef.set(ref, msg.from);
      const r = await mg('order', { product_id: a[0], user_id: a[1], zone_id: a[2] || '', ref_id: ref });
      return msg.reply(r.status
        ? `Pesanan ${r.data.order_id} diterima (${r.data.product}, ${rupiah(r.data.price)}). Tunggu notifikasi ya.`
        : `Gagal: ${r.message}`);
    }
    case '!status': { // !status MG123456271026
      const r = await mg('status', { order_id: a[0] });
      return msg.reply(r.status ? `${r.data.order_id}: ${r.data.status_text}${r.data.sn ? '\nSN: ' + r.data.sn : ''}` : r.message);
    }
  }
});
wa.initialize();

// Callback URL di Pengaturan Akun = https://domain-bot-kamu.com/mg-webhook
const app = express();
app.post('/mg-webhook', express.raw({ type: '*/*' }), async (req, res) => {
  const sign = crypto.createHmac('sha256', KEY).update(req.body).digest('hex');
  const dari = req.get('X-Signature') || '';
  if (dari.length !== sign.length || !crypto.timingSafeEqual(Buffer.from(dari), Buffer.from(sign))) return res.sendStatus(401);
  res.send('OK');
  const e = JSON.parse(req.body.toString());
  const chat = chatDariRef.get(e.ref_id);
  if (chat && e.status !== 'Processing') {
    await wa.sendMessage(chat, `Pesanan ${e.order_id}: ${e.status_text}${e.sn ? '\nSN: ' + e.sn : ''}`);
  }
});
app.listen(3000, () => console.log('Webhook di port 3000'));
Pakai gateway WhatsApp lain (Fonnte, Wablas, Baileys, dll.)? Bagian API-nya sama persis: fungsi mg() dan penerima webhook tinggal dipasang di handler pesan gateway kamu.

Bot Telegram

Buat bot di @BotFather, ambil token, lalu jalankan contoh ini. Chat id disisipkan di ref_id (TG<chat_id>-<waktu>), jadi webhook tahu harus membalas ke chat mana tanpa database.

// Bot Telegram: Node.js 18+  |  npm i telegraf express
// Jalankan: BOT_TOKEN=token_dari_BotFather MG_API_KEY=API_KEY_KAMU node bot-tg.js
const { Telegraf } = require('telegraf');
const express = require('express');
const crypto = require('crypto');

const API = 'https://limitzstore.com/api/v2';
const KEY = process.env.MG_API_KEY;
const rupiah = n => 'Rp ' + Number(n).toLocaleString('id-ID');
async function mg(endpoint, data = {}) {
  const r = await fetch(`${API}/${endpoint}`, {
    method: 'POST',
    headers: { 'X-API-Key': KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });
  return r.json();
}

const bot = new Telegraf(process.env.BOT_TOKEN);
const arg = ctx => ctx.message.text.trim().split(/\s+/).slice(1);

bot.command('saldo', async ctx => {
  const r = await mg('balance');
  ctx.reply(r.status ? `Saldo: ${rupiah(r.data.balance)}` : r.message);
});
bot.command('produk', async ctx => { // /produk free-fire
  const r = await mg('products', { game: arg(ctx)[0] || '' });
  if (!r.status) return ctx.reply(r.message);
  ctx.reply(r.data.slice(0, 40).map(p => `${p.product_id} | ${p.product} | ${rupiah(p.price)}`).join('\n') || 'Produk tidak ditemukan');
});
bot.command('beli', async ctx => { // /beli 1201 12345678 1234
  const [pid, uid, zone] = arg(ctx);
  const ref = `TG${ctx.chat.id}-${Date.now()}`; // chat id ikut di ref -> webhook tahu harus balas ke mana
  const r = await mg('order', { product_id: pid, user_id: uid, zone_id: zone || '', ref_id: ref });
  ctx.reply(r.status ? `Pesanan ${r.data.order_id} diterima, sedang diproses.` : `Gagal: ${r.message}`);
});
bot.command('status', async ctx => { // /status MG123456271026
  const r = await mg('status', { order_id: arg(ctx)[0] });
  ctx.reply(r.status ? `${r.data.order_id}: ${r.data.status_text}${r.data.sn ? '\nSN: ' + r.data.sn : ''}` : r.message);
});
bot.launch();

// Callback URL di Pengaturan Akun = https://domain-bot-kamu.com/mg-webhook
const app = express();
app.post('/mg-webhook', express.raw({ type: '*/*' }), async (req, res) => {
  const sign = crypto.createHmac('sha256', KEY).update(req.body).digest('hex');
  const dari = req.get('X-Signature') || '';
  if (dari.length !== sign.length || !crypto.timingSafeEqual(Buffer.from(dari), Buffer.from(sign))) return res.sendStatus(401);
  res.send('OK');
  const e = JSON.parse(req.body.toString());
  const m = /^TG(-?\d+)-/.exec(e.ref_id || '');
  if (m && e.status !== 'Processing') {
    await bot.telegram.sendMessage(m[1], `Pesanan ${e.order_id}: ${e.status_text}${e.sn ? '\nSN: ' + e.sn : ''}`);
  }
});
app.listen(3000);

n8n, Make, Zapier, Pabbly

Gunakan modul HTTP Request:

IsianNilai
MethodPOST
URLhttps://limitzstore.com/api/v2/order (atau endpoint lain)
HeaderX-API-Key = API key kamu, Content-Type = application/json
Body (JSON){"product_id": 1201, "user_id": "{{id}}", "zone_id": "{{server}}", "ref_id": "{{nomor_pesanan}}"}

Untuk notifikasi status, buat Webhook trigger di n8n/Make lalu isi URL-nya sebagai Callback URL. Verifikasi X-Signature dengan node Crypto (HMAC SHA256, kunci = API key).

Google Sheets (Apps Script)

// Google Sheets > Extensions > Apps Script. Simpan API key di Project Settings > Script properties: MG_API_KEY
function mg(endpoint, data) {
  const res = UrlFetchApp.fetch('https://limitzstore.com/api/v2/' + endpoint, {
    method: 'post',
    contentType: 'application/json',
    headers: { 'X-API-Key': PropertiesService.getScriptProperties().getProperty('MG_API_KEY') },
    payload: JSON.stringify(data || {}),
    muteHttpExceptions: true,
  });
  return JSON.parse(res.getContentText());
}

// Isi sheet "Produk" dengan daftar produk Mobile Legends + harga level kamu
function tarikProduk() {
  const r = mg('products', { game: 'mobile-legends' });
  const sh = SpreadsheetApp.getActive().getSheetByName('Produk') || SpreadsheetApp.getActive().insertSheet('Produk');
  sh.clear().appendRow(['ID', 'Produk', 'Harga']);
  r.data.forEach(p => sh.appendRow([p.product_id, p.product, p.price]));
}

Postman, Insomnia & SDK

Spesifikasi lengkap tersedia dalam format OpenAPI 3.0: https://limitzstore.com/api/v2/openapi.json

  • Postman: Import → Link → tempel URL di atas → isi API key di tab Authorization (API Key, header X-API-Key).
  • Insomnia / Bruno / Hoppscotch: Import from URL.
  • SDK otomatis (PHP, JavaScript/TypeScript, Python, Go, Java, Dart/Flutter, dll.):
    npx @openapitools/openapi-generator-cli generate -i https://limitzstore.com/api/v2/openapi.json -g python -o limitzstore-sdk

Pindah dari API lama

API lama https://api.limitzstore.com/v2 sudah dihentikan (alamatnya tidak aktif dan banyak masalah). Perubahan yang perlu kamu lakukan:

DuluSekarang
https://api.limitzstore.com/v2/...https://limitzstore.com/api/v2/...
AUTHORIZATION: APIKEYX-API-Key: APIKEY (cara lama masih diterima)
product: "110.10" / sku_productproduct_id: 110 (format lama masih diterima)
order_id dari sistemmuref_id (order_id lama masih dibaca sebagai ref_id)
Respons order "data": "MG...""data" berisi objek pesanan lengkap
Callback tanpa tanda tanganHeader X-Signature wajib diverifikasi; isi callback lihat Webhook
Whitelist IP kami 103.89.0.40IP kami 36.50.77.116