Dokumentasi API Qirim
Qirim membungkus WhatsApp jadi REST API sederhana untuk semua project kamu: OTP, notifikasi, dan chatbot. Semua endpoint diawali https://qirim.qapuasmedia.tech/api/v1 dan mengembalikan JSON dengan bentuk seragam:
// sukses
{"success": true, "data": { ... }}
// gagal
{"success": false, "error": {"code": "...", "message": "..."}}Autentikasi
Sertakan API key project kamu di setiap request (kecuali /health):
X-Api-Key: qirim_xxxxxxxxxxxxxxxx
# atau
Authorization: Bearer qirim_xxxxxxxxxxxxxxxxBuat API key baru lewat panel App / API Key → Buat App, atau perintah php artisan qirim:create-app "Nama" --features=otp,notif. Key hanya tampil sekali.
Alur OTP
User isi no. HP ─▶ backend ─POST /otp/request─▶ Qirim ─WhatsApp─▶ kode ke HP
User isi kode ─▶ backend ─POST /otp/verify──▶ Qirim ─▶ verified:true
└▶ backend kamu: buat sesi / tandai terverifikasiMinta & kirim OTP
Body: phone (wajib), purpose, code_length (4–8), ttl (30–1800 dtk). Nomor boleh 08…, +62…, atau 62… — otomatis dinormalkan.
curl -X POST https://qirim.qapuasmedia.tech/api/v1/otp/request \
-H "X-Api-Key: qirim_xxxx" -H "Content-Type: application/json" \
-d '{"phone":"08123456789","purpose":"login"}'Respons 201 — kode tidak pernah dikembalikan (dikirim via WA):
{"success":true,"data":{
"request_id":"e683e653-7e51-4635-bee5-9298ad5578be",
"phone":"628123456789","expires_in":300,
"expires_at":"2026-06-26T10:31:01+00:00"}}Verifikasi kode
curl -X POST https://qirim.qapuasmedia.tech/api/v1/otp/verify \
-H "X-Api-Key: qirim_xxxx" -H "Content-Type: application/json" \
-d '{"phone":"08123456789","code":"123456"}'{"success":true,"data":{"verified":true,"phone":"628123456789"}}Kirim ulang
Sama seperti /otp/request; kena cooldown kalau terlalu cepat (default 60 dtk, lihat retry_after).
Contoh kode backend
PHP / Laravel
use Illuminate\Support\Facades\Http;
$qirim = Http::baseUrl('https://qirim.qapuasmedia.tech/api/v1')
->withHeaders(['X-Api-Key' => env('QIRIM_KEY')])->acceptJson();
// kirim OTP
$res = $qirim->post('/otp/request', ['phone' => $phone, 'purpose' => 'login'])->json();
// verifikasi
$res = $qirim->post('/otp/verify', ['phone' => $phone, 'code' => $code])->json();
if (data_get($res, 'data.verified')) {
// ✅ terverifikasi — buat sesi / login user kamu di sini
}Node.js
const QIRIM = "https://qirim.qapuasmedia.tech/api/v1";
const H = { "X-Api-Key": process.env.QIRIM_KEY, "Content-Type": "application/json" };
const requestOtp = (phone) => fetch(`${QIRIM}/otp/request`,
{ method:"POST", headers:H, body:JSON.stringify({ phone, purpose:"login" }) }).then(r=>r.json());
const verifyOtp = (phone, code) => fetch(`${QIRIM}/otp/verify`,
{ method:"POST", headers:H, body:JSON.stringify({ phone, code }) }).then(r=>r.json());Notifikasi — Kirim pesan
to boleh string atau array. type: text / media / template. Pengiriman async (antrian + retry).
# text
{"to":"08123456789","type":"text","text":"Halo 👋"}
# media
{"to":"0812...","type":"media","media_url":"https://...jpg","mediatype":"image","caption":"Promo"}
# template (pakai template tersimpan)
{"to":["0812...","0813..."],"type":"template","template":"invoice",
"vars":{"no":"INV-1","total":"Rp10.000"}}{"success":true,"data":{"batch_id":"7de1...","accepted":1,"queued":1,"rejected":0}}Notifikasi — Cek status
{"success":true,"data":{"batch_id":"7de1...","counts":{"sent":1},
"messages":[{"to":"628...","status":"sent","evolution_message_id":"3EB0..."}]}}Kode error
| HTTP | code | Arti |
|---|---|---|
| 401 | unauthenticated | API key salah / hilang |
| 403 | feature_disabled | Fitur (otp/notif) belum aktif untuk key ini |
| 422 | invalid_phone | Nomor tidak valid |
| 429 | resend_cooldown | Terlalu cepat minta ulang (ada retry_after) |
| 429 | daily_limit | Batas OTP harian per nomor tercapai |
| 422 | otp_expired | Kode kadaluarsa / belum diminta |
| 422 | otp_incorrect | Kode salah (ada attempts_remaining) |
| 429 | too_many_attempts | Salah terlalu sering → minta kode baru |
| 422 | validation_error | Body tidak valid (ada fields) |
Best practice
- 🔒 Simpan API key sebagai ENV di backend. Jangan pernah expose ke frontend/mobile.
- Nomor tujuan harus nomor WhatsApp aktif.
verified:true= kode cocok. Logika sesi/login tetap di aplikasimu.- Guard bawaan (cooldown, max attempt, cap harian) sudah aktif — tetap batasi tombol "kirim ulang" di UI.
- Kustomisasi template/ttl/rate-limit per app lewat panel App / API Key → Ubah (kolom rate_limit). Token:
{code},{minutes},{app}.
Qirim · Qapuas Media Technologies