Qirim API
WhatsApp Gateway — OTP · Notifikasi · Chatbot
Base URL: https://qirim.qapuasmedia.tech/api/v1 ⬇ OpenAPI (Postman) Panel Admin →

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": "..."}}
⚠️ Panggil API dari backend, jangan dari aplikasi mobile / JavaScript browser — API key bersifat rahasia.

Autentikasi

Sertakan API key project kamu di setiap request (kecuali /health):

X-Api-Key: qirim_xxxxxxxxxxxxxxxx
# atau
Authorization: Bearer qirim_xxxxxxxxxxxxxxxx

Buat 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 terverifikasi

Minta & kirim OTP

POST /otp/request

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

POST /otp/verify
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

POST /otp/resend

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

POST /notifications/send

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

GET /notifications/{batch_id}
{"success":true,"data":{"batch_id":"7de1...","counts":{"sent":1},
  "messages":[{"to":"628...","status":"sent","evolution_message_id":"3EB0..."}]}}

Kode error

HTTPcodeArti
401unauthenticatedAPI key salah / hilang
403feature_disabledFitur (otp/notif) belum aktif untuk key ini
422invalid_phoneNomor tidak valid
429resend_cooldownTerlalu cepat minta ulang (ada retry_after)
429daily_limitBatas OTP harian per nomor tercapai
422otp_expiredKode kadaluarsa / belum diminta
422otp_incorrectKode salah (ada attempts_remaining)
429too_many_attemptsSalah terlalu sering → minta kode baru
422validation_errorBody tidak valid (ada fields)

Best practice

Qirim · Qapuas Media Technologies