REST API Reference¶
All endpoints are prefixed with wherever you mount the subscription URLs (e.g., /api/subscriptions/).
Authentication¶
Most endpoints require authentication via session or basic auth. The webhook endpoint is unauthenticated.
Plans¶
GET /plans/¶
List all active plans. Public (no auth required).
Query Parameters:
status— Filter by status (active,inactive,archived)interval_unit— Filter by interval (day,week,month)currency— Filter by currency codesearch— Search in name and descriptionordering— Order byprice,sort_order,created_at
Response:
{
"count": 3,
"results": [
{
"id": "uuid",
"name": "Basic",
"slug": "basic",
"description": "Basic plan",
"price": "49000.00",
"currency": "IDR",
"interval": 1,
"interval_unit": "month",
"trial_period_days": 7,
"max_cycles": 0,
"status": "active",
"features": {"max_projects": 5},
"sort_order": 0
}
]
}
GET /plans/{slug}/¶
Retrieve a single plan by slug. Public.
Subscriptions¶
GET /subscriptions/¶
List the current user’s subscriptions.
Query Parameters:
status— Filter by statuspayment_type— Filter by payment typeordering— Order bycreated_at,next_billing_date
GET /subscriptions/{id}/¶
Retrieve subscription details.
POST /subscriptions/¶
Create a new subscription.
Request Body:
{
"plan_id": "plan-uuid-or-slug",
"payment_type": "bank_transfer",
"token": "",
"customer_details": {
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "08123456789"
},
"metadata": {"bank": "bca"}
}
Response (201):
{
"subscription": { "id": "uuid", "status": "pending", "...": "..." },
"payment": {
"order_id": "SUB-A1B2C3D4E5F6",
"status": "pending",
"payment_details": {
"bank": "bca",
"va_number": "1234567890"
}
}
}
POST /subscriptions/{id}/cancel/¶
Cancel a subscription.
{
"reason": "Too expensive",
"immediate": false
}
POST /subscriptions/{id}/pause/¶
Pause an active subscription (no request body).
POST /subscriptions/{id}/resume/¶
Resume a paused subscription (no request body).
POST /subscriptions/{id}/change-plan/¶
Change subscription plan.
{
"plan_id": "new-plan-uuid-or-slug",
"immediate": true
}
GET /subscriptions/{id}/sync/¶
Sync subscription status from Midtrans API.
GET /subscriptions/active/¶
Get the current user’s active subscription. Returns 404 if none found.
Payments¶
GET /payments/¶
List the current user’s payments.
Query Parameters:
status— Filter by statuspayment_type— Filter by payment typeordering— Order bycreated_at,gross_amount
GET /payments/{id}/¶
Retrieve payment details including payment_details (VA numbers, QR URLs).
POST /payments/charge/¶
Create a new charge for a subscription.
{
"subscription_id": "subscription-uuid"
}
POST /payments/{id}/refund/¶
Refund a settled payment.
{
"amount": 50000,
"reason": "Customer request",
"direct": false
}
GET /payments/{id}/check-status/¶
Check payment status directly from Midtrans API.
Response:
{
"local_status": "pending",
"midtrans_status": {
"transaction_status": "settlement",
"status_code": "200",
"...": "..."
}
}
Invoices¶
GET /invoices/¶
List the current user’s invoices.
Query Parameters:
status— Filter by statusordering— Order byissue_date,due_date,total_amount
GET /invoices/{id}/¶
Retrieve invoice details with line items.
Webhook¶
POST /webhook/notification/¶
Midtrans payment notification endpoint. No authentication required.
Midtrans sends POST requests here with payment status updates. The system:
Logs the webhook in
WebhookLogVerifies the SHA-512 signature
Updates payment status
Triggers subscription lifecycle events
Request Body (from Midtrans):
{
"order_id": "SUB-A1B2C3D4E5F6",
"transaction_status": "settlement",
"status_code": "200",
"gross_amount": "49000.00",
"signature_key": "sha512hash...",
"fraud_status": "accept",
"payment_type": "bank_transfer",
"transaction_id": "midtrans-txn-id"
}
Response:
{
"status": "ok",
"webhook_log_id": "uuid"
}
Notifications¶
GET /notifications/¶
List the current user’s notification logs.
Query Parameters:
notification_type— Filter by typechannel— Filter by channel (email,webhook,in_app)status— Filter by status
GET /notifications/{id}/¶
Retrieve notification detail.
GET /notifications/unread/¶
Get unread (queued) notifications (max 50).
POST /notifications/{id}/mark-read/¶
Mark a notification as read.
Wallet¶
GET /wallet/me/¶
Get or create the current user’s wallet.
Response:
{
"id": "uuid",
"balance": "150000.00",
"currency": "IDR",
"is_active": true
}
GET /wallet/transactions/¶
List wallet transactions (paginated).
Top-Ups¶
GET /topups/¶
List the current user’s top-ups.
Query Parameters:
status— Filter by statuspayment_type— Filter by payment type
GET /topups/{id}/¶
Retrieve top-up detail (includes payment_details with VA/QR).
POST /topups/¶
Create a new wallet top-up.
{
"amount": 100000,
"payment_type": "bank_transfer",
"bank": "bca"
}
Response (201):
{
"id": "uuid",
"order_id": "TOPUP-A1B2C3D4E5F6",
"amount": "100000.00",
"status": "pending",
"payment_type": "bank_transfer",
"payment_details": {
"bank": "bca",
"va_number": "1234567890"
}
}