---
title: "Subscriptions"
source_url: https://docs.rapyd.net/en/subscriptions-369196.html
lang: en
---

# 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](https://docs.rapyd.net/en/create-plan.md "Create Plan").
- For periodic billing with a fixed end date, see [Create Subscription](https://docs.rapyd.net/en/create-subscription.md "Create Subscription").

A customer would like to use your digital service, Acme Music, in Singapore. The cost is 3 Singapore dollars per month, indefinitely.

### Subscriptions Overview

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.

### Selecting a Payment Method and Customer Profile Workflow

Let’s look at the highlights of your workflow.

> **Tip:**
>
> 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

![643e7dbfb8223.png](image/img-7de394478ca54e67ed1f71c9974abd5e.png)

1. Your website queries Rapyd for the payment methods available in Singapore.
2. Rapyd returns a list of payment methods.
3. Your website offers a list of choices to your customer.

### Part 2 - Create a Customer Profile

![643e7dc13588f.png](image/img-4d9a23a3ffa17d92fda5c966704e0baf.png)

1. The customer selects your product and a payment method.
2. Your website back end asks Rapyd to create a customer profile.
3. Rapyd creates the profile and assigns a unique ID.

### Subscription Creation Workflow

### Step 1 - Create a Product

![643e7dc299474.png](image/img-353f9083bae757eaed94f3e4abc87833.png)

1. You define the product you are providing.
2. Your website back end asks Rapyd to create a product of type 'service'.
3. Rapyd creates the product and returns a Product ID.

### Step 2 - Create a Plan

![643e7dc3c28d2.png](image/img-1573f883e9117051844f0cb8ec7f9d8b.png)

1. You determine the pricing structure you want for the recurring payment.
2. Your website back end asks Rapyd to create the plan.
3. Rapyd creates the plan and returns a Plan ID.

### Step 3 - Create the Subscription

![643e7dc5213bb.png](image/img-155a6628c21e4b58f14ff8025c16ad3e.png)

1. You decide the parameters you need for the recurring payment.
2. Your website back end asks Rapyd to create a subscription for the customer.
3. 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.

### Subscription Message Sequences

The message sequence diagrams below describe how information is exchanged between Rapyd, the merchant, and the card network.

Create Subscription

![subscription-with-automatic-capture-of-card-payment.svg](image/img-002e3068e072f72bfdf40df707ee149e.svg)

### How Subscriptions Work

> **Note:**
>
> If you already have a customer with a payment method, you can skip to Create Product.

### Find Payment Methods

First, you need to determine which Singaporean payment methods support payments in Singapore dollars (SGD). Run [List Payment Methods by Country](https://docs.rapyd.net/en/list-payment-methods-by-country.md "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&currency=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}&currency={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&currency=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&currency=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}&currency={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](https://docs.rapyd.net/en/payment-method-type.md "Payment Method Type") .

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

### Get Required Fields

Each payment method has its own requirements. To determine what information the customer needs to provide, run [Get Payment Method Required Fields](https://docs.rapyd.net/en/get-payment-method-required-fields.md "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](https://docs.rapyd.net/en/payment-method-type.md "Payment Method Type") .

- - 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 Customer Profile

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](https://docs.rapyd.net/en/create-customer.md "Create Customer") with the following parameters:

Description of Body Parameters

| Body Parameter | Description |
| --- | --- |
| name | Your customer's name. |
| email | Your customer's email address. |
| payment_method | An object containing the following:  - `type` - string - The code for the payment method, in this case, **sg_credit_cup_card**. - `fields` - object - The fields required for the payment method, as shown in the  `fields` array in the response to [Get Payment Method Required Fields](https://docs.rapyd.net/en/get-payment-method-required-fields.md "Get Payment Method Required Fields"). |

> **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](https://docs.rapyd.net/en/create-card-token.md "Create Card Token"), then set that payment method as the default with [Update Customer](https://docs.rapyd.net/en/update-customer.md "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/"
          }
      }
      ```

### Create Product

To define a product of type **services**, run [Create Product](https://docs.rapyd.net/en/create-product.md "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**.

### Create Plan

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](https://docs.rapyd.net/en/create-plan.md "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](https://docs.rapyd.net/en/create-plan.md "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.

### Create Subscription

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](https://docs.rapyd.net/en/subscription-364807.md "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](https://docs.rapyd.net/en/create-subscription-by-hosted-page.md "Create Subscription by Hosted Page").

Run [Create Subscription](https://docs.rapyd.net/en/create-subscription.md "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 `payment_method`. See [Subscription](https://docs.rapyd.net/en/subscription-364807.md "Subscription"). |
| billing | Enter **pay_automatically** . |
| subscription_items | Enter an array that contains only one object. The object contains the following fields:  - `plan` - Enter the plan 'id' that you received when you created the plan in your sandbox. In this instance, we are using **plan_5487c8a5be1dd847de7da4ce8feebfab**, which is the plan ID we created for our sandbox. - `quantity` - Enter **1**, since your customer is subscribing to one instance of this plan (for example). |

### 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.
