Dokumentasi API NEOS B2B

Versi 1 · Base URL https://b2b.neos.id/api/v1

Pendahuluan

API NEOS B2B dipakai untuk menjual pulsa dan paket data Telkomsel dari sistem Anda. Semua request dan respons berformat JSON (UTF-8). Transaksi memotong saldo deposit akun Anda; bila transaksi gagal, saldo otomatis dikembalikan.

Akun harus sudah disetujui NEOS. Sebelum memanggil API: buat API key, daftarkan IP server, isi callback URL, dan topup saldo di menu Pengaturan & Topup.

Autentikasi

Kirim API key di header setiap request:

X-Api-Key: neos_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Selain API key, IP sumber request harus terdaftar di IP whitelist. Request dari IP lain ditolak dengan HTTP 403 IP_NOT_WHITELISTED. Simpan API key hanya di server; jangan pernah memakainya dari aplikasi mobile atau browser.

Format respons

Respons sukses:

{
  "success": true,
  "data": { ... }
}

Respons gagal (HTTP 4xx/5xx):

{
  "success": false,
  "error": { "code": "INSUFFICIENT_BALANCE", "message": "Saldo tidak cukup" }
}

Cek saldo

GET/api/v1/balance
{
  "success": true,
  "data": { "balance": 15250000, "currency": "IDR" }
}

Daftar produk pulsa

GET/api/v1/products/pulsa?msisdn=081234567890
ParameterKeterangan
msisdnWajib. Nomor tujuan (format 08xx, 628xx, atau +628xx).
{
  "success": true,
  "data": {
    "msisdn": "081234567890",
    "type": "PULSA",
    "products": [
      { "product_code": "PULSA-10000", "name": "Pulsa 10.000", "category": "Pulsa Reguler", "nominal": 10000, "price": 10373 },
      { "product_code": "PULSA-50000", "name": "Pulsa 50.000", "category": "Pulsa Reguler", "nominal": 50000, "price": 50678 }
    ]
  }
}

Daftar produk paket data

GET/api/v1/products/data?msisdn=081234567890

Paket yang tersedia berbeda per nomor (termasuk promo khusus nomor tersebut), jadi selalu ambil daftar untuk nomor tujuan sebelum bertransaksi.

{
  "success": true,
  "data": {
    "msisdn": "081234567890",
    "type": "DATA",
    "products": [
      {
        "product_code": "DATA-00110944",
        "name": "Super Seru Promo 7 Hari",
        "category": "Kamu Banget Nih",
        "quota": "DATA National/Internet 7 GB Nasional 7 Days",
        "validity": "7 hari",
        "price": 22800
      }
    ]
  }
}

Buat transaksi

POST/api/v1/transaction
Field (JSON)Keterangan
ref_idWajib. ID transaksi unik dari sistem Anda (1–64 karakter: huruf, angka, . _ -). ref_id yang sama tidak akan diproses dua kali.
msisdnWajib. Nomor tujuan.
product_codeWajib. Dari daftar produk, mis. PULSA-10000 atau DATA-00110944.
POST /api/v1/transaction
Content-Type: application/json
X-Api-Key: neos_live_xxxx

{ "ref_id": "INV-1001", "msisdn": "081234567890", "product_code": "DATA-00110944" }

Respons HTTP 201 — transaksi diterima dan sedang diproses:

{
  "success": true,
  "data": {
    "trx_id": "TX-1793900012345",
    "ref_id": "INV-1001",
    "type": "DATA",
    "product_code": "DATA-00110944",
    "product_name": "Super Seru Promo 7 Hari",
    "msisdn": "081234567890",
    "price": 22800,
    "status": "PENDING",
    "sn": null,
    "message": "Transaksi sedang diproses",
    "created_at": "2026-11-05 21:30:12",
    "updated_at": "2026-11-05 21:30:12"
  }
}
  • price adalah harga final yang dipotong dari saldo saat transaksi dibuat (harga terbaru, bisa berbeda dari daftar produk bila ada perubahan harga).
  • Status akhir (SUCCESS / FAILED) dikirim lewat callback, atau cek manual lewat cek status.
  • Bila koneksi terputus sebelum respons diterima, jangan buat ref_id baru: cek status dengan ref_id yang sama. Mengirim ulang ref_id yang sama menghasilkan HTTP 409 DUPLICATE_REF_ID beserta data transaksi yang sudah ada.

Cek status transaksi

GET/api/v1/transaction/{ref_id}

Bisa memakai ref_id Anda atau trx_id NEOS. Data sama dengan respons buat transaksi.

{
  "success": true,
  "data": {
    "trx_id": "TX-1793900012345",
    "ref_id": "INV-1001",
    "status": "SUCCESS",
    "sn": "DGPS261105213012345678901",
    "message": "Transaksi sukses",
    ...
  }
}

Callback

Saat status transaksi menjadi final, NEOS mengirim POST ke callback URL Anda:

POST https://api.perusahaan.co.id/neos/callback
Content-Type: application/json
X-Neos-Timestamp: 1793900042
X-Neos-Signature: 5f0c...e91a

{
  "event": "transaction.updated",
  "data": {
    "trx_id": "TX-1793900012345",
    "ref_id": "INV-1001",
    "type": "DATA",
    "product_code": "DATA-00110944",
    "product_name": "Super Seru Promo 7 Hari",
    "msisdn": "081234567890",
    "price": 22800,
    "status": "SUCCESS",
    "sn": "DGPS261105213012345678901",
    "message": "Transaksi sukses",
    "created_at": "2026-11-05 21:30:12",
    "updated_at": "2026-11-05 21:30:41"
  }
}

Verifikasi signature

X-Neos-Signature = HMAC-SHA256 (hex) dari timestamp + "." + body mentah dengan callback secret (menu Pengaturan). Tolak callback bila signature tidak cocok atau timestamp lebih dari 5 menit.

<?php
$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_NEOS_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_NEOS_SIGNATURE'] ?? '';
$hitung = hash_hmac('sha256', $ts . '.' . $body, CALLBACK_SECRET);
if (!hash_equals($hitung, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(401);
    exit;
}
$data = json_decode($body, true)['data'];
// update transaksi berdasarkan $data['ref_id'] dan $data['status'] (idempoten)
http_response_code(200);

Balas HTTP 2xx dalam 15 detik. Bila tidak, callback diulang hingga 6 kali (1 menit, 5 menit, 15 menit, 1 jam, 2 jam). Callback bisa terkirim lebih dari sekali — proses secara idempoten berdasarkan ref_id. Riwayat pengiriman ada di menu Log.

Alur & status transaksi

StatusArtiSaldo
PENDINGDiterima, sedang diproses operator.Sudah dipotong
SUCCESSBerhasil. sn berisi nomor seri / referensi operator.Tetap terpotong
FAILEDGagal. Alasan di message.Dikembalikan otomatis

Sebagian besar transaksi selesai dalam hitungan detik. Bila operator belum memberi jawaban pasti, status tetap PENDING dan terus dicek otomatis — transaksi PENDING tidak boleh diulang dengan ref_id baru.

Kode error

HTTPKodeArti
401UNAUTHORIZEDAPI key kosong atau tidak valid
403IP_NOT_WHITELISTEDIP sumber belum terdaftar
403ACCOUNT_INACTIVEAkun belum aktif / ditangguhkan
403PRODUCT_DISABLEDProduk tidak aktif untuk akun Anda
402INSUFFICIENT_BALANCESaldo tidak cukup
409DUPLICATE_REF_IDref_id sudah dipakai (data transaksi lama ikut dikirim)
422INVALID_MSISDN / INVALID_REF_ID / INVALID_PRODUCTParameter tidak valid
422PRODUCT_UNAVAILABLEProduk tidak tersedia untuk nomor tujuan saat ini
404TRANSACTION_NOT_FOUND / NOT_FOUNDTransaksi / endpoint tidak ditemukan
405METHOD_NOT_ALLOWEDMetode HTTP salah
503SERVICE_UNAVAILABLE / PRODUCT_UNAVAILABLELayanan sementara tidak tersedia, coba lagi

Contoh kode

cURL

curl https://b2b.neos.id/api/v1/products/data?msisdn=081234567890 \
  -H "X-Api-Key: $NEOS_API_KEY"

curl -X POST https://b2b.neos.id/api/v1/transaction \
  -H "X-Api-Key: $NEOS_API_KEY" -H "Content-Type: application/json" \
  -d '{"ref_id":"INV-1001","msisdn":"081234567890","product_code":"PULSA-10000"}'

PHP

<?php
function neos($method, $path, $body = null) {
    $ch = curl_init('https://b2b.neos.id/api/v1' . $path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 60,
        CURLOPT_HTTPHEADER     => ['X-Api-Key: ' . getenv('NEOS_API_KEY'), 'Content-Type: application/json'],
        CURLOPT_POSTFIELDS     => $body ? json_encode($body) : null,
    ]);
    $res = json_decode(curl_exec($ch), true);
    curl_close($ch);
    return $res;
}

$produk = neos('GET', '/products/data?msisdn=081234567890');
$trx = neos('POST', '/transaction', [
    'ref_id' => 'INV-1001',
    'msisdn' => '081234567890',
    'product_code' => $produk['data']['products'][0]['product_code'],
]);
echo $trx['data']['status']; // PENDING

Node.js

const res = await fetch('https://b2b.neos.id/api/v1/transaction', {
  method: 'POST',
  headers: { 'X-Api-Key': process.env.NEOS_API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({ ref_id: 'INV-1001', msisdn: '081234567890', product_code: 'PULSA-10000' }),
});
const json = await res.json();