Autentikasi & Signature
Setiap request ke API IsiKuota harus menyertakan 3 parameter ini di dalam body:
| Parameter | Keterangan |
|---|---|
api_id | ID unik akun API Anda |
timestamp | Waktu sekarang dalam format Unix (detik) |
signature | Kode validasi yang dibuat dari kombinasi API key Anda |
Cara Mendapatkan API Key
- Login ke Dashboard IsiKuota
- Buka Pengaturan → API
- Salin
api_id,api_key, dansecret_key
Jangan pernah membagikan api_key dan secret_key kepada siapapun. Simpan di environment variable, bukan di kode.
Cara Membuat Signature
Signature berfungsi seperti tanda tangan digital — membuktikan bahwa request benar-benar dikirim oleh Anda dan isinya tidak diubah di perjalanan.
Ringkasan Alur
1. Ambil parameter request (selain api_id, timestamp, signature)
2. Urutkan nama parameternya dari A ke Z
3. Jadikan JSON string
4. Hitung SHA-256 dari JSON tersebut → body_hash
5. Gabungkan: api_id|api_key|timestamp|body_hash
6. Hitung HMAC-SHA256 dari gabungan tadi → signature
Penjelasan Per Langkah
Langkah 1 — Pisahkan parameter bisnis
Ambil semua parameter kecuali api_id, timestamp, dan signature.
Contoh: Anda ingin order pulsa dengan body:
{
"api_id": "abc123",
"timestamp": 1748678400,
"signature": "...",
"cmd": "prepaid",
"code": "TSEL21",
"customer_no": "08123456789"
}
Parameter bisnisnya adalah:
{
"cmd": "prepaid",
"code": "TSEL21",
"customer_no": "08123456789"
}
Langkah 2 — Urutkan dari A ke Z (ksort)
cmd, code, customer_no ✓ sudah urut
Urutan ini harus sama antara aplikasi Anda dan server IsiKuota. Jika urutannya berbeda, signature akan salah.
Langkah 3 — Jadikan JSON string
{"cmd":"prepaid","code":"TSEL21","customer_no":"08123456789"}
Jika tidak ada parameter bisnis (seperti saat cek saldo), gunakan string kosong
"".
Langkah 4 — Hitung body_hash
body_hash = SHA256( JSON string tadi )
Langkah 5 — Gabungkan dengan tanda |
stringToSign = api_id | api_key | timestamp | body_hash
Contoh:
abc123|key456|1748678400|e3b0c44298fc1c...
Langkah 6 — Hitung signature
signature = HMAC-SHA256( stringToSign, secret_key )
Contoh Kode Lengkap
- PHP
- JavaScript
- Python
- cURL
- Java
- C#
<?php
$api_id = 'your_api_id';
$api_key = 'your_api_key';
$secret_key = 'your_secret_key';
$timestamp = time();
// Parameter bisnis (tanpa api_id, timestamp, signature)
$businessParams = [
'cmd' => 'prepaid',
'code' => 'TSEL21',
'customer_no' => '08123456789',
];
// Urutkan A ke Z
ksort($businessParams);
// Jadikan JSON (kosong jika tidak ada parameter bisnis)
$canonicalBody = empty($businessParams)
? ''
: json_encode($businessParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
// Hitung signature
$bodyHash = hash('sha256', $canonicalBody);
$stringToSign = implode('|', [$api_id, $api_key, $timestamp, $bodyHash]);
$signature = hash_hmac('sha256', $stringToSign, $secret_key);
// Kirim request
$payload = array_merge($businessParams, [
'api_id' => $api_id,
'timestamp' => $timestamp,
'signature' => $signature,
]);
$ch = curl_init('https://api.isikuota.com/v1/order');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const crypto = require('crypto');
const api_id = 'your_api_id';
const api_key = 'your_api_key';
const secret_key = 'your_secret_key';
const timestamp = Math.floor(Date.now() / 1000);
// Parameter bisnis
const businessParams = {
cmd: 'prepaid',
code: 'TSEL21',
customer_no: '08123456789',
};
// Urutkan A ke Z
const sorted = Object.fromEntries(
Object.keys(businessParams).sort().map(k => [k, businessParams[k]])
);
// Jadikan JSON (kosong jika tidak ada parameter bisnis)
const canonicalBody = Object.keys(sorted).length === 0
? ''
: JSON.stringify(sorted);
// Hitung signature
const bodyHash = crypto.createHash('sha256').update(canonicalBody).digest('hex');
const stringToSign = `${api_id}|${api_key}|${timestamp}|${bodyHash}`;
const signature = crypto.createHmac('sha256', secret_key).update(stringToSign).digest('hex');
// Kirim request
const response = await fetch('https://api.isikuota.com/v1/order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...sorted, api_id, timestamp, signature }),
});
const data = await response.json();
import hmac, hashlib, time, json, requests
api_id = 'your_api_id'
api_key = 'your_api_key'
secret_key = 'your_secret_key'
timestamp = int(time.time())
# Parameter bisnis
business_params = {
'cmd': 'prepaid',
'code': 'TSEL21',
'customer_no': '08123456789',
}
# Urutkan A ke Z
sorted_params = dict(sorted(business_params.items()))
# Jadikan JSON (kosong jika tidak ada parameter bisnis)
canonical_body = '' if not sorted_params else json.dumps(
sorted_params, ensure_ascii=False, separators=(',', ':')
)
# Hitung signature
body_hash = hashlib.sha256(canonical_body.encode()).hexdigest()
string_to_sign = f'{api_id}|{api_key}|{timestamp}|{body_hash}'
signature = hmac.new(secret_key.encode(), string_to_sign.encode(), hashlib.sha256).hexdigest()
# Kirim request
payload = {**sorted_params, 'api_id': api_id, 'timestamp': timestamp, 'signature': signature}
response = requests.post('https://api.isikuota.com/v1/order', json=payload)
data = response.json()
API_ID="your_api_id"
API_KEY="your_api_key"
SECRET="your_secret_key"
TIMESTAMP=$(date +%s)
# Parameter bisnis — key wajib urut A ke Z
CANONICAL_BODY='{"cmd":"prepaid","code":"TSEL21","customer_no":"08123456789"}'
# Hitung signature
BODY_HASH=$(echo -n "$CANONICAL_BODY" | sha256sum | awk '{print $1}')
STRING_TO_SIGN="${API_ID}|${API_KEY}|${TIMESTAMP}|${BODY_HASH}"
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
# Kirim request
curl -X POST https://api.isikuota.com/v1/order \
-H "Content-Type: application/json" \
-d "{
\"api_id\": \"$API_ID\",
\"timestamp\": $TIMESTAMP,
\"signature\": \"$SIGNATURE\",
\"cmd\": \"prepaid\",
\"code\": \"TSEL21\",
\"customer_no\": \"08123456789\"
}"
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.Map;
import java.util.TreeMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.http.*;
import java.net.URI;
public class IsiKuotaSignature {
static String sha256(String input) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
return sb.toString();
}
static String hmacSha256(String data, String key) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
return sb.toString();
}
public static void main(String[] args) throws Exception {
String apiId = "your_api_id";
String apiKey = "your_api_key";
String secretKey = "your_secret_key";
long timestamp = Instant.now().getEpochSecond();
// Parameter bisnis — gunakan TreeMap agar otomatis urut A ke Z
TreeMap<String, String> businessParams = new TreeMap<>();
businessParams.put("cmd", "prepaid");
businessParams.put("code", "TSEL21");
businessParams.put("customer_no", "08123456789");
// Jadikan JSON
ObjectMapper mapper = new ObjectMapper();
String canonicalBody = businessParams.isEmpty() ? "" : mapper.writeValueAsString(businessParams);
// Hitung signature
String bodyHash = sha256(canonicalBody);
String stringToSign = apiId + "|" + apiKey + "|" + timestamp + "|" + bodyHash;
String signature = hmacSha256(stringToSign, secretKey);
// Gabungkan payload
Map<String, Object> payload = new java.util.LinkedHashMap<>(businessParams);
payload.put("api_id", apiId);
payload.put("timestamp", timestamp);
payload.put("signature", signature);
// Kirim request
String body = mapper.writeValueAsString(payload);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.isikuota.com/v1/order"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class IsiKuotaSignature
{
static string Sha256(string input)
{
using var sha = SHA256.Create();
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
static string HmacSha256(string data, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
static async Task Main()
{
var apiId = "your_api_id";
var apiKey = "your_api_key";
var secretKey = "your_secret_key";
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
// Parameter bisnis — gunakan SortedDictionary agar otomatis urut A ke Z
var businessParams = new SortedDictionary<string, string>
{
{ "cmd", "prepaid" },
{ "code", "TSEL21" },
{ "customer_no", "08123456789" },
};
// Jadikan JSON (kosong jika tidak ada parameter bisnis)
var canonicalBody = businessParams.Count == 0
? ""
: JsonSerializer.Serialize(businessParams);
// Hitung signature
var bodyHash = Sha256(canonicalBody);
var stringToSign = $"{apiId}|{apiKey}|{timestamp}|{bodyHash}";
var signature = HmacSha256(stringToSign, secretKey);
// Gabungkan payload
var payload = new Dictionary<string, object>(businessParams.Select(x =>
new KeyValuePair<string, object>(x.Key, x.Value)))
{
{ "api_id", apiId },
{ "timestamp", timestamp },
{ "signature", signature },
};
// Kirim request
using var client = new HttpClient();
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.isikuota.com/v1/order", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
Cek Saldo (Tanpa Parameter Bisnis)
Untuk endpoint yang tidak punya parameter tambahan, canonicalBody cukup diisi string kosong:
$bodyHash = hash('sha256', ''); // string kosong
$stringToSign = implode('|', [$api_id, $api_key, $timestamp, $bodyHash]);
$signature = hash_hmac('sha256', $stringToSign, $secret_key);
Signature Salah? Cek Ini
| Error | Penyebab Umum |
|---|---|
INVALID_SIGNATURE | Parameter bisnis tidak diurutkan A–Z, atau secret_key salah |
UNAUTHORIZED | api_id tidak ditemukan |
INVALID_API_KEY | api_key salah |
TIMESTAMP_EXPIRED | Timestamp sudah lewat 5 menit |
- Parameter bisnis sudah diurutkan A ke Z (
ksort) -
api_keyyang dipakai distringToSign, bukanapi_id -
timestampdalam detik, bukan milidetik - JSON tidak ada spasi tambahan (
JSON_UNESCAPED_SLASHES)