Create Subscription

Create a subscription or recurring transaction by sending all the details required to create a transaction. The details such as name, amount, currency, payment_type, token, and schedule are sent in the request. Successful request returns id status:active, and other subscription details.

Subscription API currently supports idempotency when creating subscription. If you're using the same idempotency key, you will continue to receive the same response. Subscription will validate the request body first before performing the idempotency check - this idempotency applies for the next 3 minutes for the same key.




Create Subscription Method

HTTP MethodEndpointDescription
POSTBASE_URL/v1/subscriptionsCreate subscription



Create Subscription Request

{
    "name": "MONTHLY_2019",
    "amount": "14000",
    "currency": "IDR",
    "payment_type": "credit_card",
    "token": "48111111sHfSakAvHvFQFEjTivUV1114",
    "schedule": {
      "interval": 1,
      "interval_unit": "month",
      "max_interval": 12,
      "start_time": "2020-07-22 07:25:01 +0700"
    },
    "retry_schedule": {
      "interval": 1,
      "interval_unit": "day",
      "max_interval": 3,
    },
    "metadata": {
      "description": "Recurring payment for A"
    },
    "customer_details": {
      "first_name": "John",
      "last_name": "Doe",
      "email": "[email protected]",
      "phone": "+62812345678"
    }
}
{
    "name": "MONTHLY_2019",
    "amount": "14000",
    "currency": "IDR",
    "payment_type": "gopay",
    "token": "eyJ0eXBlIjogIkdPUEFZX1dBTExFVCIsICJpZCI6ICIifQ==",
    "schedule": {
      "interval": 1,
      "interval_unit": "month",
      "max_interval": 12,
      "start_time": "2020-07-22 07:25:01 +0700"
    },
    "metadata": {
      "description": "Recurring payment for A"
    },
    "customer_details": {
      "first_name": "John",
      "last_name": "Doe",
      "email": "[email protected]",
      "phone": "+62812345678"
    },
    "gopay": {
      "account_id": "0dd2cd90-a9a9-4a09-b393-21162dfb713b"
    }
}
JSON AttributeDescriptionTypeRequired
nameName of the subscription. It is used to generate order ID for the transaction. Generated order ID will contain subscription name and 32 digits of unique number.
Note: Allowed symbols are dash(-), underscore(_), tilde (~), and dot (.).
String(40)Required
amountThe amount to be charged to the customer.
Note: Do not use decimal.
StringRequired
currencyISO-4217 representation of three-letter alphabetic currency code. Value: IDR.
Note: Currently only IDR is supported.
StringRequired
payment_typeThe payment method used by the customer. Note: Currently only credit_card and gopay are supported.StringRequired
token (Card Payment)The saved_token_id for Card Payment. Credit Card token retrieved via One Click Token ResponseStringRequired
token (GoPay)The token for Gopay Tokenization. GoPay token retrieved via Get Pay Account APIStringRequired
scheduleDetails of the subscription schedule.ObjectRequired
retry_scheduleDetails of the retry scheudleObjectOptional
metadataMetadata of subscription specified by you.
Note: Limit the size to less than 1KB.
ObjectOptional
customer_detailsDetails of the customer.ObjectOptional
gopayGoPay subscription information, required if payment type is gopay.ObjectConditional

Obtaining GoPay token

Get Pay Account API is called to retrieve GoPay Token, needed for GoPay subscriptions. Account ID can be retrieved from HTTP notification of first transaction charge that will be used to create subscription for the scheduled subsequent charges.


HTTP MethodEndpointDefinition
GETBASE_URL/v2/pay/account/account_idGet GoPay's account information and linked status.

{
  "status_code": "200",
  "payment_type": "gopay",
  "account_id": "00000269-7836-49e5-bc65-e592afafec14",
  "account_status": "ENABLED",
  "metadata": {
    "payment_options": [
      {
        "name": "GOPAY_WALLET",
        "active": true,
        "balance": {
          "value": "1000000.00",
          "currency": "IDR"
        },
        "metadata": {},
        "token": "eyJ0eXBlIjogIkdPUEFZX1dBTExFVCIsICJpZCI6ICIifQ==" // The token is used for Subscription 
      }
    ]
  }
}

Obtaining card token & GoPay account ID via Get Transaction API

Get Transaction API is used to get card token that has been saved in the first transaction charge facilitated in a One Click flow, or GoPay account_id mapped to the user_id passed during create Snap Token creation, that is needed to make the subsequent scheduled charges with Subscription API.


HTTP MethodEndpointDefinition
GETBASE_URL/v2/{order_id OR transaction_id}/statusGet the status of transaction and card information.

{
    "masked_card": "48111111-1114",
    "approval_code": "1689306913393",
    "bank": "cimb",
    "eci": "05",
    "saved_token_id": "48111111ktaqYoxJQAGvXBoxEPqO1114", // The token is used for Subscription 
    "saved_token_id_expired_at": "2024-11-30 07:00:00",
    "channel_response_code": "00",
    "channel_response_message": "Approved",
    "three_ds_version": "2",
    "transaction_time": "2023-07-14 10:55:09",
    "gross_amount": "20000.00",
    "currency": "IDR",
    "order_id": "sample-store-1689306888",
    "payment_type": "credit_card",
    "signature_key": "40df7114b015e899526f78f98ff7a0297fa8ba270e5a436687af9cfee2ec471444dd239834d8836f217b1bdf12e9677cb65643470dc666c578fb120b8135480b",
    "status_code": "200",
    "transaction_id": "a4e2f006-2cc1-4110-ac38-811e4c427199",
    "transaction_status": "capture",
    "fraud_status": "accept",
    "expiry_time": "2023-07-14 11:05:09",
    "status_message": "Success, Credit Card transaction is successful",
    "merchant_id": "M123",
    "card_type": "credit",
    "challenge_completion": true
}


OPTIONAL : Authenticating first transaction for GoPay Subscription


All payment transactions beyond the linking step will not have an additional authentication challenge e.g. PIN challenge in GoPay app. As such all additional authentication - if deemed as needed- will need to be set up in merchant's web/app directly between merchant and customers, before initiating the payment charge to Subscription API.

Do note that during onboarding, you might be required to perform authentication on first transaction - this is referring to merchant's own authentication, as this is not part of Subscription API / GoPay Tokenization payment flow.




Create Subscription Sample Response

{
  "id": "d98a63b8-97e4-4059-825f-0f62340407e9",
  "name": "MONTHLY_2019",
  "amount": "14000",
  "currency": "IDR",
  "created_at": "2019-05-29T09:11:01.810452",
  "schedule": {
    "interval": 1,
    "interval_unit": "month",
    "start_time": "2019-05-29T09:11:01.803677",
    "previous_execution_at": "2019-05-29T09:11:01.803677",
    "next_execution_at": "2019-06-29T09:11:01.803677"
  },
  "retry_schedule": {
  	"interval": 1,
  	"interval_unit": "day",
    "max_interval": 3,
  },
  "status": "active",
  "token": "48111111sHfSakAvHvFQFEjTivUV1114",
  "payment_type": "credit_card",
  "metadata": {
    "description": "Recurring payment for A"
  },
  "customer_details": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "phone": "+62812345678"
  }
}
{
  "id": "d98a63b8-97e4-4059-825f-0f62340407e9",
  "name": "MONTHLY_2019",
  "amount": "14000",
  "currency": "IDR",
  "created_at": "2019-05-29T09:11:01.810452",
  "schedule": {
    "interval": 1,
    "interval_unit": "month",
    "start_time": "2019-05-29T09:11:01.803677",
    "previous_execution_at": "2019-05-29T09:11:01.803677",
    "next_execution_at": "2019-06-29T09:11:01.803677"
  },
  "status": "active",
  "token": "48111111sHfSakAvHvFQFEjTivUV1114",
  "payment_type": "credit_card",
  "metadata": {
    "description": "Recurring payment for A"
  },
  "customer_details": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "phone": "+62812345678"
  },
  "gopay": {                                                    
    "account_id": "phy56f8f-2683-4248-8080-e59b36c6bbgf"
  }
}
{
  "status_message": "Invalid parameter.",
  "validation_messages": [
    "subscription.amount is required"
  ]
}
{
  "status_message": "Sorry, Our system is recovering from unexpected issues. Please retry."
}
JSON AttributeDescriptionTypeNotes
idSubscription ID given by Midtrans.String
nameSubscription name specified by you.String
amountAmount specified by you for recurring charge.String
currencyISO-4217 representation of three-letter alphabetic currency code. Value: IDR.
Note: Currently only IDR is supported.
String
created_atSubscription schedule creation timestamp in ISO 8601 format. Time Zone: GMT + 7.String
scheduleDetails of the subscription schedule.Object
retry_scheduleDetails of the retry subscription schedule.Object
statusCurrent subscription status.
Possible values are active, inactive.
String
token (Card Payment)The saved_token_id for Card Payment. Credit Card token retrieved via Get Pay Account API.String
token (GoPay)Token that is retrieved via Get Pay Account APIString
payment_typeThe payment method used by the customer. Value: credit_card.
Note: Currently only credit_card and gopay are supported.
String
metadataMetadata of subscription specified by you.
Note: Limit the size to less than 1KB.
ObjectConditional
customer_detailsDetails of the customer.Object
status_messageDescription of the error.String
validation_messageDetailed description of the error.Array(String)
account_id (GoPay)GoPay account IDString

Retry Mechanism if Subscription Fails


If for some reason deduction fails, Midtrans will perform automatic retries 3 times for every one hour by default (unless customized) before marking subscription as inactive. Retries for every charge will be attempted until exhausted regardless of subscription's status. To test for the automatic retries, you can try to simulate with cases that returns error such as incorrect card token, or GoPay account is in unlinked state prior to charge.

If you do not want to retry your failed subscription charge, simply specify the max_interval parameter in the retry_schedule object as 0.


📘

Retry notification

Note that Midtrans Payment API will send HTTP notification for every transactions' attempt; while Midtrans's Subscription API will send a separate notification at the end of retry attempt cycle of every transaction or once retry is successful. As such, use Subscription HTTP notification should be referred to when handling failed or success subscriptions.


Example of retry schedules :
There's a payment that's failed to be processed at 11 Oct 2022 15.48 GMT+7. Then, Midtrans will automatically retry at :

  • 11 Oct 2022 16.48 GMT+7
  • 11 Oct 2022 17.48 GMT+7
  • 11 Oct 2022 18.48 GMT+7

OPTIONAL - Accepting Subscription in Snap Checkout


Use this object to show a dedicated recurring flow UI in Snap - differences include card will be automatically saved without having user manually tick the checkbox and adjusted copy to better suit recurring payments. Snap will then return the information passed here back in HTTP notification, for you to utilize when creating a subscription via the Subscription API.

Use this object in conjunction with Subscription API - add this object to alter the Snap customer UI, then convert the transaction to recurring payments using Subscription API. Make sure to also have the prerequisites to accept Subscription (e.g. One Click feature) - otherwise transactions might fail.

Note that if you do choose to pass the start_time and interval_unit within the object, make sure to use the same information when calling the Subscription API - otherwise, information presented to user and actual subscription charge schedule will be different, which might result in chargeback.


...
"recurring": {
    "required": true,
    "start_time": "2024-06-09 15:07:00 +0700",
    "interval_unit": "week"
}
...
ParameterDescriptionTypeRequired
requiredSpecify the intent whether payment will be utilizing recurring payments or not.IntegerRequired (if recurring object is passed)
start_timeStart of the subscription schedule. Passed information will be shown in Snap Checkout UI & returned in HTTP Notification.StringOptional
interval_unitSubscription charge internal unitStringOptional
Language
Credentials
Basic
base64
:
Click Try It! to start a request and see the response here!