> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.qfapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription API Reference

> This page lists the API reference for creating, updating, and managing recurring (subscription) payment resources.

This page documents the available API endpoints for recurring payments. Make sure you have read the [Recurring Overview](/integration/online-shop/integration-by-use-case/recurring-payments/recurring-overview) before using these APIs.

***

## 1. Create Customer

**POST** `/customer/v1/create`

Creates a new customer profile.

### Request Parameters

| Parameter         | Type          | Required | Description                    |
| ----------------- | ------------- | -------- | ------------------------------ |
| `name`            | String        | No       | Customer name                  |
| `phone`           | String        | No       | Contact number                 |
| `email`           | String        | No       | Email address                  |
| `billing_address` | String (JSON) | No       | JSON string of billing address |

### Response

Returns the `customer_id`.

***

## 2. Update Customer

**POST** `/customer/v1/update`

Updates an existing customer.

### Request Parameters

| Parameter         | Type   | Required | Description                    |
| ----------------- | ------ | -------- | ------------------------------ |
| `customer_id`     | String | Yes      | QFPay system customer ID       |
| `name`            | String | No       | Customer name                  |
| `phone`           | String | No       | Contact number                 |
| `email`           | String | No       | Email address                  |
| `billing_address` | JSON   | No       | JSON object of billing address |

### Response

Returns number of affected rows.

***

## 3. Query Customers

**POST** `/customer/v1/query`

Search for customers.

### Request Parameters

| Parameter     | Type   | Required | Description             |
| ------------- | ------ | -------- | ----------------------- |
| `customer_id` | String | No       | Customer ID             |
| `name`        | String | No       | Customer name           |
| `phone`       | String | No       | Contact number          |
| `email`       | String | No       | Email address           |
| `page`        | Int    | No       | Default = 1             |
| `page_size`   | Int    | No       | Default = 10, max = 100 |

### Response

List of matching customers.

***

## 4. Delete Customer

**POST** `/customer/v1/delete`

Deletes a customer. This action is irreversible.

### Request Parameters

| Parameter     | Type   | Required | Description           |
| ------------- | ------ | -------- | --------------------- |
| `customer_id` | String | Yes      | Customer ID to delete |

### Response

Returns deleted customer ID and row count.

***

## 5. Create Product

**POST** `/product/v1/create`

Creates a recurring billing product.

### Request Parameters

| Parameter        | Type   | Required | Description                              |
| ---------------- | ------ | -------- | ---------------------------------------- |
| `name`           | String | Yes      | Product name                             |
| `type`           | String | Yes      | Must be `recurring`                      |
| `description`    | String | No       | Product description                      |
| `txamt`          | Int    | Yes      | Amount in cents (100 = \$1)              |
| `txcurrcd`       | String | Yes      | Currency (e.g. HKD)                      |
| `interval`       | String | Yes      | Billing cycle: `monthly`, `yearly`, etc. |
| `interval_count` | Int    | Yes      | Interval count (e.g. 1 month = 1)        |
| `usage_type`     | String | Yes      | Must be `licensed`                       |

<Note>
  In the sandbox environment, `minutes` and `hours` can be used in the `interval` field for testing purposes.
</Note>

### Response

Returns generated `product_id`.

***

## 6. Update Product

**POST** `/product/v1/update`

Updates product metadata.

### Request Parameters

| Parameter     | Type   | Required | Description          |
| ------------- | ------ | -------- | -------------------- |
| `product_id`  | String | Yes      | Product ID to update |
| `name`        | String | No       | New name             |
| `description` | String | No       | New description      |

### Response

Returns number of affected rows.

***

## 7. Query Products

**POST** `/product/v1/query`

Search for products.

### Request Parameters

| Parameter     | Type   | Required | Description             |
| ------------- | ------ | -------- | ----------------------- |
| `product_id`  | String | No       | Product ID              |
| `name`        | String | No       | Product name            |
| `description` | String | No       | Description             |
| `txcurrcd`    | String | No       | Currency                |
| `interval`    | String | No       | `monthly` / `yearly`    |
| `page`        | Int    | No       | Default = 1             |
| `page_size`   | Int    | No       | Default = 10, max = 100 |

### Response

List of matching products.

***

## 8. Delete Product

**POST** `/product/v1/delete`

Deletes a product (must not be linked to active subscriptions).

### Request Parameters

| Parameter    | Type   | Required | Description          |
| ------------ | ------ | -------- | -------------------- |
| `product_id` | String | Yes      | Product ID to delete |

### Response

Returns deleted product ID and row count.

***

## 9. Create Subscription

<Tip>
  You must create `customer_id`, `product_id`, and `token_id` before calling the subscription API.
</Tip>

**POST** `/subscription/v1/create`

Creates a recurring subscription.

### Request Parameters

| Parameter              | Type   | Required | Description                               |
| ---------------------- | ------ | -------- | ----------------------------------------- |
| `customer_id`          | String | Yes      | Linked customer ID                        |
| `token_id`             | String | Yes      | Linked payment token                      |
| `products`             | List   | Yes      | Product ID and quantity                   |
| `total_billing_cycles` | Int    | No       | Total billing periods (null = indefinite) |
| `start_time`           | String | No       | ISO timestamp to start subscription       |

### Products Object

| Attribute    | Type   | Required | Description               |
| ------------ | ------ | -------- | ------------------------- |
| `product_id` | String | Yes      | Unique product identifier |
| `quantity`   | Int    | No       | Default = 1               |

### Example Request

```json theme={null}
{
  "products": [
    {
      "product_id": "prod_54c3772d******9a54b236e09ec74f",
      "quantity": 1
    }
  ],
  "customer_id": "cust_aaf6aae94******982c54c9cae5ba32",
  "token_id": "tk_a99892fd*********d3417d168a18bb",
  "total_billing_cycles": 2,
  "start_time": "2020-05-14 12:32:56"
}
```

### Response (data field)

| Attribute         | Type   | Description                         |
| ----------------- | ------ | ----------------------------------- |
| `subscription_id` | String | Unique subscription identifier      |
| `state`           | String | `ACTIVE`, `INCOMPLETE`, `COMPLETED` |

***

## 10. Update Subscription

**POST** `/subscription/v1/update`

### Request Parameters

| Attribute              | Type   | Required | Description             |
| ---------------------- | ------ | -------- | ----------------------- |
| `subscription_id`      | String | Yes      | Unique subscription ID  |
| `total_billing_cycles` | Int    | No       | Null = indefinite       |
| `start_time`           | String | No       | First billing time      |
| `token_id`             | String | No       | Payment token           |
| `products`             | Object | No       | List of product objects |

### Response (data field)

| Attribute         | Type   | Description               |
| ----------------- | ------ | ------------------------- |
| `subscription_id` | String | Subscription ID           |
| `rowAffected`     | Int    | Number of records updated |

***

## 11. Query Subscription

**POST** `/subscription/v1/query`

### Request Parameters

| Attribute         | Type   | Required | Description                 |
| ----------------- | ------ | -------- | --------------------------- |
| `page`            | Int    | No       | Default = 1                 |
| `page_size`       | Int    | No       | Default = 10, max = 100     |
| `subscription_id` | String | No       | Subscription ID             |
| `customer_id`     | String | No       | Customer ID                 |
| `state`           | String | No       | e.g. `INCOMPLETE`, `ACTIVE` |

### Sample Response

```json theme={null}
{
  "resperr": "success",
  "respcd": "0000",
  "respmsg": "success",
  "data": [
    {
      "subscription_id": "sub_e120378de*******da066f690da75",
      "customer_id": "cust_5ba1539f*******c9bda11d12c854e36",
      "token_id": "tk_9ac510017*******69b614e8f7ee",
      "state": "ACTIVE",
      "total_billing_cycles": 3,
      "completed_iteration": 1,
      "last_billing_time": "2024-11-21T11:12:06Z",
      "next_billing_time": "2024-11-21T11:13:06Z",
      "products": [
        { "product_id": "prod_8efecd0bd******b9aa1ec5ec01", "quantity": 1 }
      ]
    }
  ]
}
```

***

## 12. Cancel Subscription

**POST** `/subscription/v1/cancel`

### Request Parameters

| Attribute         | Type   | Required | Description     |
| ----------------- | ------ | -------- | --------------- |
| `subscription_id` | String | Yes      | Subscription ID |

***

## 13. Query Subscription Orders

**POST** `/subscription/billing_order/v1/list`

### Request Parameters

| Attribute         | Type   | Required | Description             |
| ----------------- | ------ | -------- | ----------------------- |
| `subscription_id` | String | Yes      | Subscription ID         |
| `page`            | Int    | No       | Default = 1             |
| `page_size`       | Int    | No       | Default = 10, max = 100 |

### Response (data field)

| Attribute               | Type   | Description                                |
| ----------------------- | ------ | ------------------------------------------ |
| `subscription_order_id` | String | Format: `sub_ord_{subscription_id}_{0001}` |
| `subscription_id`       | String | Parent subscription                        |
| `trigger_by`            | String | `auto` or `manual`                         |
| `sequence_no`           | Int    | Billing iteration number                   |

***

## 14. Manual Charge Subscription

**POST** `/subscription/v1/charge`

### Request Parameters

| Attribute               | Type   | Required | Description             |
| ----------------------- | ------ | -------- | ----------------------- |
| `subscription_id`       | String | Yes      | Subscription ID         |
| `subscription_order_id` | String | No       | Specific order to retry |

<Note>
  This API is only valid for subscriptions with failed billing and state `UNPAID`, `INCOMPLETE`, or `PAST_DUE`.

  * If manual charge occurs **before** next billing time → subscription remains `ACTIVE`
  * If manual charge occurs **after** next billing time → subscription will be cancelled
  * If manual charge fails → subscription state remains unchanged
</Note>

***
