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 code

  • search — Search in name and description

  • ordering — Order by price, 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 status

  • payment_type — Filter by payment type

  • ordering — Order by created_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 status

  • payment_type — Filter by payment type

  • ordering — Order by created_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 status

  • ordering — Order by issue_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:

  1. Logs the webhook in WebhookLog

  2. Verifies the SHA-512 signature

  3. Updates payment status

  4. 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 type

  • channel — 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 status

  • payment_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"
  }
}