Subscriptions
With Rapyd Collect, you can create subscriptions (also called subscription billing, recurring billing or recurring payments).
Subscriptions work well for businesses that offer a monthly service. Rapyd Collect helps you integrate this functionality into your website or application.
This use case describes a regular monthly billing with the amount always the same.
For periodic billing with the amount based on usage, or different rate levels depending on quantity, see Plan.
For periodic billing with a fixed end date, see Create Subscription.
A customer would like to use your digital service, Acme Music, in Singapore. The cost is 3 Singapore dollars per month, indefinitely.
Part 1 - Create Product of type 'service'.
Part 2 - Create Plan to define the pricing structure.
Part 3 - Create Subscription
Note: A customer profile with a payment method defined is needed to create a subscription.
Let’s look at the highlights of your workflow.
Prerequisite
A customer profile is created only one time. It contains payment methods that can be reused for all subsequent payments. It can be used for recurring payments and many other purposes.
Part 1 - Select a Payment Method
Your website queries Rapyd for the payment methods available in Singapore.
Rapyd returns a list of payment methods.
Your website offers a list of choices to your customer.
Part 2 - Create a Customer Profile
The customer selects your product and a payment method.
Your website back end asks Rapyd to create a customer profile.
Rapyd creates the profile and assigns a unique ID.
Step 1 - Create a Product
You define the product you are providing.
Your website back end asks Rapyd to create a product of type 'service'.
Rapyd creates the product and returns a Product ID.
Step 2 - Create a Plan
You determine the pricing structure you want for the recurring payment.
Your website back end asks Rapyd to create the plan.
Rapyd creates the plan and returns a Plan ID.
Step 3 - Create the Subscription
You decide the parameters you need for the recurring payment.
Your website back end asks Rapyd to create a subscription for the customer.
Rapyd creates the subscription and returns a Subscription ID.
At the end of each billing period, Rapyd collects the amount due and adds it to your wallet.
The message sequence diagrams below describe how information is exchanged between Rapyd, the merchant, and the card network.
Create Subscription
Customer ID with Saved Payment Method
If you already have a customer with a payment method, you can skip to Create Product.
First, you need to determine which Singaporean payment methods support payments in Singapore dollars (SGD). Run List Payment Methods by Country with the following parameters:
Description of Query Parameters
Query Parameter | Description |
---|---|
country | SG, the country code for Singapore. |
currency | SGD, the currency code for Singapore dollars. |
List Payment Methods by Country Request
Request
// Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/country?country=SG¤cy=SGD // Message body absent
.NET Core
using System; namespace RapydApiRequestSample { class Program { static void Main(string[] args) { try { string country = "SG"; string currency = "SGD"; string result = RapydApiRequestSample.Utilities.MakeRequest("GET", $"/v1/payment_methods/country?country={country}¤cy={currency}"); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine("Error completing request: " + e.Message); } } } }
JavaScript
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest; async function main() { try { const result = await makeRequest( 'GET', '/v1/payment_methods/country?country=SG¤cy=SGD ); console.log(result); } catch (error) { console.error('Error completing request', error); } }
PHP
<?php $path = $_SERVER['DOCUMENT_ROOT']; $path .= "/<path-to-your-utility-file>/utilities.php"; include($path); try { $object = make_request('get', '/v1/payment_methods/country?country=SG¤cy=SGD'); echo $object; } catch (Exception $e) { echo "Error: $e"; } ?>
Python
from pprint import pprint from utilities import make_request country = 'SG' currency = 'SGD' results = make_request(method='get', path=f'/v1/payment_methods/country?country={country}¤cy={currency}') pprint(results)
List Payment Methods by Country Response
Rapyd returns the following response (redacted for brevity). The fields are described in Payment Method Type Object .
Response
{ "status": { "error_code": "", "status": "SUCCESS", "message": "", "response_code": "", "operation_id": "865cd976-1b2f-4321-b88c-3caaa5a4499e" }, "data": [ { "type": "sg_credit_cup_card", "name": "UnionPay", "category": "card", "image": "https://iconslib.rapyd.net/checkout/sg_credit_cup_card.png", "country": "sg", "payment_flow_type": "", "currencies": [ "SGD" ], "status": 1, "is_cancelable": true, "payment_options": [ { "name": "capture", "type": "boolean", "regex": "", "description": "Determines when the payment is processed for capture.", "is_required": false, "is_updatable": false }, { "name": "complete_payment_url", "type": "string", "regex": "", "description": "the complete_payment_url field must be filled in.", "is_required": true, "is_updatable": false }, { "name": "error_payment_url", "type": "string", "regex": "", "description": "the error_payment_url field must be filled in.", "is_required": true, "is_updatable": false }, { "name": "statement_descriptor", "type": "string", "regex": "/^[a-zA-Z0-9]{0,22}/", "description": "A text description suitable for a customer's payment statement. Limited to 22 characters.", "is_required": false, "is_updatable": false } ], "is_expirable": false, "is_online": false, "is_refundable": true, "minimum_expiration_seconds": 0, "maximum_expiration_seconds": 604800, "virtual_payment_method_type": "card", "is_virtual": false, "multiple_overage_allowed": false, "amount_range_per_currency": [ { "currency": "SGD", "maximum_amount": null, "minimum_amount": null } ], "is_tokenizable": false, "supported_digital_wallet_providers": [], "submid_required": false, "is_restricted": false }, // . . . ] }
Using your website or a Rapyd hosted page, you display one or more of these payment methods to the customer. The customer chooses one and provides the required information.
Each payment method has its own requirements. To determine what information the customer needs to provide, run Get Payment Method Required Fields. In this use case, our customer chose UnionPay.
Description of Path Parameters
Path Parameter | Description |
---|---|
type | sg_credit_cup_card, the ID for the UnionPay payment method type. |
Get Payment Method Required Fields Request
Request
// Request URL: GET https://sandboxapi.rapyd.net/v1/payment_methods/sg_credit_cup_card/required_fields // Message body absent
.NET Core
using System; namespace RapydApiRequestSample { class Program { static void Main(string[] args) { try { string type = "sg_fast_bank"; string result = RapydApiRequestSample.Utilities.MakeRequest("GET", $"/v1/payment_methods/{type}/required_fields"); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine("Error completing request: " + e.Message); } } } }
JavaScript
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest; async function main() { try { const result = await makeRequest('GET', '/v1/payment_methods/sg_fast_bank/required_fields'); console.log(result); } catch (error) { console.error('Error completing request', error); } }
PHP
<?php $path = $_SERVER['DOCUMENT_ROOT']; $path .= "/<path-to-your-utility-file>/utilities.php"; include($path); try { $object = make_request('get', '/v1/payment_methods/sg_fast_bank/required_fields'); echo $object; } catch (Exception $e) { echo "Error: $e"; } ?>
Python
from pprint import pprint from utilities import make_request payment_method = 'sg_fast_bank' results = make_request(method='get', path=f'/v1/payment_methods/{payment_method}/required_fields') pprint(results)
Get Payment Method Required Fields Response
Rapyd returns the following response. The fields in the response are described in Payment Method Type Object .
Response
{ "status": { "error_code": "", "status": "SUCCESS", "message": "", "response_code": "", "operation_id": "01ccc669-ca5d-4ff4-bc1e-88be05fae2cb" }, "data": { "type": "sg_credit_cup_card", "fields": [ { "name": "name", "type": "string", "regex": "", "is_required": true, "instructions": "card holder name" }, { "name": "number", "type": "string", "regex": "", "is_required": true, "instructions": "card number" }, { "name": "expiration_month", "type": "string", "regex": "", "is_required": true, "instructions": "expiration month as string, 01-12" }, { "name": "expiration_year", "type": "string", "regex": "", "is_required": true, "instructions": "expiration year in to digits as string, 18-99" }, { "name": "cvv", "type": "string", "regex": "", "is_required": true, "instructions": "card cvv" } ], "payment_method_options": [ { "name": "3d_required", "type": "boolean", "regex": "", "description": "Allows the client to determine whether the customer is required to complete 3DS authentication for the transaction", "is_required": false, "is_updatable": false } ], "payment_options": [ { "name": "capture", "type": "boolean", "regex": "", "description": "Determines when the payment is processed for capture.", "is_required": false, "is_updatable": false }, { "name": "complete_payment_url", "type": "string", "regex": "", "description": "the complete_payment_url field must be filled in.", "is_required": true, "is_updatable": false }, { "name": "error_payment_url", "type": "string", "regex": "", "description": "the error_payment_url field must be filled in.", "is_required": true, "is_updatable": false }, { "name": "statement_descriptor", "type": "string", "regex": "/^[a-zA-Z0-9]{0,22}/", "description": "A text description suitable for a customer's payment statement. Limited to 22 characters.", "is_required": false, "is_updatable": false } ], "minimum_expiration_seconds": 0, "maximum_expiration_seconds": 604800 } }
The response shows that this payment method does not require any specific fields or payment method options.
Note
Some payment methods require fields in the 'payment_options' array to appear in other contexts. For details, see the description of the fields in the response to 'Get Payment Method Required Fields'.
Create the customer's profile with all parameters required for a customer and for the payment method selected. For our example, we will use Create Customer with the following parameters:
Description of Body Parameters
Body Parameter | Description |
---|---|
name | Your customer's name. |
Your customer's email address. | |
payment_method | An object containing the following:
|
Note
If you are creating a card payment method and you do not have PCI clearance, you must create the customer without the payment method, then add the payment method using Create Card Token, then set that payment method as the default with Update Customer.
Create Customer Request
Request
// Request URL: post https://sandboxapi.rapyd.net/v1/customers // Message body { "name": "John Doe", "email": "johndoe@rapyd.net", "payment_method": { "type": "sg_credit_cup_card", "fields": { "number": "4111111111111111", "expiration_month": "10", "expiration_year": "23", "cvv": "123", "name": "John Doe" }, "complete_payment_url": "https://complete.rapyd.net/", "error_payment_url": "https://error.rapyd.net/" } }
.NET Core
using System; using System.Text.Json; namespace RapydApiRequestSample { class Program { static void Main(string[] args) { try { var requestObj = new { name = "John Doe", email = "johndoe@rapyd.net", payment_method = new Object[] { new { type = "sg_credit_cup_card", fields = new Object[] { new { number = "4111111111111111", expiration_month = "10", expiration_year = "23", cvv = "123", name = "John Doe" } } complete_payment_url = "https://complete.rapyd.net/", error_payment_url = "https://error.rapyd.net/" } } }; string request = JsonSerializer.Serialize(requestObj); string result = RapydApiRequestSample.Utilities.MakeRequest("POST", "/v1/customers", request); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine("Error completing request: " + e.Message); } } } }
JavaScript
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest; async function main() { try { const body = { name: 'John Doe', email: 'johndoe@rapyd.net', payment_method: [ { type: 'sg_credit_cup_card', fields: [ number: '4111111111111111', expiration_month: '10', expiration_year: '23', cvv: '123', name: 'John Doe' ], complete_payment_url: 'https://complete.rapyd.net/', error_payment_url: 'https://error.rapyd.net/' } ] }; const result = await makeRequest('POST', '/v1/customers', body); console.log(result); } catch (error) { console.error('Error completing request', error); } }
PHP
<?php $path = $_SERVER['DOCUMENT_ROOT']; $path .= "/<path-to-your-utility-file>/utilities.php"; include($path); $body = [ "name" => "John Doe", "email" => "johndoe@rapyd.net", "payment_method" => array(array( "type" => "sg_credit_cup_card", "fields" => array(array( "number" => "4111111111111111", "expiration_month" => "10", "expiration_year" => "23", "cvv" => "123", "name" => "John Doe" )), "complete_payment_url" => "https://complete.rapyd.net/", "error_payment_url" => "https://error.rapyd.net/" )) ]; try { $object = make_request('post', '/v1/customers', $body); var_dump($object); } catch (Exception $e) { echo "Error: $e"; } ?>
Python
from pprint import pprint from utilities import make_request customer = { "name": "John Doe", "email": "johndoe@rapyd.net", "payment_method": { "type": "sg_credit_cup_card", "fields": { "number": "4111111111111111", "expiration_month": "10", "expiration_year": "23", "cvv": "123", "name": "John Doe" }, "complete_payment_url": "https://complete.rapyd.net/", "error_payment_url": "https://error.rapyd.net/" } } result = make_request(method='post', path='/v1/customers', body=customer) pprint(result)
Create Customer Response
Rapyd returns the following response.
Response
{ "status": { "error_code": "", "status": "SUCCESS", "message": "", "response_code": "", "operation_id": "acc384b0-1430-4d7d-a2b0-327be9da975a" }, "data": { "id": "cus_81da79bf18af36e64b49c1c374faa524", "delinquent": false, "discount": null, "name": "John Doe", "default_payment_method": "card_c01d1b10f309884f381cfc499cdfb1ec", "description": "", "email": "johndoe@rapyd.net", "phone_number": "", "invoice_prefix": "", "addresses": [], "payment_methods": { "data": [ { "id": "card_c01d1b10f309884f381cfc499cdfb1ec", "type": "sg_credit_cup_card", "category": "card", "metadata": null, "image": "https://iconslib.rapyd.net/checkout/sg_credit_cup_card.png", "webhook_url": "", "supporting_documentation": "", "next_action": "3d_verification", "name": "John Doe", "last4": "1111", "acs_check": "unchecked", "cvv_check": "unchecked", "bin_details": { "type": null, "brand": null, "level": null, "country": null, "bin_number": "411111" }, "expiration_year": "23", "expiration_month": "10", "fingerprint_token": "ocfp_e599f990674473ce6283b245e9ad2467", "redirect_url": "https://sandboxcheckout.rapyd.net/3ds-payment?token=payment_178af04b589334ee6406eee7a430e028" } ], "has_more": false, "total_count": 1, "url": "/v1/customers/cus_81da79bf18af36e64b49c1c374faa524/payment_methods" }, "subscriptions": null, "created_at": 1668353979, "metadata": {}, "business_vat_id": "", "ewallet": "", "network_reference_id": 962926, "complete_payment_url": "https://complete.rapyd.net/", "error_payment_url": "https://error.rapyd.net/" } }
To define a product of type services, run Create Product with the following parameters:
Description of Body Parameters
Body Parameter | Description |
---|---|
name | Enter the name of your product, Acme Music Stream. |
type | Enter services . |
Create Product Request
Request
// Request URL: POST https://sandboxapi.rapyd.net/v1/products // Message body: { "name": "Acme Music Stream", "type": "services" }
.NET Core
using System; using System.Text.Json; namespace RapydApiRequestSample { class Program { static void Main(string[] args) { try { var requestObj = new { name = "Acme Music Stream", type = "services", }; string request = JsonSerializer.Serialize(requestObj); string result = RapydApiRequestSample.Utilities.MakeRequest("POST", "/v1/products", request); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine("Error completing request: " + e.Message); } } } }
JavaScript
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest; async function main() { try { const body = { name: 'Acme Music Stream', type: 'services' }; const result = await makeRequest('POST', '/v1/products', body); console.log(result); } catch (error) { console.error('Error completing request', error); } }
PHP
<?php $path = $_SERVER['DOCUMENT_ROOT']; $path .= "/<path-to-your-utility-file>/utilities.php"; include($path); $body = [ "name" => "Acme Music Stream", "type" => "services" ]; try { $object = make_request('post', '/v1/products', $body); var_dump($object); } catch (Exception $e) { echo "Error: $e"; } ?>
Python
from pprint import pprint from utilities import make_request product = { "name": "Acme Music Stream", "type": "services" } results = make_request(method='post', path=f'/v1/products', body=product) pprint(results)
Create Product Response
Rapyd returns the following response.
Response
{ "status": { "error_code": "", "status": "SUCCESS", "message": "", "response_code": "", "operation_id": "1f5c173f-fc9a-4d11-9fd3-de91419b5ab7" }, "data": { "id": "product_3f22f9ef6eb18894e95127e5bb8e0c9d", "active": true, "attributes": [], "created_at": 1668432691, "description": "", "images": [], "metadata": {}, "name": "Acme Music Stream", "package_dimensions": { "height": 0, "length": 0, "weight": 0, "width": 0 }, "shippable": false, "skus": [], "statement_descriptor": "", "type": "services", "unit_label": "", "updated_at": 1668432691 } }
The data
section of this response shows that:
The product
id
for your product is product_3f22f9ef6eb18894e95127e5bb8e0c9d. When you run this example in your own sandbox, you will get a different ID, which you will need for the next step.The product
name
is Acme Music Stream.The product
type
is services.
The plan defines the pricing structure for your product. You can define different plans for the same product, for example, basic or premium, with different rates. For this use case, run Create Plan with the following parameters:
Description of Body Parameters
Body Parameter | Description |
---|---|
amount | Enter 3.00 as the monthly amount for the plan. |
currency | Enter SGD as the currency code for Singapore dollar. |
interval | Enter month as the billing cycle interval. |
product | Enter the ID that you received when you created the product in your sandbox. In this instance, we are using product_3f22f9ef6eb18894e95127e5bb8e0c9d, which is for the product we created in our sandbox. |
nickname | Enter Basic Streaming as the name of the plan. |
usage_type | Enter licensed as the usage type. The customer is billed a flat rate, even when the service is not used. For other options, see Create Plan. |
Create Plan Request
Request
// Request URL: POST https://sandboxapi.rapyd.net/v1/plans // Message body { "currency": "SGD", "interval": "month", "product": "product_3f22f9ef6eb18894e95127e5bb8e0c9d", "amount": 3, "nickname": "Basic Streaming", "usage_type": "licensed" }
.NET Core
using System; using System.Text.Json; namespace RapydApiRequestSample { class Program { static void Main(string[] args) { try { var requestObj = new { currency = "SGD", interval = "month", product = "product_3f22f9ef6eb18894e95127e5bb8e0c9d", amount = 3, nickname = "Basic Streaming", usage_type = "licensed", }; string request = JsonSerializer.Serialize(requestObj); string result = RapydApiRequestSample.Utilities.MakeRequest("POST", "/v1/plans", request); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine("Error completing request: " + e.Message); } } } }
JavaScript
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest; async function main() { try { const body = { currency: 'SGD', interval: 'month', product: 'product_3f22f9ef6eb18894e95127e5bb8e0c9d', amount: 3, nickname: 'Basic Streaming', usage_type: 'licensed' }; const result = await makeRequest('POST', '/v1/plans', body); console.log(result); } catch (error) { console.error('Error completing request', error); } }
PHP
<?php $path = $_SERVER['DOCUMENT_ROOT']; $path .= "/<path-to-your-utility-file>/utilities.php"; include($path); $body = [ "currency" => "SGDSGD", "interval" => "month", "product" => "product_3f22f9ef6eb18894e95127e5bb8e0c9d", "amount" => 3, "nickname" => "Basic Streaming", "usage_type" => "licensed" ]; try { $object = make_request('post', '/v1/plans', $body); var_dump($object); } catch (Exception $e) { echo "Error: $e"; } ?>
Python
from pprint import pprint from utilities import make_request # Create Plan request plan = { "currency": "SGD", "interval": "month", "product": "product_3f22f9ef6eb18894e95127e5bb8e0c9d", "amount": 3, "nickname": "Basic Streaming", "usage_type": "licensed" } result = make_request(method='post', path='/v1/plans', body=plan) pprint(result)
Create Plan Response
Rapyd returns the following response.
Response
{ "status": { "error_code": "", "status": "SUCCESS", "message": "", "response_code": "", "operation_id": "935d04de-51b9-4869-a68c-76692ce5387a" }, "data": { "id": "plan_5487c8a5be1dd847de7da4ce8feebfab", "aggregate_usage": "sum", "amount": 3, "billing_scheme": "per_unit", "created_at": 1668432810, "currency": "SGD", "interval": "month", "interval_count": 1, "metadata": {}, "product": { "id": "product_3f22f9ef6eb18894e95127e5bb8e0c9d", "active": true, "attributes": [], "created_at": 1668432691, "description": "", "images": [], "metadata": {}, "name": "Acme Music Stream", "package_dimensions": { "height": 0, "length": 0, "weight": 0, "width": 0 }, "shippable": false, "skus": [], "statement_descriptor": "", "type": "services", "unit_label": "", "updated_at": 1668432691 }, "nickname": "Basic Streaming", "tiers": [], "tiers_mode": "", "transform_usage": { "divide_by": 1, "round": "up" }, "trial_period_days": 0, "usage_type": "licensed" } }
The data section of this response shows that Rapyd created an ID for the Basic Streaming plan and linked it to the product. The ID of the plan is plan_5487c8a5be1dd847de7da4ce8feebfab. When you run this example in your own sandbox, you get a different ID, which you will need for the next step.
The final step in the process is creating the subscription itself. Here, you link all the required elements together: (customer, product, the plan) and set the subscription to continue indefinitely. To make the subscription terminate at a specific time, see Subscription. This use case uses the API, but you can create the subscription with a hosted page. See Create Subscription by Create Subscription by Hosted Page.
Run Create Subscription with the following parameters:
Description of Body Parameters
Body Parameter | Description |
---|---|
customer | Enter the ID that you received when you created the customer in your sandbox. In this instance, we are using cus_81da79bf18af36e64b49c1c374faa524, which is the ID of the customer we created in our sandbox. Because we are not explicitly mentioning a payment method, the API will use the customer's default payment method. To use a payment method other than the default, configure |
billing | Enter pay_automatically . |
subscription_items | Enter an array that contains only one object. The object contains the following fields:
|
Create Subscription Request
Request Rapyd to create a subscription for your customer.
Request
// Request URL: POST /v1/payments/subscriptions/ // Message body: { "customer": "cus_81da79bf18af36e64b49c1c374faa524", "billing": "pay_automatically", "subscription_items": [ { "plan": "plan_5487c8a5be1dd847de7da4ce8feebfab", "quantity": 1 } ] }
.NET Core
using System; using System.Text.Json; namespace RapydApiRequestSample { class Program { static void Main(string[] args) { try { var requestObj = new { customer = "cus_81da79bf18af36e64b49c1c374faa524", billing = "pay_automatically", subscription_items = new Object[] { new { plan = "plan_5487c8a5be1dd847de7da4ce8feebfab", quantity = 1 } } }; string request = JsonSerializer.Serialize(requestObj); string result = RapydApiRequestSample.Utilities.MakeRequest("POST", "/v1/payments/subscriptions", request); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine("Error completing request: " + e.Message); } } } }
JavaScript
const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest; async function main() { try { const body = { customer: 'cus_81da79bf18af36e64b49c1c374faa524', billing: 'pay_automatically', subscription_items: [ { plan: 'plan_5487c8a5be1dd847de7da4ce8feebfab', quantity: 1 } ] }; const result = await makeRequest('POST', '/v1/payments/subscriptions', body); console.log(result); } catch (error) { console.error('Error completing request', error); } }
PHP
<?php $path = $_SERVER['DOCUMENT_ROOT']; $path .= "/<path-to-your-utility-file>/utilities.php"; include($path); $body = [ "customer" => "cus_81da79bf18af36e64b49c1c374faa524", "billing" => "pay_automatically", "subscription_items" => array(array( "plan" => "plan_5487c8a5be1dd847de7da4ce8feebfab", "quantity" => 1 )) ]; try { $object = make_request('post', '/v1/payments/subscriptions', $body); var_dump($object); } catch (Exception $e) { echo "Error: $e"; } ?>
Python
from pprint import pprint from utilities import make_request subscription = { "customer": "cus_81da79bf18af36e64b49c1c374faa524", "billing": "pay_automatically", "subscription_items": [ { "plan": "plan_5487c8a5be1dd847de7da4ce8feebfab", "quantity": 1 } ] } result = make_request(method='post', path='/v1/payments/subscriptions', body=subscription) pprint(result)
Create Subscription Response
Rapyd returns the following response.
Response
{ "status": { "error_code": "", "status": "SUCCESS", "message": "", "response_code": "", "operation_id": "423028d6-5bc5-429d-9d59-049a3967ccfa" }, "data": { "id": "sub_c1388d28c46c4cf853655a5a822e5e46", "billing": "pay_automatically", "billing_cycle_anchor": 1668432892, "created_at": 1668432892, "customer_token": "cus_81da79bf18af36e64b49c1c374faa524", "days_until_due": 30, "metadata": {}, "tax_percent": 0, "cancel_at_period_end": false, "canceled_at": null, "current_period_end": 1671024892, "current_period_start": 1668432892, "discount": null, "ended_at": null, "subscription_items": { "data": [ { "id": "subi_b4b55ddb6c854be912cceeb4d95ed1a4", "created": 1668432892, "metadata": null, "quantity": 1, "plan": { "id": "plan_5487c8a5be1dd847de7da4ce8feebfab", "aggregate_usage": "sum", "amount": 3, "billing_scheme": "per_unit", "created_at": 1668432810, "currency": "SGD", "interval": "month", "interval_count": 1, "metadata": {}, "product": "product_3f22f9ef6eb18894e95127e5bb8e0c9d", "nickname": "Basic Streaming", "tiers": [], "tiers_mode": "", "transform_usage": { "divide_by": 1, "round": "up" }, "trial_period_days": 0, "usage_type": "licensed" } } ], "has_more": false, "total_count": 0, "url": "/v1/subscription_items?subscription=sub_c1388d28c46c4cf853655a5a822e5e46" }, "status": "active", "trial_end": null, "trial_start": null, "payment_method": "card_c01d1b10f309884f381cfc499cdfb1ec", "payment_fields": null, "payout_fields": null, "type": "payment" } }
The data section of this response shows:
The
id
of the subscription is sub_c1388d28c46c4cf853655a5a822e5e46. When you run this example in your own sandbox, you will get a different ID.The customer's payment method will be charged 3.00 SGD every month until the subscription is canceled.