Welcome to Xendit’s latest documentation. For legacy content, access the previous version here.

Usage-based Subscriptions

Prev Next

Usage-based subscription is a type of recurring payment model where the payment amount varies and is determined based on the user's consumption or usage at a specific cut-off time before the next billing cycle. This model offers flexibility for businesses that charge customers based on actual usage rather than a fixed fee.

Common use cases include utility services, postpaid plan for telecommunication, ride hailing, SaaS or cloud storage subscriptions, and many more.

How to integrate

In usage-based subscriptions, the amount to be charged must be defined for each billing cycle before the cycle begins. This ensures that the end user’s balance can be accurately deducted based on their usage during the period.

  1. To start, you need to create a customer object in Xendit by registering the end user's details.

    Request - POST /customers

    {
         "reference_id": "demo_1475801962688",
         "type": "INDIVIDUAL",
         "individual_detail": {
           "given_names": "John",
           "surname": "Doe"
         },
         "email": "customer@website.com",
         "mobile_number": "+628121234567890"
    }
     

    Response - POST /customers

    {
        "type": "INDIVIDUAL",
        "date_of_registration": null,
        "email": "customer@website.com",
        "mobile_number": "+628121234567890",
        "phone_number": null,
        "created": "2024-12-06T02:42:36.343Z",
        "updated": "2024-12-06T02:42:36.343Z",
        "description": null,
        "hashed_phone_number": null,
        "domicile_of_registration": null,
        "kyc_documents": [],
        "id": "cust-ab93b98b-3e79-4961-b243-66a0e66daadc",
        "reference_id": "demo_1475801962688",
        "metadata": null,
        "individual_detail": {
            "given_names": "John",
            "given_names_non_roman": null,
            "surname": "Doe",
            "surname_non_roman": null,
            "nationality": null,
            "date_of_birth": null,
            "place_of_birth": null,
            "gender": null,
            "employment": null
        },
        "business_detail": null,
        "addresses": [],
        "identity_accounts": []
    }
  2. Once the end user is registered, create a subscription plan tailored to their preference and needs

    Request - POST /recurring/plans

    {
        "reference_id": "ref-{{$timestamp}}",
        "customer_id": "cust-7e34f507-808d-44f8-a4a6-aea89a14a89c",
        "recurring_action": "PAYMENT",
        "currency": "IDR",
        "amount": 13579,
        "schedule": {
            "reference_id": "test-{{$timestamp}}",
            "interval": "MONTH",
            "interval_count": 1,
            "total_recurrence": 6,
            "anchor_date": "2025-02-15T09:44:19.546Z",
            "retry_interval": "DAY",
            "retry_interval_count": 1,
            "total_retry": 3,
            "failed_attempt_notifications": [
                1,3
            ]
        },
        "notification_config": {
            "locale": "en",
            "recurring_created": [
                "WHATSAPP",
                "EMAIL"
            ],
            "recurring_succeeded": [
                "WHATSAPP",
                "EMAIL"
            ],
            "recurring_failed": [
                "WHATSAPP",
                "EMAIL"
            ]
        },
        "failed_cycle_action": "STOP",
        "immediate_action_type": "FULL_AMOUNT",
        "payment_link_for_failed_attempt": true,
        "metadata": null,
        "description": "Xendit Recurring Test",
        "success_return_url": "https://www.xendit.co/",
        "failure_return_url": "https://www.xendit.co/"
    }

    Response - POST /recurring/plans

    {
        "id": "repl_c87f3312-a9c1-4eee-932c-38479f911830",
        "reference_id": "ref-1733299168",
        "customer_id": "cust-7e34f507-808d-44f8-a4a6-aea89a14a89c",
        "recurring_action": "PAYMENT",
        "failed_cycle_action": "STOP",
        "recurring_cycle_count": 0,
        "currency": "IDR",
        "amount": 13579,
        "status": "REQUIRES_ACTION",
        "created": "2024-12-04T07:59:28.553Z",
        "updated": "2024-12-04T07:59:28.553Z",
        "schedule_id": "resc_07d3197d-f860-47dc-bc6e-b87deaf34735",
        "payment_methods": [],
        "schedule": {
            "id": "resc_07d3197d-f860-47dc-bc6e-b87deaf34735",
            "reference_id": "test-1733299168",
            "business_id": "62440e322008e87fb29c1fd0",
            "interval": "MONTH",
            "interval_count": 1,
            "total_recurrence": 6,
            "anchor_date": "2025-02-15T09:44:19.546Z",
            "retry_interval": "DAY",
            "retry_interval_count": 1,
            "total_retry": 3,
            "failed_attempt_notifications": [
                1,
                3
            ],
            "created": "2024-12-04T07:59:28.545Z",
            "updated": "2024-12-04T07:59:28.545Z"
        },
        "immediate_action_type": "FULL_AMOUNT",
        "notification_config": {
            "locale": "en",
            "recurring_created": [
                "WHATSAPP",
                "EMAIL"
            ],
            "recurring_succeeded": [
                "WHATSAPP",
                "EMAIL"
            ],
            "recurring_failed": [
                "WHATSAPP",
                "EMAIL"
            ]
        },
        "metadata": null,
        "description": "Xendit Recurring Test",
        "actions": [
            {
                "url": "https://linking-dev.xendit.co/pali_a757f019-19b9-4522-91fe-03b6dc00368a",
                "action": "AUTH",
                "method": "GET",
                "url_type": "WEB"
            }
        ],
        "success_return_url": "https://www.xendit.co/",
        "failure_return_url": "https://www.xendit.co/",
        "items": null,
        "payment_link_for_failed_attempt": true,
        "failure_code": null
    }
  3. After creating a subscription, redirect the end user to the Xendit-hosted page using the actions object from the API response. This step allows the end user to link their payment method to the subscription plan.

  4. Once the end user successfully links their payment method, Xendit will send a recurring.plan.activation webhook to confirm the activation of the subscription plan.

  5. Xendit will send a recurring.cycle.created webhook for each upcoming billing cycle, notifying you that the next cycle is about to begin. You can store the cycle.id on your end to be used for updating next cycle billing.

  6. To deduct the user's balance accurately for the upcoming billing cycle, you must use the Update Cycle API to define the total usage-based amount to be charged. This update must be completed before the scheduled_timestamp date (e.g., if scheduled_timestamp is "2020-12-20," the update should occur no later than "2020-12-19"). Once the date component of the scheduled_timestamp is reached, no further updates can be made to that cycle.

  7. This process needs to be repeated for each subsequent billing cycle to reflect the correct usage-based charges.

Learn more about payments lifecyle here.