Referensi API
Ambil OTP dan email verifikasi dari alamat sementara, dari server, skrip, atau browser.
- Base URL
https://api.hilmipremindo.online/api/v1- Format
- JSON. Request
POSTmemakai headerContent-Type: application/json. - Autentikasi
X-Api-KeyatauX-Session-Token, hanya untuk endpoint yang bertanda "Butuh auth".- Rate limit
- 120 request per menit per IP. Request dengan
X-Api-Keyjuga dibatasi 500 request per detik per key (nilai bawaan). - Kontak
- Telegram @generatortelebot
Autentikasi
Sebagian besar endpoint bersifat publik: membuat alamat, melihat info alamat, memperpanjang alamat, dan daftar domain. Empat endpoint yang membaca atau mengubah isi pesan membutuhkan auth: list pesan, pesan terbaru, isi pesan, dan hapus pesan.
Sertakan salah satu header berikut:
| Header | Untuk | Masa berlaku | Cara mendapatkan |
|---|---|---|---|
X-Api-Key | Server ke server, skrip, bot | Permanen sampai dicabut | Bot Telegram: Admin > API Key > Generate (hanya ditampilkan sekali) |
X-Session-Token | Browser | 10 menit | GET /session, kedaluwarsa otomatis |
Dari backend atau skrip, gunakan X-Api-Key karena tidak perlu diperbarui. Dari JavaScript di browser, gunakan alur X-Session-Token (lihat contoh di bawah). Tanpa header yang valid, endpoint ini mengembalikan 403:
{ "error": "Akses ditolak - butuh browser resmi atau API key" }Kunci inbox
Kedua header di atas melewati gerbang yang sama, tapi haknya berbeda. Pemilik layanan dapat mengunci alamat penerima tertentu (opsional dibatasi ke pengirim tertentu), dan pesan ke alamat itu isinya tidak dikirim server kepada pemegang X-Session-Token — bukan disembunyikan di tampilan, melainkan memang tidak ikut dalam response. Alamat yang tidak dikunci tetap terbuka seperti biasa.
| Header | Pesan ke alamat terkunci |
|---|---|
X-Api-Key | Isi lengkap, apa adanya |
X-Session-Token | Hanya penanda — subjek, isi, dan OTP tidak ada |
Bentuk yang diterima pemegang session token, di semua endpoint baca:
{ "id": 42, "receivedAt": 1790000000, "locked": true, "lockedSender": "capcut.com" }DELETE pesan terkunci juga ditolak dengan 403 bila hanya memakai session token, supaya pesan yang isinya sengaja ditahan tidak dapat dihancurkan pembaca publik. Aturan dievaluasi saat pesan dibaca, bukan saat masuk — menambah aturan langsung mengunci email lama juga, menghapusnya langsung membuka kembali.
Jangan menaruh X-Api-Key di JavaScript frontend. Isi bundle browser dapat dibaca pengunjung lewat DevTools, sehingga key-nya otomatis bocor dan kuncinya kehilangan arti. Untuk membaca pesan terkunci, gunakan skrip sisi server atau bot Telegram.
Kode status
| Kode | Arti | Penyebab |
|---|---|---|
200 | OK | Request berhasil. |
400 | Bad Request | domain tidak ada di GET /domains saat membuat alamat. |
403 | Forbidden | Endpoint dengan auth dipanggil tanpa X-Api-Key atau X-Session-Token yang valid. |
404 | Not Found | Alamat atau pesan tidak ditemukan, atau sudah kedaluwarsa. |
429 | Too Many Requests | Melewati rate limit. Kurangi frekuensi request. |
Body error selalu berbentuk { "error": "..." }.
Endpoint publik
Ambil session token
GET/session
Untuk browser. Mengembalikan token HMAC berumur 10 menit untuk header X-Session-Token. Dari server ke server, lewati endpoint ini dan gunakan X-Api-Key.
Response
{ "token": "eyJleHAiOjE3ODU2NzQwMDB9.q1w2e3..." }Contoh request
curl https://api.hilmipremindo.online/api/v1/session
import requests
r = requests.get("https://api.hilmipremindo.online/api/v1/session")
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/session");
console.log(await r.json());<?php
echo file_get_contents("https://api.hilmipremindo.online/api/v1/session");Daftar domain
GET/domains
Ambil daftar dari endpoint ini, jangan ditulis permanen di kode: domain dapat bertambah sewaktu-waktu.
Response
{ "domains": ["hilmipremindo.online", "hilmipremindo.com", "aksesresmi.biz.id", "indocuan.web.id"] }Contoh request
curl https://api.hilmipremindo.online/api/v1/domains
import requests
r = requests.get("https://api.hilmipremindo.online/api/v1/domains")
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/domains");
console.log(await r.json());<?php
echo file_get_contents("https://api.hilmipremindo.online/api/v1/domains");Buat atau ambil alamat
POST/addresses
| Field | Wajib | Keterangan |
|---|---|---|
domain | Ya | Harus salah satu dari GET /domains. |
local | Tidak | Local-part kustom (budi menjadi budi@domain). Jika kosong, dibuat acak sepanjang 12 karakter. |
Jika local@domain sudah ada dan belum kedaluwarsa, alamat yang sama dikembalikan, jadi aman dipanggil berulang.
Response
{ "local": "k7m2x9qp3a4d", "domain": "hilmipremindo.online", "createdAt": 1784574688, "expiresAt": 1784575288, "extendedCount": 0 }Contoh request
curl -X POST https://api.hilmipremindo.online/api/v1/addresses \
-H "Content-Type: application/json" \
-d '{"domain":"hilmipremindo.online"}'import requests
r = requests.post(
"https://api.hilmipremindo.online/api/v1/addresses",
json={"domain": "hilmipremindo.online"},
)
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/addresses", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ domain: "hilmipremindo.online" }),
});
console.log(await r.json());<?php
$ch = curl_init("https://api.hilmipremindo.online/api/v1/addresses");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["domain" => "hilmipremindo.online"]),
]);
echo curl_exec($ch);Info alamat
GET/addresses/:local/:domain
Bentuk response sama dengan endpoint buat alamat. Mengembalikan 404 jika alamat tidak ditemukan atau sudah kedaluwarsa.
Contoh request
curl https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online
import requests
r = requests.get("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online")
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online");
console.log(await r.json());<?php
echo file_get_contents("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online");Perpanjang alamat
POST/addresses/:local/:domain/extend
TTL awal alamat baru adalah 10 menit. Setiap perpanjangan menambah 10 menit dari sisa waktu, dengan batas maksimal 1 jam yang dihitung dari saat endpoint dipanggil. Mengembalikan 404 jika alamat sudah kedaluwarsa.
Contoh request
curl -X POST https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/extend
import requests
r = requests.post("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/extend")
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/extend", {
method: "POST",
});
console.log(await r.json());<?php
$ch = curl_init("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/extend");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
]);
echo curl_exec($ch);Endpoint dengan auth
List pesan masuk
GET/addresses/:local/:domain/messagesButuh auth
| Query | Keterangan |
|---|---|
since | Hanya mengembalikan pesan dengan id lebih besar dari nilai ini. Berguna untuk polling tanpa mengambil ulang pesan lama. |
Field otp diekstrak otomatis (kode 4-8 digit atau format XXX-XXX) dan berisi string kosong jika tidak ditemukan. List ini belum memuat isi lengkap (plain, html); gunakan dua endpoint berikutnya untuk itu.
Response
{
"count": 1,
"messages": [
{
"id": 42,
"fromName": "OpenAI",
"fromEmail": "noreply@openai.com",
"subject": "Your verification code",
"otp": "482913",
"receivedAt": 1784574700,
"read": 0
}
]
}Contoh request
curl -H "X-Api-Key: API_KEY_ANDA" \ "https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages?since=42"
import requests
r = requests.get(
"https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages?since=42",
headers={"X-Api-Key": "API_KEY_ANDA"},
)
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages?since=42", {
headers: { "X-Api-Key": "API_KEY_ANDA" },
});
console.log(await r.json());<?php
$ch = curl_init("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages?since=42");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-Api-Key: API_KEY_ANDA"],
]);
echo curl_exec($ch);Pesan terbaru dengan isi lengkap
GET/addresses/:local/:domain/messages/latestButuh auth
Menggabungkan list dan isi lengkap dalam satu panggilan: mengembalikan pesan terbaru beserta plain, html, dan otp, tanpa perlu memanggil list lalu GET /messages/:id. Diurutkan berdasarkan waktu masuk, bukan berdasarkan ada tidaknya OTP. Jika email terbaru hanya berisi tautan, otp tetap kosong.
Mengembalikan 404 jika alamat tidak ditemukan atau belum ada pesan masuk sama sekali.
Response
{
"id": 42,
"fromName": "OpenAI",
"fromEmail": "noreply@openai.com",
"subject": "Your verification code",
"plain": "Your code is 482913",
"html": "<p>Your code is <b>482913</b></p>",
"otp": "482913",
"receivedAt": 1784574700
}Contoh request
curl -H "X-Api-Key: API_KEY_ANDA" \ "https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/latest"
import requests
r = requests.get(
"https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/latest",
headers={"X-Api-Key": "API_KEY_ANDA"},
)
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/latest", {
headers: { "X-Api-Key": "API_KEY_ANDA" },
});
console.log(await r.json());<?php
$ch = curl_init("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/latest");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-Api-Key: API_KEY_ANDA"],
]);
echo curl_exec($ch);Isi lengkap satu pesan
GET/messages/:idButuh auth
:id berasal dari field id pada response list. Memanggil endpoint ini menandai pesan sebagai read.
Response
{
"id": 42,
"fromName": "OpenAI",
"fromEmail": "noreply@openai.com",
"subject": "Your verification code",
"plain": "Your code is 482913",
"html": "<p>Your code is <b>482913</b></p>",
"otp": "482913",
"receivedAt": 1784574700
}Contoh request
curl -H "X-Api-Key: API_KEY_ANDA" \ https://api.hilmipremindo.online/api/v1/messages/42
import requests
r = requests.get(
"https://api.hilmipremindo.online/api/v1/messages/42",
headers={"X-Api-Key": "API_KEY_ANDA"},
)
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/messages/42", {
headers: { "X-Api-Key": "API_KEY_ANDA" },
});
console.log(await r.json());<?php
$ch = curl_init("https://api.hilmipremindo.online/api/v1/messages/42");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-Api-Key: API_KEY_ANDA"],
]);
echo curl_exec($ch);Hapus satu pesan
DELETE/addresses/:local/:domain/messages/:idButuh auth
Penghapusan bersifat permanen: langsung terhapus tanpa tempat sampah dan tidak dapat dibatalkan. Endpoint ini di-scope ke :local/:domain (bukan DELETE /messages/:id) karena id pesan berupa integer berurutan yang mudah ditebak. Server memeriksa bahwa pesan itu memang milik alamat pada URL sebelum menghapusnya.
Mengembalikan 404 jika alamat atau pesan tidak ditemukan, atau pesan itu bukan milik alamat tersebut. Sengaja 404 dan bukan 403, agar tidak membocorkan bahwa pesan itu ada tetapi milik alamat lain.
Response
{ "ok": true }Contoh request
curl -X DELETE -H "X-Api-Key: API_KEY_ANDA" \ "https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/42"
import requests
r = requests.delete(
"https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/42",
headers={"X-Api-Key": "API_KEY_ANDA"},
)
print(r.json())// Node 18+; simpan sebagai .mjs karena memakai top-level await
const r = await fetch("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/42", {
method: "DELETE",
headers: { "X-Api-Key": "API_KEY_ANDA" },
});
console.log(await r.json());<?php
$ch = curl_init("https://api.hilmipremindo.online/api/v1/addresses/k7m2x9qp3a4d/hilmipremindo.online/messages/42");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => ["X-Api-Key: API_KEY_ANDA"],
]);
echo curl_exec($ch);Contoh
Ambil OTP: buat alamat, lalu polling
Semua contoh memakai API key (server ke server). Ganti API_KEY_ANDA dengan key dari bot.
#!/usr/bin/env bash
BASE="https://api.hilmipremindo.online/api/v1"
KEY="API_KEY_ANDA"
# 1. buat alamat
RESP=$(curl -s -X POST "$BASE/addresses" \
-H "Content-Type: application/json" -d '{"domain":"hilmipremindo.online"}')
LOCAL=$(echo "$RESP" | grep -o '"local":"[^"]*"' | cut -d'"' -f4)
echo "alamat: $LOCAL@hilmipremindo.online"
# 2. gunakan alamat itu untuk mendaftar di layanan lain, lalu polling OTP:
for i in $(seq 1 30); do
MSGS=$(curl -s -H "X-Api-Key: $KEY" \
"$BASE/addresses/$LOCAL/hilmipremindo.online/messages")
OTP=$(echo "$MSGS" | grep -o '"otp":"[0-9][^"]*"' | head -1 | cut -d'"' -f4)
if [ -n "$OTP" ]; then echo "OTP: $OTP"; break; fi
sleep 3
doneMembutuhkan: pip install requests
import time
import requests
BASE = "https://api.hilmipremindo.online/api/v1"
KEY = "API_KEY_ANDA"
HEADERS = {"X-Api-Key": KEY}
def generate(domain="hilmipremindo.online", local=None):
body = {"domain": domain}
if local:
body["local"] = local
r = requests.post(f"{BASE}/addresses", json=body)
r.raise_for_status()
return r.json()
def wait_for_otp(local, domain, timeout=120, interval=3):
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.get(
f"{BASE}/addresses/{local}/{domain}/messages",
headers=HEADERS,
)
r.raise_for_status()
for msg in r.json()["messages"]:
if msg["otp"]:
return msg["otp"]
time.sleep(interval)
return None
addr = generate()
print("alamat:", f'{addr["local"]}@{addr["domain"]}')
# ... gunakan alamat itu untuk mendaftar di layanan lain ...
otp = wait_for_otp(addr["local"], addr["domain"])
print("OTP:", otp)Membutuhkan Node 18 atau lebih baru (memakai fetch bawaan, tanpa dependensi).
const BASE = "https://api.hilmipremindo.online/api/v1";
const KEY = "API_KEY_ANDA";
const HEADERS = { "X-Api-Key": KEY };
async function generate(domain = "hilmipremindo.online", local) {
const body = local ? { domain, local } : { domain };
const r = await fetch(`${BASE}/addresses`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
}
async function waitForOtp(local, domain, timeoutMs = 120000, intervalMs = 3000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const r = await fetch(
`${BASE}/addresses/${local}/${domain}/messages`,
{ headers: HEADERS }
);
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const { messages } = await r.json();
const hit = messages.find((m) => m.otp);
if (hit) return hit.otp;
await new Promise((res) => setTimeout(res, intervalMs));
}
return null;
}
(async () => {
const addr = await generate();
console.log("alamat:", `${addr.local}@${addr.domain}`);
// ... gunakan alamat itu untuk mendaftar di layanan lain ...
const otp = await waitForOtp(addr.local, addr.domain);
console.log("OTP:", otp);
})();Membutuhkan ext-curl (tersedia di sebagian besar instalasi PHP).
<?php
$BASE = "https://api.hilmipremindo.online/api/v1";
$KEY = "API_KEY_ANDA";
function req($method, $url, $body = null, $key = null) {
$ch = curl_init($url);
$headers = ["Content-Type: application/json"];
if ($key) $headers[] = "X-Api-Key: $key";
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
]);
if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$resp = curl_exec($ch);
curl_close($ch);
return json_decode($resp, true);
}
// 1. buat alamat
$addr = req("POST", "$BASE/addresses", ["domain" => "hilmipremindo.online"]);
$local = $addr["local"];
$domain = $addr["domain"];
echo "alamat: $local@$domain\n";
// 2. polling OTP
$otp = null;
for ($i = 0; $i < 40; $i++) {
$msgs = req("GET", "$BASE/addresses/$local/$domain/messages", null, $KEY);
foreach ($msgs["messages"] as $m) {
if (!empty($m["otp"])) { $otp = $m["otp"]; break 2; }
}
sleep(3);
}
echo "OTP: $otp\n";Session token di browser
Di browser, ganti X-Api-Key dengan alur mengambil /session lebih dulu, lalu mengulang sekali jika menerima 403:
const BASE = "https://api.hilmipremindo.online/api/v1";
let token = null;
async function ensureToken() {
const r = await fetch(`${BASE}/session`);
token = (await r.json()).token;
}
async function listMessages(local, domain) {
let r = await fetch(`${BASE}/addresses/${local}/${domain}/messages`, {
headers: token ? { "X-Session-Token": token } : {},
});
if (r.status === 403) { // token kedaluwarsa atau belum ada: ambil baru, ulangi sekali
await ensureToken();
r = await fetch(`${BASE}/addresses/${local}/${domain}/messages`, {
headers: { "X-Session-Token": token },
});
}
return r.json();
}Memanggil dari browser di origin lain terkena CORS: tambahkan origin tersebut ke ALLOWED_ORIGIN di .env server terlebih dahulu.
Catatan
- Alamat tidak dapat dihapus manual. Alamat kedaluwarsa otomatis lewat TTL dan dibersihkan oleh job latar belakang. Pesan dapat dihapus satu per satu lewat
DELETE(lihat Hapus satu pesan), atau hilang otomatis saat alamatnya dibersihkan. - Endpoint lain di codebase (
/tenant-config,/webhooks/*, ingest) bersifat internal dan tidak untuk dipanggil dari luar. - API key dapat dicabut kapan saja lewat bot (Admin > API Key > Cabut). Setelah dicabut, request dengan key itu langsung mendapat
403.
Riwayat perubahan
- Menambah
DELETE /addresses/:local/:domain/messages/:id: menghapus satu email secara permanen, butuh auth, di-scope ke alamat (bukanDELETE /messages/:id) agar pesan alamat lain tidak dapat dihapus paksa. - Menambah
GET /addresses/:local/:domain/messages/latest: pesan terbaru dengan isi lengkap dalam satu panggilan (gabungan list danGET /messages/:id). GET /addresses/:local/:domain/messagesdanGET /messages/:idkini butuh auth (X-Api-KeyatauX-Session-Token). MenambahGET /session.- Local-part acak dinaikkan menjadi 12 karakter (sebelumnya 5) agar ruang kemungkinannya jauh lebih besar dan sulit ditebak.
- Rilis awal: membuat alamat, daftar domain, perpanjang, membaca pesan dan OTP.