# SMS Gateway

> Kirim SMS ke nomor Indonesia lewat API: SMS OTP atau SMS reguler, dibayar dengan kredit SMS.

Kirim SMS ke nomor seluler Indonesia lewat satu endpoint. Jenis pesan: SMS OTP (bawaan) dan SMS reguler (`type: "sender"`). Setiap pesan memotong kredit SMS sesuai jenisnya; jumlah kredit per pesan dan harga kredit dalam coin diatur admin dan bisa dilihat lewat GET /types dan GET /balance. Kredit SMS dibeli dengan coin di menu Saldo, dan kredit dikembalikan otomatis bila pengiriman gagal di provider. Agar tingkat keberhasilan tinggi, hindari kata seperti token, OTP, kode, verifikasi, validasi, atau registrasi di isi pesan.

- Base URL: `https://api.apipedia.id/v1/sms`
- Autentikasi: `Authorization: Bearer apk_…` (token dari console.apipedia.id)
- Kategori: Messaging
- Halaman: https://apipedia.id/docs/sms-gateway
- OpenAPI: https://console.apipedia.id/openapi/sms-gateway.yaml

Semua respons memakai amplop `{ "is_success", "message", "data" }` kecuali disebutkan lain. Kode error umum: lihat https://apipedia.id/docs#kode-status-error.

## Endpoint (4)

- `GET /balance`: Saldo kredit SMS
- `GET /messages`: Riwayat SMS terkirim
- `POST /send`: Kirim SMS
- `GET /types`: Jenis pesan SMS yang aktif

### Saldo kredit SMS

`GET https://api.apipedia.id/v1/sms/balance`

Sisa kredit SMS pemanggil dan kredit per jenis pesan yang aktif. Kredit SMS dibeli dengan coin lewat POST /credits/buy (atau menu Saldo di console).

Contoh request:

```bash
curl -X GET "https://api.apipedia.id/v1/sms/balance" \
  -H "Authorization: Bearer apk_xxxxxxxxxxxxxxxx"
```

Contoh respons (200):

```json
{
  "is_success": true,
  "message": "Saldo kredit SMS berhasil diambil",
  "data": {
    "balance": 955,
    "creditsPerType": {
      "otp": 45,
      "sender": 30
    }
  }
}
```

### Riwayat SMS terkirim

`GET https://api.apipedia.id/v1/sms/messages`

50 SMS terbaru milik pemanggil, terbaru dulu. `status` bernilai `sent` atau `failed` (kredit pesan yang gagal sudah dikembalikan).

Contoh request:

```bash
curl -X GET "https://api.apipedia.id/v1/sms/messages" \
  -H "Authorization: Bearer apk_xxxxxxxxxxxxxxxx"
```

Contoh respons (200):

```json
{
  "is_success": true,
  "message": "Riwayat SMS berhasil diambil",
  "data": {
    "items": [
      {
        "id": "6b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
        "type": "otp",
        "to": "081234567890",
        "message": "Angka masuk kamu 482913. Berlaku 5 menit, jangan bagikan ke siapa pun.",
        "credits": 45,
        "status": "sent",
        "error": null,
        "created_at": "2026-10-29T03:15:00Z"
      }
    ]
  }
}
```

### Kirim SMS

`POST https://api.apipedia.id/v1/sms/send`

Mengirim satu SMS ke nomor seluler Indonesia dan memotong kredit SMS sesuai jenis pesannya (lihat GET /sms/types). Bisa dipanggil dengan API key `apk_...` (cakupan produk `sms-gateway`) atau JWT console.

Body: `to` wajib, nomor Indonesia `08...`, `628...`, atau `+628...` (dinormalkan ke awalan `0`); `message` wajib, 1-480 karakter; `type` opsional, salah satu jenis yang aktif (bawaan `otp`): `otp` = SMS OTP (45 kredit/pesan), `sender` = SMS reguler (30 kredit/pesan). Harga per jenis diatur admin; nilai terkini ada di GET /sms/types.

Kredit dipotong SEBELUM pesan diteruskan ke provider. Bila provider menolak atau tidak menjawab (timeout 20 detik), kredit dikembalikan otomatis (refund) dan respons 502. `balance` di respons adalah sisa kredit SMS setelah pengiriman.

Tips agar tingkat keberhasilan tinggi (anjuran WebSMS): hindari kata Token, OTP, Kode, Verifikasi, Validasi, Registrasi (dan padanan Inggrisnya: code, verification, validation, registration) di isi pesan. Contoh yang aman: "Angka masuk kamu 482913. Berlaku 5 menit, jangan bagikan ke siapa pun."

Error: 400 nomor/isi/jenis tidak valid; 402 "Kredit SMS tidak cukup. Beli kredit di menu Saldo." (beli kredit dengan coin lewat POST /credits/buy); 502 provider gagal (kredit sudah dikembalikan); 503 "SMS gateway belum dikonfigurasi."

Body (`application/json`, wajib):

```json
{
  "to": "081234567890",
  "message": "Angka masuk kamu 482913. Berlaku 5 menit, jangan bagikan ke siapa pun.",
  "type": "otp"
}
```

Contoh request:

```bash
curl -X POST "https://api.apipedia.id/v1/sms/send" \
  -H "Authorization: Bearer apk_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"to":"081234567890","message":"Angka masuk kamu 482913. Berlaku 5 menit, jangan bagikan ke siapa pun.","type":"otp"}'
```

Contoh respons (200):

```json
{
  "is_success": true,
  "message": "SMS terkirim",
  "data": {
    "id": "6b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
    "type": "otp",
    "to": "081234567890",
    "credits": 45,
    "status": "sent",
    "balance": 955
  }
}
```

Error khusus endpoint ini:

- **402**: Kredit SMS tidak cukup untuk jenis pesan ini (`Kredit SMS tidak cukup. Beli kredit di menu Saldo.`)
- **503**: Admin belum mengisi kredensial provider SMS (`SMS gateway belum dikonfigurasi.`)

### Jenis pesan SMS yang aktif

`GET https://api.apipedia.id/v1/sms/types`

Jenis pesan yang boleh dipakai di field `type` POST /sms/send beserta jumlah kredit SMS yang terpotong per pesan. Hanya jenis yang diaktifkan admin yang muncul (bawaan: `otp` SMS OTP 45 kredit dan `sender` SMS reguler 30 kredit).

Contoh request:

```bash
curl -X GET "https://api.apipedia.id/v1/sms/types" \
  -H "Authorization: Bearer apk_xxxxxxxxxxxxxxxx"
```

Contoh respons (200):

```json
{
  "is_success": true,
  "message": "Jenis SMS berhasil diambil",
  "data": {
    "items": [
      {
        "id": "otp",
        "label": "SMS OTP",
        "credits": 45
      },
      {
        "id": "sender",
        "label": "SMS Reguler",
        "credits": 30
      }
    ]
  }
}
```
