curl --request POST \
--url https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-PARTNER-ID: <api-key>' \
--data '
{
"name": "Monthly Pro Subscription",
"customer_name": "John Doe",
"customer_email": "john.doe@example.com",
"customer_phone": "081234567890",
"account_id": "01K5G4FZZ18DMK0M5QTR8Y9QY9",
"schedule": {
"interval": 1,
"interval_unit": "month",
"start_time": "2026-07-01T00:00:00+07:00",
"total_interval": 12
},
"subscription_id": "SUB-2026-0001",
"merchant_reff_no": "REF-0001",
"amount": 150000,
"currency": "IDR",
"items": [
{
"item_name": "Pro Plan License",
"quantity": 1,
"unit_price": 50000,
"item_type": "subscription"
}
],
"customer_id": "CUST-001",
"payment_type": "credit_card",
"return_url": "https://merchant.example.com/subscription/return",
"retry_policy": {
"max_attempts": 3,
"interval_days": 1,
"failed_payment_action": "continue_plan"
},
"retry_count": 3,
"retry_interval_days": 1,
"failed_payment_action": "continue_plan",
"charge_immediately": false,
"allow_manual_payment": true,
"allow_user_notification": true,
"metadata": {
"description": "Pro plan monthly billing"
}
}
'import requests
url = "https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans"
payload = {
"name": "Monthly Pro Subscription",
"customer_name": "John Doe",
"customer_email": "john.doe@example.com",
"customer_phone": "081234567890",
"account_id": "01K5G4FZZ18DMK0M5QTR8Y9QY9",
"schedule": {
"interval": 1,
"interval_unit": "month",
"start_time": "2026-07-01T00:00:00+07:00",
"total_interval": 12
},
"subscription_id": "SUB-2026-0001",
"merchant_reff_no": "REF-0001",
"amount": 150000,
"currency": "IDR",
"items": [
{
"item_name": "Pro Plan License",
"quantity": 1,
"unit_price": 50000,
"item_type": "subscription"
}
],
"customer_id": "CUST-001",
"payment_type": "credit_card",
"return_url": "https://merchant.example.com/subscription/return",
"retry_policy": {
"max_attempts": 3,
"interval_days": 1,
"failed_payment_action": "continue_plan"
},
"retry_count": 3,
"retry_interval_days": 1,
"failed_payment_action": "continue_plan",
"charge_immediately": False,
"allow_manual_payment": True,
"allow_user_notification": True,
"metadata": { "description": "Pro plan monthly billing" }
}
headers = {
"Authorization": "Bearer <token>",
"X-PARTNER-ID": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'X-PARTNER-ID': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Monthly Pro Subscription',
customer_name: 'John Doe',
customer_email: 'john.doe@example.com',
customer_phone: '081234567890',
account_id: '01K5G4FZZ18DMK0M5QTR8Y9QY9',
schedule: {
interval: 1,
interval_unit: 'month',
start_time: '2026-07-01T00:00:00+07:00',
total_interval: 12
},
subscription_id: 'SUB-2026-0001',
merchant_reff_no: 'REF-0001',
amount: 150000,
currency: 'IDR',
items: [
{
item_name: 'Pro Plan License',
quantity: 1,
unit_price: 50000,
item_type: 'subscription'
}
],
customer_id: 'CUST-001',
payment_type: 'credit_card',
return_url: 'https://merchant.example.com/subscription/return',
retry_policy: {max_attempts: 3, interval_days: 1, failed_payment_action: 'continue_plan'},
retry_count: 3,
retry_interval_days: 1,
failed_payment_action: 'continue_plan',
charge_immediately: false,
allow_manual_payment: true,
allow_user_notification: true,
metadata: {description: 'Pro plan monthly billing'}
})
};
fetch('https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Monthly Pro Subscription',
'customer_name' => 'John Doe',
'customer_email' => 'john.doe@example.com',
'customer_phone' => '081234567890',
'account_id' => '01K5G4FZZ18DMK0M5QTR8Y9QY9',
'schedule' => [
'interval' => 1,
'interval_unit' => 'month',
'start_time' => '2026-07-01T00:00:00+07:00',
'total_interval' => 12
],
'subscription_id' => 'SUB-2026-0001',
'merchant_reff_no' => 'REF-0001',
'amount' => 150000,
'currency' => 'IDR',
'items' => [
[
'item_name' => 'Pro Plan License',
'quantity' => 1,
'unit_price' => 50000,
'item_type' => 'subscription'
]
],
'customer_id' => 'CUST-001',
'payment_type' => 'credit_card',
'return_url' => 'https://merchant.example.com/subscription/return',
'retry_policy' => [
'max_attempts' => 3,
'interval_days' => 1,
'failed_payment_action' => 'continue_plan'
],
'retry_count' => 3,
'retry_interval_days' => 1,
'failed_payment_action' => 'continue_plan',
'charge_immediately' => false,
'allow_manual_payment' => true,
'allow_user_notification' => true,
'metadata' => [
'description' => 'Pro plan monthly billing'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"X-PARTNER-ID: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans"
payload := strings.NewReader("{\n \"name\": \"Monthly Pro Subscription\",\n \"customer_name\": \"John Doe\",\n \"customer_email\": \"john.doe@example.com\",\n \"customer_phone\": \"081234567890\",\n \"account_id\": \"01K5G4FZZ18DMK0M5QTR8Y9QY9\",\n \"schedule\": {\n \"interval\": 1,\n \"interval_unit\": \"month\",\n \"start_time\": \"2026-07-01T00:00:00+07:00\",\n \"total_interval\": 12\n },\n \"subscription_id\": \"SUB-2026-0001\",\n \"merchant_reff_no\": \"REF-0001\",\n \"amount\": 150000,\n \"currency\": \"IDR\",\n \"items\": [\n {\n \"item_name\": \"Pro Plan License\",\n \"quantity\": 1,\n \"unit_price\": 50000,\n \"item_type\": \"subscription\"\n }\n ],\n \"customer_id\": \"CUST-001\",\n \"payment_type\": \"credit_card\",\n \"return_url\": \"https://merchant.example.com/subscription/return\",\n \"retry_policy\": {\n \"max_attempts\": 3,\n \"interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\"\n },\n \"retry_count\": 3,\n \"retry_interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\",\n \"charge_immediately\": false,\n \"allow_manual_payment\": true,\n \"allow_user_notification\": true,\n \"metadata\": {\n \"description\": \"Pro plan monthly billing\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("X-PARTNER-ID", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans")
.header("Authorization", "Bearer <token>")
.header("X-PARTNER-ID", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Monthly Pro Subscription\",\n \"customer_name\": \"John Doe\",\n \"customer_email\": \"john.doe@example.com\",\n \"customer_phone\": \"081234567890\",\n \"account_id\": \"01K5G4FZZ18DMK0M5QTR8Y9QY9\",\n \"schedule\": {\n \"interval\": 1,\n \"interval_unit\": \"month\",\n \"start_time\": \"2026-07-01T00:00:00+07:00\",\n \"total_interval\": 12\n },\n \"subscription_id\": \"SUB-2026-0001\",\n \"merchant_reff_no\": \"REF-0001\",\n \"amount\": 150000,\n \"currency\": \"IDR\",\n \"items\": [\n {\n \"item_name\": \"Pro Plan License\",\n \"quantity\": 1,\n \"unit_price\": 50000,\n \"item_type\": \"subscription\"\n }\n ],\n \"customer_id\": \"CUST-001\",\n \"payment_type\": \"credit_card\",\n \"return_url\": \"https://merchant.example.com/subscription/return\",\n \"retry_policy\": {\n \"max_attempts\": 3,\n \"interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\"\n },\n \"retry_count\": 3,\n \"retry_interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\",\n \"charge_immediately\": false,\n \"allow_manual_payment\": true,\n \"allow_user_notification\": true,\n \"metadata\": {\n \"description\": \"Pro plan monthly billing\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["X-PARTNER-ID"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Monthly Pro Subscription\",\n \"customer_name\": \"John Doe\",\n \"customer_email\": \"john.doe@example.com\",\n \"customer_phone\": \"081234567890\",\n \"account_id\": \"01K5G4FZZ18DMK0M5QTR8Y9QY9\",\n \"schedule\": {\n \"interval\": 1,\n \"interval_unit\": \"month\",\n \"start_time\": \"2026-07-01T00:00:00+07:00\",\n \"total_interval\": 12\n },\n \"subscription_id\": \"SUB-2026-0001\",\n \"merchant_reff_no\": \"REF-0001\",\n \"amount\": 150000,\n \"currency\": \"IDR\",\n \"items\": [\n {\n \"item_name\": \"Pro Plan License\",\n \"quantity\": 1,\n \"unit_price\": 50000,\n \"item_type\": \"subscription\"\n }\n ],\n \"customer_id\": \"CUST-001\",\n \"payment_type\": \"credit_card\",\n \"return_url\": \"https://merchant.example.com/subscription/return\",\n \"retry_policy\": {\n \"max_attempts\": 3,\n \"interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\"\n },\n \"retry_count\": 3,\n \"retry_interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\",\n \"charge_immediately\": false,\n \"allow_manual_payment\": true,\n \"allow_user_notification\": true,\n \"metadata\": {\n \"description\": \"Pro plan monthly billing\"\n }\n}"
response = http.request(request)
puts response.read_body{
"response_code": "SP000",
"response_message": "Successfully",
"data": {
"id": "9f8b6c2e-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
"name": "Monthly Pro Subscription",
"amount": "150000",
"currency": "IDR",
"created_at": "2026-06-09T10:00:00+07:00",
"schedule": {
"interval": 1,
"interval_unit": "month",
"current_interval": 1,
"total_interval": 12,
"start_time": "2026-07-01T00:00:00+07:00",
"previous_payment_at": null,
"next_payment_at": "2026-07-01T00:00:00+07:00"
},
"status": "active",
"payment_type": "credit_card",
"retry_policy": {
"max_attempts": 3,
"interval_days": 1,
"failed_payment_action": "continue_plan"
},
"metadata": {
"description": "Pro plan monthly billing",
"extra": []
},
"subscription_id": "SUB-2026-0001",
"merchant_reff_no": "REF-0001",
"payment_link_url": "https://pay.singapay.id/sub/9f8b6c2e",
"parent_plan_id": null,
"created_from": null
}
}{
"status": 422,
"success": false,
"errors": {
"code": 422,
"message": "The given data was invalid.",
"errors": {
"subscription_id": [
"The subscription id has already been taken."
]
}
}
}{
"response_code": "SP002",
"response_message": "An unexpected error occurred",
"data": null
}Create Plan
Creates a recurring subscription plan and returns the plan details with its payment link.
curl --request POST \
--url https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-PARTNER-ID: <api-key>' \
--data '
{
"name": "Monthly Pro Subscription",
"customer_name": "John Doe",
"customer_email": "john.doe@example.com",
"customer_phone": "081234567890",
"account_id": "01K5G4FZZ18DMK0M5QTR8Y9QY9",
"schedule": {
"interval": 1,
"interval_unit": "month",
"start_time": "2026-07-01T00:00:00+07:00",
"total_interval": 12
},
"subscription_id": "SUB-2026-0001",
"merchant_reff_no": "REF-0001",
"amount": 150000,
"currency": "IDR",
"items": [
{
"item_name": "Pro Plan License",
"quantity": 1,
"unit_price": 50000,
"item_type": "subscription"
}
],
"customer_id": "CUST-001",
"payment_type": "credit_card",
"return_url": "https://merchant.example.com/subscription/return",
"retry_policy": {
"max_attempts": 3,
"interval_days": 1,
"failed_payment_action": "continue_plan"
},
"retry_count": 3,
"retry_interval_days": 1,
"failed_payment_action": "continue_plan",
"charge_immediately": false,
"allow_manual_payment": true,
"allow_user_notification": true,
"metadata": {
"description": "Pro plan monthly billing"
}
}
'import requests
url = "https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans"
payload = {
"name": "Monthly Pro Subscription",
"customer_name": "John Doe",
"customer_email": "john.doe@example.com",
"customer_phone": "081234567890",
"account_id": "01K5G4FZZ18DMK0M5QTR8Y9QY9",
"schedule": {
"interval": 1,
"interval_unit": "month",
"start_time": "2026-07-01T00:00:00+07:00",
"total_interval": 12
},
"subscription_id": "SUB-2026-0001",
"merchant_reff_no": "REF-0001",
"amount": 150000,
"currency": "IDR",
"items": [
{
"item_name": "Pro Plan License",
"quantity": 1,
"unit_price": 50000,
"item_type": "subscription"
}
],
"customer_id": "CUST-001",
"payment_type": "credit_card",
"return_url": "https://merchant.example.com/subscription/return",
"retry_policy": {
"max_attempts": 3,
"interval_days": 1,
"failed_payment_action": "continue_plan"
},
"retry_count": 3,
"retry_interval_days": 1,
"failed_payment_action": "continue_plan",
"charge_immediately": False,
"allow_manual_payment": True,
"allow_user_notification": True,
"metadata": { "description": "Pro plan monthly billing" }
}
headers = {
"Authorization": "Bearer <token>",
"X-PARTNER-ID": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'X-PARTNER-ID': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Monthly Pro Subscription',
customer_name: 'John Doe',
customer_email: 'john.doe@example.com',
customer_phone: '081234567890',
account_id: '01K5G4FZZ18DMK0M5QTR8Y9QY9',
schedule: {
interval: 1,
interval_unit: 'month',
start_time: '2026-07-01T00:00:00+07:00',
total_interval: 12
},
subscription_id: 'SUB-2026-0001',
merchant_reff_no: 'REF-0001',
amount: 150000,
currency: 'IDR',
items: [
{
item_name: 'Pro Plan License',
quantity: 1,
unit_price: 50000,
item_type: 'subscription'
}
],
customer_id: 'CUST-001',
payment_type: 'credit_card',
return_url: 'https://merchant.example.com/subscription/return',
retry_policy: {max_attempts: 3, interval_days: 1, failed_payment_action: 'continue_plan'},
retry_count: 3,
retry_interval_days: 1,
failed_payment_action: 'continue_plan',
charge_immediately: false,
allow_manual_payment: true,
allow_user_notification: true,
metadata: {description: 'Pro plan monthly billing'}
})
};
fetch('https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Monthly Pro Subscription',
'customer_name' => 'John Doe',
'customer_email' => 'john.doe@example.com',
'customer_phone' => '081234567890',
'account_id' => '01K5G4FZZ18DMK0M5QTR8Y9QY9',
'schedule' => [
'interval' => 1,
'interval_unit' => 'month',
'start_time' => '2026-07-01T00:00:00+07:00',
'total_interval' => 12
],
'subscription_id' => 'SUB-2026-0001',
'merchant_reff_no' => 'REF-0001',
'amount' => 150000,
'currency' => 'IDR',
'items' => [
[
'item_name' => 'Pro Plan License',
'quantity' => 1,
'unit_price' => 50000,
'item_type' => 'subscription'
]
],
'customer_id' => 'CUST-001',
'payment_type' => 'credit_card',
'return_url' => 'https://merchant.example.com/subscription/return',
'retry_policy' => [
'max_attempts' => 3,
'interval_days' => 1,
'failed_payment_action' => 'continue_plan'
],
'retry_count' => 3,
'retry_interval_days' => 1,
'failed_payment_action' => 'continue_plan',
'charge_immediately' => false,
'allow_manual_payment' => true,
'allow_user_notification' => true,
'metadata' => [
'description' => 'Pro plan monthly billing'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"X-PARTNER-ID: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans"
payload := strings.NewReader("{\n \"name\": \"Monthly Pro Subscription\",\n \"customer_name\": \"John Doe\",\n \"customer_email\": \"john.doe@example.com\",\n \"customer_phone\": \"081234567890\",\n \"account_id\": \"01K5G4FZZ18DMK0M5QTR8Y9QY9\",\n \"schedule\": {\n \"interval\": 1,\n \"interval_unit\": \"month\",\n \"start_time\": \"2026-07-01T00:00:00+07:00\",\n \"total_interval\": 12\n },\n \"subscription_id\": \"SUB-2026-0001\",\n \"merchant_reff_no\": \"REF-0001\",\n \"amount\": 150000,\n \"currency\": \"IDR\",\n \"items\": [\n {\n \"item_name\": \"Pro Plan License\",\n \"quantity\": 1,\n \"unit_price\": 50000,\n \"item_type\": \"subscription\"\n }\n ],\n \"customer_id\": \"CUST-001\",\n \"payment_type\": \"credit_card\",\n \"return_url\": \"https://merchant.example.com/subscription/return\",\n \"retry_policy\": {\n \"max_attempts\": 3,\n \"interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\"\n },\n \"retry_count\": 3,\n \"retry_interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\",\n \"charge_immediately\": false,\n \"allow_manual_payment\": true,\n \"allow_user_notification\": true,\n \"metadata\": {\n \"description\": \"Pro plan monthly billing\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("X-PARTNER-ID", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans")
.header("Authorization", "Bearer <token>")
.header("X-PARTNER-ID", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Monthly Pro Subscription\",\n \"customer_name\": \"John Doe\",\n \"customer_email\": \"john.doe@example.com\",\n \"customer_phone\": \"081234567890\",\n \"account_id\": \"01K5G4FZZ18DMK0M5QTR8Y9QY9\",\n \"schedule\": {\n \"interval\": 1,\n \"interval_unit\": \"month\",\n \"start_time\": \"2026-07-01T00:00:00+07:00\",\n \"total_interval\": 12\n },\n \"subscription_id\": \"SUB-2026-0001\",\n \"merchant_reff_no\": \"REF-0001\",\n \"amount\": 150000,\n \"currency\": \"IDR\",\n \"items\": [\n {\n \"item_name\": \"Pro Plan License\",\n \"quantity\": 1,\n \"unit_price\": 50000,\n \"item_type\": \"subscription\"\n }\n ],\n \"customer_id\": \"CUST-001\",\n \"payment_type\": \"credit_card\",\n \"return_url\": \"https://merchant.example.com/subscription/return\",\n \"retry_policy\": {\n \"max_attempts\": 3,\n \"interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\"\n },\n \"retry_count\": 3,\n \"retry_interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\",\n \"charge_immediately\": false,\n \"allow_manual_payment\": true,\n \"allow_user_notification\": true,\n \"metadata\": {\n \"description\": \"Pro plan monthly billing\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox-payment-b2b.singapay.id/api/v2.0/recurring/plans")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["X-PARTNER-ID"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Monthly Pro Subscription\",\n \"customer_name\": \"John Doe\",\n \"customer_email\": \"john.doe@example.com\",\n \"customer_phone\": \"081234567890\",\n \"account_id\": \"01K5G4FZZ18DMK0M5QTR8Y9QY9\",\n \"schedule\": {\n \"interval\": 1,\n \"interval_unit\": \"month\",\n \"start_time\": \"2026-07-01T00:00:00+07:00\",\n \"total_interval\": 12\n },\n \"subscription_id\": \"SUB-2026-0001\",\n \"merchant_reff_no\": \"REF-0001\",\n \"amount\": 150000,\n \"currency\": \"IDR\",\n \"items\": [\n {\n \"item_name\": \"Pro Plan License\",\n \"quantity\": 1,\n \"unit_price\": 50000,\n \"item_type\": \"subscription\"\n }\n ],\n \"customer_id\": \"CUST-001\",\n \"payment_type\": \"credit_card\",\n \"return_url\": \"https://merchant.example.com/subscription/return\",\n \"retry_policy\": {\n \"max_attempts\": 3,\n \"interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\"\n },\n \"retry_count\": 3,\n \"retry_interval_days\": 1,\n \"failed_payment_action\": \"continue_plan\",\n \"charge_immediately\": false,\n \"allow_manual_payment\": true,\n \"allow_user_notification\": true,\n \"metadata\": {\n \"description\": \"Pro plan monthly billing\"\n }\n}"
response = http.request(request)
puts response.read_body{
"response_code": "SP000",
"response_message": "Successfully",
"data": {
"id": "9f8b6c2e-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
"name": "Monthly Pro Subscription",
"amount": "150000",
"currency": "IDR",
"created_at": "2026-06-09T10:00:00+07:00",
"schedule": {
"interval": 1,
"interval_unit": "month",
"current_interval": 1,
"total_interval": 12,
"start_time": "2026-07-01T00:00:00+07:00",
"previous_payment_at": null,
"next_payment_at": "2026-07-01T00:00:00+07:00"
},
"status": "active",
"payment_type": "credit_card",
"retry_policy": {
"max_attempts": 3,
"interval_days": 1,
"failed_payment_action": "continue_plan"
},
"metadata": {
"description": "Pro plan monthly billing",
"extra": []
},
"subscription_id": "SUB-2026-0001",
"merchant_reff_no": "REF-0001",
"payment_link_url": "https://pay.singapay.id/sub/9f8b6c2e",
"parent_plan_id": null,
"created_from": null
}
}{
"status": 422,
"success": false,
"errors": {
"code": 422,
"message": "The given data was invalid.",
"errors": {
"subscription_id": [
"The subscription id has already been taken."
]
}
}
}{
"response_code": "SP002",
"response_message": "An unexpected error occurred",
"data": null
}Authorizations
JWT issued by POST /api/v1.1/access-token/b2b. Send Authorization: Bearer <token>.
Merchant API key (Credential.api_key). Required on every request.
Body
Payload for CreateSubscriptionPlanRequest. Exactly one of amount or items must be present (mutually exclusive). Per-cycle charge (amount-only or sum of quantity * unit_price) must be at least IDR 10,000 when greater than zero (ChannelType::MIN_CARD_AMOUNT_IDR).
Human-readable plan name.
255"Monthly Pro Subscription"
Full name of the subscribing customer.
191"John Doe"
Customer email address.
191"john.doe@example.com"
Customer contact phone number.
50"081234567890"
Account ULID owned by the authenticated merchant.
50"01K5G4FZZ18DMK0M5QTR8Y9QY9"
Billing schedule that controls how often and how many times the plan charges the customer.
Show child attributes
Show child attributes
Stored in sub_plans.reference_id; must be unique on that column when provided.
100"SUB-2026-0001"
Optional merchant reference number for reconciliation.
255"REF-0001"
Per-cycle charge in IDR. Use without items for amount-only plans.
x >= 0150000
ISO 4217 currency code. Defaults to IDR.
3"IDR"
Use without amount for itemized plans; per-cycle total = sum of quantity * unit_price.
1Show child attributes
Show child attributes
Optional merchant-side customer identifier.
100"CUST-001"
Preferred payment instrument for the plan.
credit_card, gopay "credit_card"
URL the customer is redirected to after completing payment setup.
2048"https://merchant.example.com/subscription/return"
Optional retry policy applied to every cycle when a charge fails.
Show child attributes
Show child attributes
Deprecated — use retry_policy.max_attempts.
1 <= x <= 53
Deprecated — use retry_policy.interval_days.
1 <= x <= 71
Deprecated — use retry_policy.failed_payment_action.
continue_plan, stop_plan "continue_plan"
Charge the first cycle immediately on creation instead of waiting for start_time.
false
Allow the customer to pay bills manually via the payment link.
true
Send subscription notifications (reminders, receipts) to the customer.
true
Free-form metadata stored with the plan.
Show child attributes
Show child attributes
Response
SP000 Successfully — plan created (data is RecurringPlanData).
Merchant v2 envelope returned on a successful plan operation (SP000). Used by create (HTTP 201), show, update, and cancel (HTTP 200). The data.upgrade block is present only on an upgrade/downgrade.
