Developer API Documentation
Dokumentasi ini menyediakan referensi teknis komprehensif bagi pengembang perangkat lunak untuk mengintegrasikan layanan pengiriman email transaksional dan manajemen akun Xoftware Mail melalui antarmuka HTTP REST API.
1. Pengantar
Seluruh komunikasi dengan API Xoftware Mail harus dilakukan melalui protokol HTTPS guna menjamin keamanan transmisi data. Sistem beroperasi pada arsitektur RESTful murni, menerima payload dan mengembalikan respons dalam format JSON.
- Base URL:
https://mail.xoftware.id - Content-Type:
application/json
Standar Penomoran Halaman (Pagination)
Terdapat struktur standar pagination pada setiap endpoint yang mengembalikan data berbentuk himpunan (array). Klien dapat mengendalikan volume data dengan menggunakan query parameter page dan limit.
{
"data": [ ... ],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"total_pages": 8
}
}
| Properti | Tipe Data | Deskripsi |
|---|---|---|
data |
Array | Himpunan objek sumber daya utama. |
pagination.page |
Integer | Indeks halaman aktif saat ini. |
pagination.limit |
Integer | Batas maksimum objek per halaman. |
pagination.total |
Integer | Total keseluruhan objek yang tersedia di sistem. |
pagination.total_pages |
Integer | Total akumulasi halaman berdasarkan batas yang ditentukan. |
2. Autentikasi
Setiap permintaan yang ditujukan kepada endpoint terproteksi wajib menyertakan token autentikasi yang valid. Akses akan ditolak secara otomatis apabila kredensial tidak disertakan atau tidak dikenali oleh sistem.
Header Global
Header berikut wajib diimplementasikan pada setiap permintaan ke endpoint terproteksi:
| Kunci | Tipe Data | Status | Deskripsi |
|---|---|---|---|
Authorization |
String | Wajib | Format otorisasi standar: Bearer <TOKEN_API> |
Content-Type |
String | Wajib | Nilai statis: application/json |
3. Pengiriman Email (REST API)
Endpoint: POST /api/v1/email/send
Permission Wajib: send_email
Header Khusus
| Kunci | Tipe Data | Status | Deskripsi |
|---|---|---|---|
X-Sandbox |
Integer | Opsional | Nilai 1 akan mengaktifkan mode simulasi. Sistem tidak akan memproses pengiriman fisik maupun mendebit saldo kredit. |
Payload Permintaan (Request Body)
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
from |
String | Wajib | Alamat surel pengirim. Domain yang tercantum wajib berstatus terverifikasi di dalam sistem. |
to |
String | Wajib | Alamat surel tujuan utama. |
subject |
String | Wajib | Judul atau subjek dari surel. |
html_body |
String | Opsional* | Konten surel dalam format HTML. Wajib jika text_body tidak disertakan. |
text_body |
String | Opsional* | Konten surel dalam format teks murni sebagai fallback. Wajib jika html_body tidak disertakan. |
category |
String | Opsional | Label kategorisasi kustom untuk keperluan segmentasi analitik. |
Contoh Payload:
{
"from": "no-reply@domain-terverifikasi.com",
"to": "klien@tujuan.com",
"subject": "Notifikasi Sistem",
"html_body": "<h1>Pesan Berhasil</h1>",
"text_body": "Pesan Berhasil",
"category": "notifikasi-sistem"
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Keterangan status eksekusi. |
message_id |
String | Identitas unik (UUID) yang dialokasikan oleh sistem untuk melacak siklus hidup pesan ini. |
Contoh Respons:
{
"message": "Email berhasil ditambahkan ke antrean pengiriman",
"message_id": "b3d5a1fc-8c2e-4f7a-9d01-abcd12345678"
}
Catatan:
message_iddapat digunakan untuk melacak status pengiriman melalui fitur Webhook. Simpan nilai ini untuk keperluan audit dan rekonsiliasi log pengiriman.
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Payload tidak valid; properti wajib tidak disertakan; format from bukan surel yang valid; html_body dan text_body keduanya kosong. |
400 |
Domain pengirim tidak terdaftar pada akun atau belum berstatus terverifikasi. |
400 |
Alamat tujuan (to) terdaftar di dalam Suppression List akun; pengiriman diblokir. |
401 |
Token API tidak valid atau tidak disertakan pada header Authorization. |
402 |
Saldo kredit akun tidak mencukupi untuk mengeksekusi satu pengiriman. |
403 |
Token API valid, namun tidak memiliki izin send_email. |
500 |
Kegagalan internal pada layanan antrean pesan. |
4. Pengiriman Email (SMTP Relay)
Sebagai alternatif dari HTTP API, sistem mendukung pengiriman melalui protokol SMTP standar. Metode ini direkomendasikan untuk integrasi dengan sistem warisan (legacy), CMS, dll.
Parameter Konfigurasi SMTP
| Parameter | Konfigurasi |
|---|---|
| Host | live.mail.xoftware.id |
| Port (Implicit TLS) | 465 |
| Username | Alamat surel yang terdaftar pada akun Xoftware Mail |
| Password | Token API dengan permission send_email |
| Authentication | Metode LOGIN atau PLAIN |
Ketentuan Keamanan:
- Alamat asal (
From) mutlak harus memiliki status verifikasi domain yang sah di dalam sistem. - Koneksi hanya dapat diinisiasi melalui sesi terenkripsi Implicit TLS/SSL pada Port 465..
5. Analitik & Pelaporan
GET /api/v1/dashboard/stats
Mengambil ringkasan statistik akun secara agregat, mencakup saldo kredit, status domain, serta metrik pengiriman email.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
email_credit |
Integer | Saldo kredit email aktif yang tersedia. |
total_domains |
Integer | Total keseluruhan domain yang terdaftar. |
verified_domains |
Integer | Jumlah domain yang berstatus terverifikasi. |
email_stats.total_sent |
Integer | Akumulasi pesan yang telah berhasil memasuki antrean pengiriman. |
email_stats.total_opened |
Integer | Akumulasi pesan yang terdeteksi dibuka oleh penerima. |
email_stats.total_clicked |
Integer | Akumulasi klik tautan yang terekam di dalam isi pesan. |
email_stats.total_bounced |
Integer | Akumulasi pesan yang gagal terkirim secara permanen (hard bounce). |
Contoh Respons:
{
"email_credit": 950,
"total_domains": 2,
"verified_domains": 1,
"email_stats": {
"total_sent": 500,
"total_opened": 320,
"total_clicked": 85,
"total_bounced": 12
}
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid atau tidak disertakan. |
500 |
Kegagalan pada lapisan basis data saat mengambil agregasi statistik. |
6. Manajemen Domain
GET /api/v1/domains
Mengambil daftar inventaris seluruh domain yang terasosiasi dengan akun.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
data |
Array | Himpunan objek domain. |
data[].id |
Integer | Identitas unik domain. |
data[].domain |
String | Nama domain. |
data[].is_verified |
Boolean | Status verifikasi domain. |
data[].created_at |
String | Waktu pendaftaran domain. |
Contoh Respons:
{
"data": [
{
"id": 1,
"domain": "contoh.com",
"is_verified": true,
"created_at": "2024-01-15T08:00:00Z"
}
]
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
POST /api/v1/domains
Mendaftarkan entitas domain baru ke dalam sistem untuk keperluan pengiriman surel.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
domain |
String | Wajib | Nama domain yang akan didaftarkan. Contoh: contoh.com |
Contoh Payload:
{
"domain": "contoh.com"
}
Format Respons (201 Created)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
id |
Integer | Identitas unik entitas domain. |
domain |
String | Nama domain yang didaftarkan. |
is_verified |
Boolean | Status verifikasi (default: false). |
verify_token |
String | Token unik untuk verifikasi TXT record. |
dkim_public_key |
String | Kunci publik DKIM untuk verifikasi TXT record. |
created_at |
String | Waktu pendaftaran. |
Contoh Respons:
{
"id": 2,
"domain": "contoh.com",
"is_verified": false,
"verify_token": "xoftware-verify-abc123",
"dkim_public_key": "MIIBIjANBgkqhkiG9w0B..."
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti domain tidak disertakan atau format tidak valid. |
400 |
Domain telah terdaftar oleh akun lain di dalam sistem. |
401 |
Token API tidak valid atau tidak disertakan. |
GET /api/v1/domains/:id
Mengambil detail lengkap satu entitas domain beserta instruksi rekaman DNS yang harus dikonfigurasi pada registrar domain.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
domain |
Object | Objek entitas domain. |
domain.id |
Integer | Identitas unik domain. |
domain.domain |
String | Nama domain. |
domain.is_verified |
Boolean | Status verifikasi domain. |
dns_instructions |
Array | Daftar rekaman DNS yang wajib ditambahkan pada registrar. |
dns_instructions[].type |
String | Tipe rekaman DNS (misalnya TXT atau CNAME). |
dns_instructions[].name |
String | Hostname atau nama rekaman. |
dns_instructions[].value |
String | Nilai rekaman yang harus disalin. |
dns_instructions[].reason |
String | Keterangan fungsionalitas rekaman DNS ini. |
Contoh Respons:
{
"domain": {
"id": 1,
"domain": "contoh.com",
"is_verified": false
},
"dns_instructions": [
{
"type": "TXT",
"name": "xoftware-verify.contoh.com",
"value": "xoftware-verify-abc123",
"reason": "Verifikasi Kepemilikan Domain"
}
]
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Parameter :id bukan nilai numerik yang valid. |
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan. |
404 |
Sumber daya tidak ditemukan atau bukan milik akun yang aktif. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
POST /api/v1/domains/:id/verify
Menginisiasi prosedur validasi manual terhadap rekaman DNS kriptografik (DKIM & token verifikasi kepemilikan).
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Keterangan hasil verifikasi. |
is_verified |
Boolean | Status verifikasi domain setelah proses pemeriksaan. |
Contoh Respons:
{
"message": "Domain berhasil diverifikasi",
"is_verified": true
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Rekaman DNS belum dipropagasi atau konfigurasi tidak sesuai. Verifikasi dapat diulang setelah DNS propagation selesai (biasanya 24–48 jam). |
400 |
Domain tidak ditemukan atau bukan milik akun yang aktif. |
401 |
Token API tidak valid atau tidak disertakan. |
DELETE /api/v1/domains/:id
Mencabut hak akses dan menghapus konfigurasi entitas domain secara permanen.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan penghapusan. |
Contoh Respons:
{
"message": "Domain berhasil dihapus"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Domain tidak dapat dihapus karena ID tidak valid. |
400 |
Terdapat entitas aktif (log pengiriman) yang masih berasosiasi dengan domain ini. |
401 |
Token API tidak valid atau tidak disertakan. |
404 |
Domain tidak ditemukan atau bukan milik akun yang aktif. |
GET /api/v1/domains/:id/auto-bcc
Mengambil konfigurasi Auto-BCC aktif untuk domain terkait.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
data |
Object atau null |
Objek data konfigurasi Auto-BCC. Bernilai null apabila belum dikonfigurasi. |
data.email |
String | Alamat surel tujuan penerima duplikat (BCC). |
data.is_active |
Boolean | Status aktif fitur Auto-BCC. |
Contoh Respons:
{
"data": {
"email": "bcc@perusahaan.com",
"is_active": true
}
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Parameter :id bukan nilai numerik yang valid. |
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan. |
404 |
Sumber daya tidak ditemukan atau bukan milik akun yang aktif. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
PUT /api/v1/domains/:id/auto-bcc
Menetapkan atau memperbarui konfigurasi Auto-BCC untuk domain terkait. Setiap surel yang terkirim dari domain ini akan secara otomatis di-BCC ke alamat yang ditentukan.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
email |
String | Wajib | Alamat surel tujuan Auto-BCC. Harus merupakan alamat surel yang valid. |
is_active |
Boolean | Wajib | Status operasional fitur Auto-BCC. |
Contoh Payload:
{
"email": "bcc@perusahaan.com",
"is_active": true
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan penyimpanan konfigurasi. |
data |
Object | Objek konfigurasi Auto-BCC yang telah diperbarui. |
data.email |
String | Alamat surel tujuan penerima duplikat (BCC). |
data.is_active |
Boolean | Status aktif fitur Auto-BCC. |
Contoh Respons:
{
"message": "Pengaturan Auto-BCC berhasil disimpan",
"data": {
"email": "bcc@perusahaan.com",
"is_active": true
}
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti email tidak disertakan atau formatnya bukan surel yang valid. |
400 |
Domain tidak ditemukan atau bukan milik akun yang aktif. |
401 |
Token API tidak valid atau tidak disertakan. |
7. Integrasi Webhook
GET /api/v1/webhooks
Mengambil daftar seluruh konfigurasi webhook aktif beserta daftar peristiwa yang berlangganan.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
data |
Array | Himpunan objek webhook. |
data[].id |
Integer | Identitas unik webhook. |
data[].url |
String | URL tujuan penerima webhook. |
data[].events |
Array of String | Daftar peristiwa sistem yang diawasi. |
data[].is_active |
Boolean | Status aktif webhook. |
Contoh Respons:
{
"data": [
{
"id": 1,
"url": "https://api.aplikasi.com/webhook/email",
"events": ["delivered", "bounced"],
"is_active": true
}
]
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
POST /api/v1/webhooks
Mendaftarkan spesifikasi endpoint webhook baru untuk menerima dorongan data secara waktu nyata atas peristiwa sistem yang terjadi.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
url |
String | Wajib | URL absolut HTTPS yang akan menerima transmisi payload. |
events |
Array of String | Wajib | Daftar identifikasi peristiwa sistem yang diawasi. Nilai valid: delivered, bounced, opened, clicked. |
is_active |
Boolean | Wajib | Indikator status operasional rute webhook ini. |
Contoh Payload:
{
"url": "https://api.aplikasi.com/webhook/email",
"events": ["delivered", "bounced", "opened"],
"is_active": true
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan pendaftaran webhook. |
data |
Object | Objek webhook yang baru dibuat. |
data.id |
Integer | Identitas unik webhook. |
data.url |
String | URL tujuan penerima webhook. |
data.events |
Array of String | Daftar peristiwa sistem yang diawasi. |
data.is_active |
Boolean | Status aktif webhook. |
Contoh Respons:
{
"message": "Webhook berhasil ditambahkan",
"data": {
"id": 3,
"url": "https://api.aplikasi.com/webhook/email",
"events": ["delivered", "bounced", "opened"],
"is_active": true
}
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti url atau events tidak disertakan. |
400 |
Format url bukan URL yang valid atau tidak menggunakan protokol HTTPS. |
400 |
Nilai di dalam array events tidak dikenali oleh sistem. |
401 |
Token API tidak valid atau tidak disertakan. |
DELETE /api/v1/webhooks/:id
Menonaktifkan dan menghapus konfigurasi webhook secara permanen berdasarkan identifikatornya.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan penghapusan. |
Contoh Respons:
{
"message": "Webhook berhasil dihapus"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Parameter :id bukan nilai numerik yang valid. |
401 |
Token API tidak valid atau tidak disertakan. |
404 |
Webhook tidak ditemukan atau bukan milik akun yang aktif. |
500 |
Kegagalan pada lapisan basis data. |
8. Manajemen Daftar Blokir (Suppression)
GET /api/v1/suppressions
Mengambil basis data alamat surel yang masuk dalam status isolasi pengiriman. Mendukung parameter query page dan limit untuk navigasi halaman.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
data |
Array | Himpunan objek entitas suppression. |
data[].id |
Integer | Identitas unik suppression. |
data[].email |
String | Alamat surel yang diblokir. |
data[].reason |
String | Alasan pemblokiran (mis. Hard bounce). |
data[].created_at |
String | Waktu pemblokiran. |
Contoh Respons:
{
"data": [
{
"id": 1,
"email": "spam@domain.com",
"reason": "Hard bounce",
"created_at": "2024-01-01T10:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"total_pages": 1
}
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
POST /api/v1/suppressions
Menambahkan identitas surel secara manual ke dalam daftar blokir guna mencegah alokasi sumber daya pengiriman di masa mendatang.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
email |
String | Wajib | Alamat surel yang akan dimasukkan ke daftar blokir. |
reason |
String | Wajib | Alasan atau keterangan pemblokiran. |
Contoh Payload:
{
"email": "invalid@domain.com",
"reason": "Hard bounce - address does not exist"
}
Format Respons (201 Created)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan pemblokiran. |
data |
Object | Objek entitas suppression yang baru dibuat. |
data.id |
Integer | Identitas unik suppression. |
data.email |
String | Alamat surel yang diblokir. |
data.reason |
String | Alasan pemblokiran (mis. Hard bounce). |
data.created_at |
String | Waktu pemblokiran. |
Contoh Respons:
{
"message": "Email berhasil diblokir",
"data": {
"id": 10,
"email": "invalid@domain.com",
"reason": "Hard bounce - address does not exist",
"created_at": "2024-08-25T15:00:00Z"
}
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti email atau reason tidak disertakan; format email tidak valid. |
401 |
Token API tidak valid atau tidak disertakan. |
500 |
Alamat surel kemungkinan telah terdaftar sebelumnya dalam daftar blokir akun ini. |
DELETE /api/v1/suppressions/:id
Mencabut status blokir dari suatu alamat surel, sehingga alamat tersebut kembali eligible untuk menerima surel dari akun ini.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan pencabutan pemblokiran. |
Contoh Respons:
{
"message": "Email berhasil dihapus dari suppression list"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Parameter :id bukan nilai numerik yang valid. |
401 |
Token API tidak valid atau tidak disertakan. |
500 |
Entitas suppression tidak ditemukan atau kegagalan pada lapisan basis data. |
9. Pengelolaan Akun & Penagihan
GET /api/v1/account/profile
Mengambil informasi identitas lengkap pemilik akun.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
id |
Integer | Identitas unik akun di sistem. |
full_name |
String | Nama lengkap pemilik akun. |
email |
String | Alamat surel yang terdaftar sebagai identitas login. |
whatsapp_number |
String | Nomor WhatsApp yang terdaftar. |
is_verified |
Boolean | Status verifikasi surel akun. |
email_credit |
Integer | Saldo kredit pengiriman surel yang tersedia. |
created_at |
String | Tanggal dan waktu registrasi akun dalam format ISO 8601. |
Contoh Respons:
{
"id": 1,
"full_name": "Budi Santoso",
"email": "budi@perusahaan.com",
"whatsapp_number": "+6281234567890",
"is_verified": true,
"email_credit": 950,
"created_at": "2024-01-01T08:00:00Z"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
PUT /api/v1/account/profile
Memperbarui basis informasi identitas akun.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
full_name |
String | Wajib | Nama lengkap baru pemilik akun. |
whatsapp_number |
String | Wajib | Nomor WhatsApp baru yang akan didaftarkan. |
Contoh Payload:
{
"full_name": "Budi Santoso",
"whatsapp_number": "+6281234567890"
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan pembaruan profil. |
Contoh Respons:
{
"message": "Profile updated successfully"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti full_name atau whatsapp_number tidak disertakan. |
401 |
Token API tidak valid atau tidak disertakan. |
500 |
Kegagalan pada lapisan basis data saat memperbarui data profil. |
GET /api/v1/account/credit
Mengambil metrik penggunaan saldo kredit secara terperinci berdasarkan periode harian dan bulanan.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
email_credit |
Integer | Total saldo kredit yang tersedia saat ini. |
daily_used |
Integer | Jumlah kredit yang telah terpakai pada hari berjalan. |
daily_limit |
Integer | Batas maksimum kredit yang dapat digunakan per hari. |
monthly_quota |
Integer | Kuota total penggunaan per bulan. |
monthly_used |
Integer | Jumlah kredit yang telah terpakai pada bulan berjalan. |
Contoh Respons:
{
"email_credit": 950,
"daily_used": 45,
"daily_limit": 150,
"monthly_quota": 1000,
"monthly_used": 320
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
GET /api/v1/smtp/credentials
Mengambil rincian kredensial autentikasi yang diotorisasi untuk digunakan pada layanan SMTP Relay, termasuk daftar token aktif yang memiliki izin pengiriman.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
host |
String | Hostname server SMTP Relay Xoftware Mail. |
port |
Integer | Nomor port koneksi SMTP. |
encryption |
String | Metode enkripsi yang digunakan. |
username |
String | Nama pengguna untuk autentikasi SMTP (alamat surel akun). |
password_note |
String | Panduan penggunaan token API sebagai kata sandi. |
tokens_with_send_permission |
Array | Daftar token aktif yang memiliki izin send_email. |
tokens_with_send_permission[].name |
String | Nama label token API. |
tokens_with_send_permission[].token_prefix |
String | Prefiks publik token API. |
Contoh Respons:
{
"host": "live.mail.xoftware.id",
"port": 465,
"encryption": "Implicit TLS",
"username": "budi@perusahaan.com",
"password_note": "Gunakan salah satu API Token Anda...",
"tokens_with_send_permission": [
{
"name": "Token Produksi",
"token_prefix": "xm_live_1234"
}
]
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
10. Pengelolaan API Token
GET /api/v1/settings/tokens
Mengambil daftar seluruh token API yang terdaftar pada akun.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
data |
Array | Himpunan objek token. |
data[].id |
Integer | Identitas unik token. |
data[].name |
String | Nama label token. |
data[].permissions |
Array of String | Daftar izin akses. |
data[].token_prefix |
String | Prefiks publik token. |
data[].last_used_at |
String | Waktu pemakaian terakhir. |
Contoh Respons:
{
"data": [
{
"id": 1,
"name": "Token Produksi",
"permissions": ["send_email"],
"token_prefix": "xm_live_abcd",
"last_used_at": "2024-08-25T14:30:00Z"
}
]
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid, kedaluwarsa, atau tidak disertakan pada header Authorization. |
500 |
Kegagalan pada lapisan basis data saat memproses permintaan. |
POST /api/v1/settings/tokens
Membuat token API baru dengan himpunan izin akses yang ditentukan secara eksplisit.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
name |
String | Wajib | Label identifikasi deskriptif untuk token. |
permissions |
Array of String | Wajib | Daftar izin akses yang diberikan. Nilai valid: send_email, stats, domains, suppressions, webhooks, tokens. |
Contoh Payload:
{
"name": "Token Produksi - Pengiriman",
"permissions": ["send_email", "stats"]
}
Format Respons (201 Created)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Pemberitahuan penting bahwa nilai token hanya akan ditampilkan satu kali. |
data.id |
Integer | Identitas unik token. |
data.name |
String | Nama token yang telah didaftarkan. |
data.plain_token |
String | Nilai token lengkap dalam format teks biasa. Simpan segera; tidak dapat diambil kembali. |
data.token_prefix |
String | Prefiks publik token untuk keperluan identifikasi. |
Contoh Respons:
{
"message": "Token berhasil dibuat. Simpan API Token ini baik-baik karena hanya akan ditampilkan sekali.",
"data": {
"id": 5,
"name": "Token Produksi - Pengiriman",
"plain_token": "xm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"token_prefix": "xm_live_xxxx"
}
}
Catatan Keamanan Kritis: Nilai
plain_tokenhanya diekspos satu kali pada respons pembuatan. Sistem menyimpan representasi hash kriptografis token, bukan nilai aslinya. Apabila nilai ini hilang, satu-satunya opsi adalah melakukan reset token melalui endpointPOST /api/v1/settings/tokens/:id/reset.
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti name atau permissions tidak disertakan. |
400 |
Salah satu nilai di dalam array permissions tidak dikenali oleh sistem. |
401 |
Token API tidak valid atau tidak disertakan. |
500 |
Kegagalan internal saat proses generasi token kriptografis. |
PUT /api/v1/settings/tokens/:id
Memperbarui nama label token tanpa mengubah hak aksesnya.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
name |
String | Wajib | Nama baru yang akan diterapkan. |
Contoh Payload:
{
"name": "Token Produksi (Baru)"
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan pembaruan nama token. |
Contoh Respons:
{
"message": "Token berhasil diupdate"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti name tidak disertakan atau kosong. |
401 |
Token API tidak valid atau tidak disertakan. |
404 |
Token tidak ditemukan atau bukan milik akun yang aktif. |
500 |
Kegagalan pada lapisan basis data. |
POST /api/v1/settings/tokens/:id/reset
Meregenerasi nilai token secara kriptografis. Nilai token lama akan diinvalidasi secara permanen.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan regenerasi token. |
data.plain_token |
String | Nilai token baru dalam format teks biasa. Simpan segera; tidak dapat diambil kembali. |
Contoh Respons:
{
"message": "Token berhasil di-reset.",
"data": {
"id": 1,
"plain_token": "xm_live_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
}
}
Catatan Keamanan: Operasi reset akan menginvalidasi token lama secara instan. Perbarui seluruh konfigurasi yang menggunakan token lama segera setelah nilai baru diperoleh.
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid atau tidak disertakan. |
404 |
Token tidak ditemukan atau bukan milik akun yang aktif. |
500 |
Kegagalan internal saat proses regenerasi token kriptografis. |
DELETE /api/v1/settings/tokens/:id
Menginvalidasi dan menghapus token API secara permanen. Seluruh permintaan yang menggunakan token ini akan langsung ditolak setelah eksekusi.
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan penghapusan token. |
Contoh Respons:
{
"message": "Token berhasil dihapus"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
401 |
Token API tidak valid atau tidak disertakan. |
404 |
Token tidak ditemukan atau bukan milik akun yang aktif. |
500 |
Kegagalan pada lapisan basis data. |
POST /api/v1/settings/change-password
Memperbarui kata sandi akun setelah validasi terhadap kata sandi yang aktif saat ini.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
old_password |
String | Wajib | Kata sandi akun yang sedang aktif. |
new_password |
String | Wajib | Kata sandi baru. Minimum 8 karakter. |
Contoh Payload:
{
"old_password": "kataSandiLama123",
"new_password": "kataSandiBaru456"
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi keberhasilan perubahan kata sandi. |
Contoh Respons:
{
"message": "Password berhasil diubah"
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti old_password atau new_password tidak disertakan. |
400 |
Nilai old_password tidak sesuai dengan kata sandi yang aktif di sistem. |
400 |
Nilai new_password kurang dari 8 karakter. |
401 |
Sesi autentikasi tidak valid. |
POST /api/v1/settings/change-email
Memperbarui alamat surel login akun. Surel verifikasi akan dikirimkan ke alamat baru setelah permintaan diproses.
Payload Permintaan
| Properti | Tipe Data | Status | Deskripsi |
|---|---|---|---|
new_email |
String | Wajib | Alamat surel baru yang akan ditetapkan sebagai identitas login. |
Contoh Payload:
{
"new_email": "email.baru@domain.com"
}
Format Respons (200 OK)
| Properti | Tipe Data | Deskripsi |
|---|---|---|
message |
String | Konfirmasi dan instruksi verifikasi alamat surel baru. |
Contoh Respons:
{
"message": "Email berhasil diubah. Silakan verifikasi email baru Anda."
}
Respons Error
| Kode HTTP | Kondisi Pemicu |
|---|---|
400 |
Properti new_email tidak disertakan atau formatnya bukan surel yang valid. |
401 |
Token API tidak valid atau tidak disertakan. |
500 |
Kegagalan pada lapisan basis data saat memperbarui alamat surel. |
Catatan Umum: Seluruh respons error menyertakan properti
errorbertipe String yang berisi keterangan teknis mengenai penyebab kegagalan. Implementasikan penanganan error pada sisi klien berdasarkan kode HTTP, bukan pada nilai stringerror, karena pesan error bersifat informatif dan dapat berubah tanpa pemberitahuan.
11. Indeks Kode Status HTTP
| Kode | Status | Interpretasi |
|---|---|---|
200 |
OK | Instruksi berhasil diotorisasi dan dieksekusi. |
201 |
Created | Sumber daya baru berhasil dialokasikan oleh sistem. |
400 |
Bad Request | Formulasi payload melanggar aturan spesifikasi atau terdapat ketidakcocokan tipe data. |
401 |
Unauthorized | Kredensial tidak valid, tidak ditemukan, atau telah kedaluwarsa. |
402 |
Payment Required | Operasi ditolak karena ketersediaan saldo kredit tidak memenuhi syarat minimum. |
403 |
Forbidden | Autentikasi berhasil, namun token tidak memiliki izin eksplisit untuk mengeksekusi instruksi ini. |
404 |
Not Found | Sumber daya yang dirujuk tidak ditemukan atau tidak menjadi bagian dari entitas akun. |
429 |
Too Many Requests | Identitas terdeteksi melampaui batasan kuota frekuensi permintaan. |
500 |
Internal Server Error | Terjadi eksepsi fatal pada lapisan internal peladen. |