Reseller API

Order akun GSuite & Hotmail/Outlook otomatis, bayar pakai saldo reseller.

Mulai

Base URL: https://apimmprojectgsuite.my.id/api/v1

1. Buka bot, ketik /reseller, daftar, tunggu admin mengaktifkan.
2. Topup saldo reseller (QRIS) di portal.
3. Buat API key di tab API portal. Key cuma muncul sekali, simpan baik-baik.

Autentikasi

Semua endpoint kecuali /ping, /products, /domains wajib pakai API key:

X-API-Key: mmpgsuite_xxxxxxxxxxxxxxxxxxxx
# atau
Authorization: Bearer mmpgsuite_xxxxxxxxxxxxxxxxxxxx

Batas 60 request/menit per key. Header respons: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Lewat batas → 429 rate_limited + Retry-After.

Format respons selalu:

{ "success": true,  "data": { ... } }
{ "success": false, "error": { "code": "...", "message": "..." } }

Endpoint

GET/pingpublik

Cek koneksi.

GET/productspublik

Daftar produk, harga per akun, stok, dan aturan jumlah.

{ "success": true, "data": { "products": [
  { "id": "regular_1d", "name": "GSuite Regular 1 Hari", "duration_days": 1,
    "price_per_account": 150, "min_quantity": 10, "max_quantity": 1000, "quantity_step": 10,
    "stock": 2400, "available": true, "extendable": false },
  { "id": "youtube_b_35d", "name": "GSuite YouTube B 35 Hari", "duration_days": 35,
    "price_per_account": 2000, "min_quantity": 1, "max_quantity": 500,
    "stock": 812, "available": true, "daily_limit": 20 },
  { "id": "hotmail", "name": "Hotmail/Outlook", "price_per_account": 1000,
    "price_tiers": [ {"min_quantity": 10, "price_per_account": 1000}, {"min_quantity": 50, "price_per_account": 900} ],
    "min_quantity": 10, "stock": 530, "available": true,
    "format": "email:password:refresh_token:client_id" }
] } }
GET/domainspublik

Domain yang bisa dipilih per produk. Opsional ?product=regular_1d.

{ "success": true, "data": { "domains": ["..."], "by_product": { "regular_1d": ["..."], "youtube_b_35d": ["..."] } } }
GET/account

Profil reseller: saldo, password & gaya email default.

GET/balance?limit=10

Saldo + mutasi terakhir (topup, spend, refund, adjust).

POST/orders

Buat order. Lihat detail di bawah.

GET/orders?limit=20&offset=0

Riwayat order (tanpa daftar akun).

GET/orders/{trx_id}

Detail order lengkap dengan daftar akun. Pakai ini kalau koneksi putus saat order berjalan.

Buat order

FieldTipeKeterangan
productstringWajib. regular_1d, youtube_b_35d, atau hotmail. (Kompatibel gaya lama: cukup duration_days 1 / 35.)
quantitynumberWajib. Regular: kelipatan 10 (10–1000). YouTube B: 1–500. Hotmail: ≥ minimal tier.
domainstringOpsional (GSuite). Dari /domains. Kosong = dipilih otomatis.
passwordstringOpsional (GSuite). 8–100 karakter tanpa spasi. Kosong = password default akunmu, atau acak.
email_stylestringOpsional (GSuite). berurut / acak.
idempotency_keystringOpsional, sangat disarankan. Key yang sama = order yang sama, aman di-retry, tidak pernah dobel potong saldo.

Sinkron. Request menunggu sampai akun jadi. Set timeout klien minimal 300 detik. Saldo dipotong di awal; akun yang gagal dibuat otomatis direfund ke saldo reseller.

HTTP 201
{ "success": true, "data": {
  "trx_id": "RS-M1ABCD2-XY9ZQ", "status": "success",
  "product": "regular_1d", "duration_days": 1, "quantity": 10,
  "accounts_created": 12, "bonus_accounts": 2, "accounts_failed": 0,
  "price_per_account": 150, "charged": 1500, "refunded": 0, "balance": 48500,
  "domain": "contoh.com", "password": "RahasiaPelanggan1", "email_style": "berurut",
  "expires_at": "2026-10-08T03:11:20+00:00",
  "accounts": ["[email protected]", "[email protected]", "..."] } }

status: success (semua jadi), partial (sebagian jadi, sisanya direfund), failed (respons 502, saldo kembali penuh). 202 = order dengan idempotency_key itu masih diproses — cek lagi lewat GET /orders/{trx_id}.

Hotmail: accounts berisi baris lengkap email:password:refresh_token:client_id.

YouTube B: limit 20 akun/hari (reset 00:00 WIB) sampai total belanjamu Rp500.000, setelah itu bebas limit.

Kode error

HTTPcodeArti
401missing_api_keyHeader API key tidak ada.
401invalid_api_keyKey salah / sudah diganti.
403account_inactiveAkun reseller belum aktif / dinonaktifkan.
402insufficient_balanceSaldo kurang. Ada field required & balance. Saldo tidak dipotong.
409out_of_stockStok kurang / habis. Ada field available. Saldo tidak dipotong.
503product_unavailableProduk sedang maintenance / gangguan. Saldo tidak dipotong.
422daily_limitMelebihi limit harian YouTube B. Ada field remaining.
422validation_errorParameter salah. Ada field field.
404not_foundOrder / endpoint tidak ada.
429rate_limitedLebih dari 60 request/menit. Lihat Retry-After.
502order_failedOrder gagal total, saldo sudah dikembalikan penuh.

Catatan integrasi

Alur yang disarankan

1. Pembeli order di bot/web kamu → kamu terima pembayaran dari pembeli.
2. (opsional) GET /products  → cek stok & harga terbaru.
3. POST /orders dengan idempotency_key unik per pesanan pembeli (mis. ID pesanan di sistemmu).
4. 201 → kirim data.accounts + password ke pembeli. Simpan trx_id.
   502 → order gagal, saldo sudah balik penuh. Tawarkan ulang / refund pembeli.
   402 / 409 / 503 → saldo/stok/produk bermasalah, saldo TIDAK terpotong.

Timeout & retry (penting)

Saldo & refund

Produk

Keamanan & lain-lain

Contoh

cURL

curl -X POST https://apimmprojectgsuite.my.id/api/v1/orders \
  -H "X-API-Key: mmpgsuite_xxx" -H "Content-Type: application/json" \
  --max-time 300 \
  -d '{"product":"regular_1d","quantity":20,"password":"PassKuat123","email_style":"berurut","idempotency_key":"order-0001"}'

Python

import requests
r = requests.post(
    "https://apimmprojectgsuite.my.id/api/v1/orders",
    headers={"X-API-Key": "mmpgsuite_xxx"},
    json={"product": "youtube_b_35d", "quantity": 5, "idempotency_key": "order-0002"},
    timeout=300,
)
print(r.status_code, r.json())

Node.js

const r = await fetch("https://apimmprojectgsuite.my.id/api/v1/orders", {
  method: "POST",
  headers: { "X-API-Key": "mmpgsuite_xxx", "Content-Type": "application/json" },
  body: JSON.stringify({ product: "hotmail", quantity: 10, idempotency_key: "order-0003" }),
  signal: AbortSignal.timeout(300000),
});
console.log(await r.json());