Skip to main content

04 — API: Membership & Billing

Endpoint untuk subscription plans, pembayaran, dan manajemen keanggotaan.


Subscription Plans​

GET /membership/plans​

Ambil semua paket berlangganan yang tersedia.

Access: Public

// Response 200
{
"success": true,
"data": [
{
"id": "plan_monthly",
"name": "Monthly",
"nameId": "Bulanan",
"description": "Akses penuh selama 1 bulan",
"period": "monthly",
"priceIdr": 99000,
"originalPriceIdr": null,
"priceFormatted": "Rp 99.000",
"pricePerDay": "Rp 3.300/hari",
"isPopular": true,
"features": {
"unlimitedAssessment": true,
"unlimitedPractice": true,
"personalBlueprint": true,
"dailyMissions": true,
"progressTracking": true,
"prioritySupport": false
},
"featureList": [
"Assessment tanpa batas",
"Latihan speaking tanpa batas",
"Blueprint belajar personal",
"Misi harian yang adaptif",
"Tracking progress lengkap"
]
},
{
"id": "plan_yearly",
"name": "Yearly",
"nameId": "Tahunan",
"description": "Akses penuh selama 1 tahun — hemat 33%!",
"period": "yearly",
"priceIdr": 799000,
"originalPriceIdr": 1188000,
"priceFormatted": "Rp 799.000",
"pricePerDay": "Rp 2.189/hari",
"savingsPercent": 33,
"isPopular": false,
"features": {
"unlimitedAssessment": true,
"unlimitedPractice": true,
"personalBlueprint": true,
"dailyMissions": true,
"progressTracking": true,
"prioritySupport": true
},
"featureList": [
"Semua fitur Monthly",
"Priority support",
"Hemat 33% dibanding bulanan"
]
}
]
}

Subscribe & Payment​

POST /membership/subscribe​

Mulai proses berlangganan — buat order dan redirect ke payment gateway.

Access: Authenticated

// Request Body
{
"planId": "plan_monthly",
"paymentMethod": "gopay" // Opsional: pre-select method
}

// Response 201
{
"success": true,
"data": {
"orderId": "ord_V1StGXR8_Z5j",
"planId": "plan_monthly",
"amount": 99000,
"currency": "IDR",
"status": "pending",

// Midtrans Snap redirect
"payment": {
"redirectUrl": "https://app.midtrans.com/snap/v4/...",
"token": "snap_token_xxx",
"expiresAt": "2026-09-20T16:30:00Z"
}
}
}

POST /membership/webhook/midtrans​

Webhook dari Midtrans saat pembayaran berhasil/gagal.

Access: Midtrans Server (diverifikasi via signature)

// Request Body (dari Midtrans)
{
"transaction_status": "settlement",
"order_id": "ord_V1StGXR8_Z5j",
"gross_amount": "99000.00",
"payment_type": "gopay",
"transaction_id": "midtrans_txn_xxx",
"signature_key": "xxx"
}

// Response 200 (acknowledgment ke Midtrans)
{
"status": "ok"
}

Proses di Backend setelah webhook:

  1. Verifikasi signature dari Midtrans
  2. Update status payment → paid
  3. Buat/extend subscription → active
  4. Update user tier → member
  5. Kirim email konfirmasi
  6. Log ke audit_logs

Subscription Management​

GET /membership/subscription​

Ambil status subscription user saat ini.

Access: Authenticated

// Response 200 (Active member)
{
"success": true,
"data": {
"id": "sub_V1StGXR8_Z5j",
"plan": {
"id": "plan_monthly",
"name": "Monthly",
"period": "monthly"
},
"status": "active",
"startsAt": "2026-09-01T00:00:00Z",
"expiresAt": "2026-10-01T00:00:00Z",
"daysRemaining": 11,
"autoRenew": true,
"nextBillingDate": "2026-10-01T00:00:00Z",
"nextBillingAmount": 99000
}
}

// Response 200 (Free user / no subscription)
{
"success": true,
"data": null
}

POST /membership/subscription/cancel​

Batalkan subscription (tidak langsung berhenti, tetap aktif sampai expired).

Access: Authenticated

// Request Body
{
"reason": "too_expensive", // Opsional
"feedback": "Saat ini budget saya terbatas" // Opsional
}

// Response 200
{
"success": true,
"data": {
"id": "sub_V1StGXR8_Z5j",
"status": "cancelled",
"activeUntil": "2026-10-01T00:00:00Z",
"message": "Subscription berhasil dibatalkan. Kamu masih bisa menggunakan fitur Member sampai 1 Oktober 2026."
}
}

POST /membership/subscription/reactivate​

Aktifkan kembali subscription yang sudah di-cancel (sebelum expired).

Access: Authenticated

// Response 200
{
"success": true,
"data": {
"id": "sub_V1StGXR8_Z5j",
"status": "active",
"autoRenew": true,
"message": "Subscription berhasil diaktifkan kembali!"
}
}

Payment History​

GET /membership/payments​

Ambil riwayat pembayaran user.

Access: Authenticated

// Response 200
{
"success": true,
"data": [
{
"id": "pay_abc123",
"amount": 99000,
"currency": "IDR",
"amountFormatted": "Rp 99.000",
"status": "paid",
"paymentMethod": "gopay",
"planName": "Monthly",
"paidAt": "2026-09-01T10:00:00Z",
"invoiceUrl": "https://api.eljoy.id/api/v1/membership/invoices/pay_abc123"
},
{
"id": "pay_def456",
"amount": 99000,
"currency": "IDR",
"amountFormatted": "Rp 99.000",
"status": "paid",
"paymentMethod": "bca_va",
"planName": "Monthly",
"paidAt": "2026-08-01T09:30:00Z",
"invoiceUrl": "https://api.eljoy.id/api/v1/membership/invoices/pay_def456"
}
],
"pagination": { ... }
}

GET /membership/invoices/:paymentId​

Download invoice PDF.

Access: Authenticated

Response: application/pdf
Content-Disposition: attachment; filename="invoice-ELJ-20260901.pdf"

Access Control​

GET /membership/access​

Cek apakah user boleh mengakses fitur tertentu.

Access: Authenticated

// Query: ?feature=unlimited_practice

// Response 200
{
"success": true,
"data": {
"feature": "unlimited_practice",
"hasAccess": false,
"reason": "free_tier",
"upgradeUrl": "/membership/plans",
"message": "Upgrade ke Member untuk latihan speaking tanpa batas!"
}
}

Feature list yang bisa dicek:

FeatureFreeMember
ice_breaker_assessment✅ (1x)✅ Unlimited
universal_assessment✅ (1x)✅ Unlimited
adaptive_assessment❌✅
unlimited_practice❌✅
personal_blueprint❌✅
daily_missions❌✅
progress_tracking❌✅
conversation_history❌✅