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

# List available subscription templates

> Lists subscription templates available to the authorized merchant and specified business. Only ACTIVE, enabled, non-tiered templates other than By agreement are returned, ordered by creation time descending. Price filters apply to the latest template price. Callers must ensure each range starts at or below its end.

The list provides candidate templates. Subscription creation still validates pricing, enabled charge segments and required dates, and returns a business error if the selected template cannot be used.

All examples illustrate request and response formats. Replace customers, orders, cards and accounts with approved test data. BASE_URL is the service root domain without /api/v2. ACCESS_TOKEN is the access_token returned by /oauth/token. Example dates are in 2030; replace them with actual dates that satisfy the current date restrictions.



## OpenAPI

````yaml /openapi/billbuddy-v2-openapi.en.yaml get /api/v2/plan/list
openapi: 3.0.3
info:
  title: BillBuddy API Integration Guide
  version: 2.0.0
  description: >
    BillBuddy API integration guide. It covers authentication, transaction and
    subscription endpoints called by third-party servers. Request and response
    examples contain complete fictional business data and tokens generated
    offline; they cannot authenticate or initiate real transactions.


    ## Getting started

    1. Obtain your Client ID, Client Secret, merchant identifier and business
    identifier from BillBuddy. If an IP allowlist applies, send requests from an
    approved fixed outbound IP address.

    2. Obtain an access_token through POST /oauth/token. Business requests
    require Authorization: Bearer {access_token} and Accept: application/json.
    Use Content-Type: application/json for JSON requests and form encoding for
    token requests.

    3. Call the payment or subscription endpoints as needed. Customers open the
    hosted activation page through activation_url. Store the Client Secret only
    on your server.


    ## Identifiers and amounts

    OAuth credentials identify the merchant; business_id is not a request
    parameter. Endpoints that require a business use merchant_id. For
    single-transaction and batch-result lookups, merchant_id is optional; omit
    it or leave it empty to search all businesses of the authenticated merchant.
    The transaction list uses optional, case-sensitive Mid; omit it to query all
    businesses belonging to the authenticated merchant. A requested business
    must belong to that merchant. Read response identifiers according to each
    endpoint's field definitions.

    TXT file amounts, amount_cents and declared_total_amount_cents use cents.
    Other amounts use major currency units with at most two decimal places:
    10.50 means AUD 10.50. Use strings for bank account numbers, card numbers,
    months, years and postcodes to preserve leading zeros.


    ## Success and failure

    Business JSON responses use code=0 for success and code=1 for ordinary
    failures. Transaction and subscription validation failures usually return
    code=400 and data={} with HTTP 200. V2 business endpoint authentication
    failures use code=1. A missing, malformed or inaccessible business
    merchant_id for plan/list return code=1. HTTP 429 indicates a rate limit.
    The OAuth endpoint uses standard OAuth responses with HTTP 200/400/401/429.

    code=0 means the API request was processed successfully; assess the payment
    outcome separately. Batch accepted means the request was accepted for
    asynchronous processing. Bank Pending, scheduled Pending and outstanding 3DS
    authentication do not indicate payment success. Transactions, DDR
    subscriptions and payment schedules use different status enumerations; refer
    to their field definitions.


    ## Dates and frequencies

    Use YYYY-MM-DD for request dates. Today and tomorrow are evaluated in
    Australia/Sydney, including daylight saving time. Scheduled cancellations
    also use Australia/Sydney: cancellation must occur strictly before 08:15 on
    the processing date; it is no longer permitted at that time. Payment
    complete_date and checkout expires_at use DD/MM/YYYY HH:mm:ss. Refer to
    individual fields for other formats.

    Standard RRULE examples: Daily FREQ=DAILY;INTERVAL=1; Weekly
    FREQ=WEEKLY;INTERVAL=1;BYDAY=MO; Fortnightly
    FREQ=WEEKLY;INTERVAL=2;BYDAY=MO; Monthly
    FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15; Quarterly
    FREQ=MONTHLY;INTERVAL=3;BYMONTHDAY=15; Half Yearly
    FREQ=MONTHLY;INTERVAL=6;BYMONTHDAY=15; Yearly
    FREQ=YEARLY;INTERVAL=1;BYMONTH=2;BYMONTHDAY=15. Weekday abbreviations are
    MO/TU/WE/TH/FR/SA/SU. Weekly/Monthly rules without a specific debit day
    derive it from the start date. A single BYDAY=SA or SU is treated as Monday;
    a weekend start date without an explicit debit day is also treated as
    Monday. A single BYMONTHDAY=29/30/31 falls on the last day of shorter
    months; BYMONTHDAY=-1 means the last day of the month. All rules must be
    valid RRULE expressions.

    For a nonstandard frequency such as every 10 days, provide process_type=12,
    custom_cycle_type=1, custom_cycle=10 and
    day_of_debit=FREQ=DAILY;INTERVAL=10. Units 1/2/3/4 correspond to
    DAILY/WEEKLY/MONTHLY/YEARLY. The minimum interval is 5 for days and 1 for
    other units. INTERVAL must equal custom_cycle. Quarterly, half-yearly and
    yearly schedules also require day_of_debit_dtstart. Its complete date must
    be strictly after the start_date of the same schedule segment and within one
    billing cycle after it. The first actual debit date for createSchedule
    depends on the DDR start date, debit frequency and the requirement that it
    be no earlier than tomorrow.


    ## Using examples

    Schemas define types, nullability, lengths, enumerations and numeric ranges.
    Field descriptions define conditional requirements, dates and business
    restrictions. Use both together. Set BASE_URL, ACCESS_TOKEN, CLIENT_ID and
    CLIENT_SECRET before running curl examples. BillBuddy provides the actual
    test and production domains. Replace example customers, orders, cards,
    accounts and dates with values permitted in your test environment and
    satisfying the date restrictions.


    ## Hosted subscription integration

    Call POST /api/v2/subscription/create, then use the complete activation_url
    unchanged for a browser redirect or an iframe src. Alternatively, use
    activation_html as the iframe srcdoc. Customers enter payment information,
    authorize debits and activate the subscription on the BillBuddy-hosted page.
    Use the full returned URL; do not construct it yourself or parse its
    credentials. Keep the Client Secret and access_token on your server; never
    include them in iframe URLs or page contents.


    Recurring and By agreement subscriptions must be activated before
    start_date. One-off-only subscriptions must be submitted for activation
    within 30 days of creation. An accessible page does not guarantee submission
    is still permitted; the activation response is authoritative.


    ## Example data conventions

    Example merchants, customers, orders, payment tokens, session links and
    OAuth credentials are fictional and cannot be used for real requests. Card
    numbers are standard test card numbers; bank accounts are fictional. Email
    addresses use the reserved example.com domain, and phone numbers use
    Australian numbers reserved for examples. Replace BASE_URL, ACCESS_TOKEN,
    CLIENT_ID and CLIENT_SECRET with actual values from your approved test
    environment. Empty strings, null, empty arrays, 0 and false represent
    meaningful API states in some examples and must not be replaced
    indiscriminately.

    Payment response signatures are calculated offline according to the signing
    rules for each payment scenario, using the public demo key
    bb_docs_demo_signing_key_2030. The html field is excluded for responses
    awaiting 3DS authentication. This key is for documentation only and cannot
    sign or authenticate real requests.


    ## TXT batch transactions

    Upload fixed-width TXT files using multipart/form-data. File amounts,
    amount_cents and declared_total_amount_cents use cents, excluding
    surcharges; see “Upload a TXT transaction file” for the format and example
    file. Upload success only confirms acceptance. Retain batch_id and
    file_identifier and use the batch result endpoint to check individual
    outcomes. Batch completed does not mean every payment succeeded. Use OAuth
    credentials for the same merchant to query results. merchant_id is optional;
    when supplied, it must match the business identifier in the original upload.
    Response identifiers follow the definitions for each endpoint.


    ## Request examples by programming language

    Examples are provided in cURL, Python, JavaScript, PHP, Go, Java and Ruby,
    with the same business scenarios available in each language. Each example
    preserves the parameters and types from its corresponding cURL scenario.


    Requirements: cURL; Python 3.9+ (standard library); JavaScript with Node.js
    18+, saved as an .mjs file; PHP 8+ with the cURL extension; Go 1.20+; Java
    11+ (save the Example class as Example.java); Ruby 3+ (standard library).


    Set BASE_URL before running examples. Business endpoints also require
    ACCESS_TOKEN; token requests require CLIENT_ID and CLIENT_SECRET. BASE_URL
    is the API root without /api/v2. TXT upload examples read payments.txt from
    the current directory. Replace fictional values with approved test data and
    assess the response code and business status separately.
servers:
  - url: https://staging-api.billbuddyhq.com
    description: Staging environment
security:
  - oauth2: []
tags:
  - name: Authentication
    description: OAuth2 Client Credentials。
  - name: Transactions
    description: Single payments, batch payments and scheduled payment cancellations.
  - name: Subscriptions
    description: >-
      Subscription templates, hosted subscription creation, DDR creation and
      activation, and payment schedule submission.
paths:
  /api/v2/plan/list:
    get:
      tags:
        - Subscriptions
      summary: List available subscription templates
      description: >-
        Lists subscription templates available to the authorized merchant and
        specified business. Only ACTIVE, enabled, non-tiered templates other
        than By agreement are returned, ordered by creation time descending.
        Price filters apply to the latest template price. Callers must ensure
        each range starts at or below its end.


        The list provides candidate templates. Subscription creation still
        validates pricing, enabled charge segments and required dates, and
        returns a business error if the selected template cannot be used.


        All examples illustrate request and response formats. Replace customers,
        orders, cards and accounts with approved test data. BASE_URL is the
        service root domain without /api/v2. ACCESS_TOKEN is the access_token
        returned by /oauth/token. Example dates are in 2030; replace them with
        actual dates that satisfy the current date restrictions.
      operationId: v2PlanList
      parameters:
        - name: merchant_id
          in: query
          required: true
          description: >-
            Required business identifier assigned by BillBuddy, up to 20
            characters; must belong to the merchant associated with the OAuth
            credentials.
          schema:
            type: string
            description: >-
              Required business identifier assigned by BillBuddy, up to 20
              characters; must belong to the merchant associated with the OAuth
              credentials.
            maxLength: 20
        - name: page
          in: query
          required: false
          description: Page number. Defaults to 1.
          schema:
            type: integer
            description: Page number. Defaults to 1.
            minimum: 1
            nullable: true
            default: 1
        - name: page_size
          in: query
          required: false
          description: Items per page. Defaults to 20; no maximum is specified.
          schema:
            type: integer
            description: Items per page. Defaults to 20; no maximum is specified.
            minimum: 1
            nullable: true
            default: 20
        - name: name
          in: query
          required: false
          description: Partial match on the template name.
          schema:
            type: string
            description: Partial match on the template name.
            nullable: true
            maxLength: 255
        - name: frequency
          in: query
          required: false
          description: >-
            Template debit frequency: 1 One-off, 3 Weekly, 4 Fortnightly, 5
            Monthly, 6 Quarterly, 7 Half Yearly, 8 Yearly, 12 Custom.
          schema:
            type: integer
            description: >-
              Template debit frequency: 1 One-off, 3 Weekly, 4 Fortnightly, 5
              Monthly, 6 Quarterly, 7 Half Yearly, 8 Yearly, 12 Custom.
            nullable: true
            enum:
              - 1
              - 3
              - 4
              - 5
              - 6
              - 7
              - 8
              - 12
              - null
        - name: min_price
          in: query
          required: false
          description: >-
            Minimum latest template price. Amounts use major currency units, for
            example 10.50 means AUD 10.50, with at most two decimal places.
            Numbers and numeric strings are accepted, with a minimum of 0; the
            same range applies to both types.
          schema:
            oneOf:
              - type: number
                multipleOf: 0.01
                minimum: 0
                nullable: true
              - type: string
                pattern: ^\d+(\.\d{1,2})?$
            description: >-
              Minimum latest template price. Amounts use major currency units,
              for example 10.50 means AUD 10.50, with at most two decimal
              places. Numbers and numeric strings are accepted, with a minimum
              of 0; the same range applies to both types.
            nullable: true
        - name: max_price
          in: query
          required: false
          description: >-
            Maximum latest template price. Amounts use major currency units, for
            example 10.50 means AUD 10.50, with at most two decimal places.
            Numbers and numeric strings are accepted, with a minimum of 0; the
            same range applies to both types.
          schema:
            oneOf:
              - type: number
                multipleOf: 0.01
                minimum: 0
                nullable: true
              - type: string
                pattern: ^\d+(\.\d{1,2})?$
            description: >-
              Maximum latest template price. Amounts use major currency units,
              for example 10.50 means AUD 10.50, with at most two decimal
              places. Numbers and numeric strings are accepted, with a minimum
              of 0; the same range applies to both types.
            nullable: true
        - name: start_create
          in: query
          required: false
          description: >-
            Creation date range start, inclusive from 00:00:00. Must use
            YYYY-MM-DD.
          schema:
            type: string
            description: >-
              Creation date range start, inclusive from 00:00:00. Must use
              YYYY-MM-DD.
            format: date
            nullable: true
        - name: end_create
          in: query
          required: false
          description: >-
            Creation date range end, inclusive through 23:59:59. Must use
            YYYY-MM-DD.
          schema:
            type: string
            description: >-
              Creation date range end, inclusive through 23:59:59. Must use
              YYYY-MM-DD.
            format: date
            nullable: true
        - name: start_update
          in: query
          required: false
          description: >-
            Update date range start, inclusive from 00:00:00. Must use
            YYYY-MM-DD.
          schema:
            type: string
            description: >-
              Update date range start, inclusive from 00:00:00. Must use
              YYYY-MM-DD.
            format: date
            nullable: true
        - name: end_update
          in: query
          required: false
          description: >-
            Update date range end, inclusive through 23:59:59. Must use
            YYYY-MM-DD.
          schema:
            type: string
            description: >-
              Update date range end, inclusive through 23:59:59. Must use
              YYYY-MM-DD.
            format: date
            nullable: true
      responses:
        '200':
          description: >-
            HTTP 200. Distinguish success, business errors, validation errors
            and business authentication errors using the response body code.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/PlanListResponse'
                  - $ref: '#/components/schemas/BusinessError'
              examples:
                success:
                  summary: Successful paginated response
                  value:
                    code: 0
                    message: ok
                    data:
                      data:
                        - plan_id: TPL62038591
                          plan_name: Monthly membership
                          description: Monthly subscription template
                          status: 1
                          invoice_account_code: null
                          invoice_theme_id: null
                          surcharge_config:
                            direct_debit_surcharge: false
                            visa_domestic_surcharge: false
                            visa_international_surcharge: false
                            mastercard_domestic_surcharge: false
                            mastercard_international_surcharge: false
                            amex_domestic_surcharge: false
                            amex_international_surcharge: false
                          surcharge_config_enabled: []
                          surcharge_config_selected: []
                          recurring:
                            enabled: 1
                            schedule_name: Monthly fee
                            recurring_type: 3
                            amount: '25.50'
                            total_amount: null
                            start_date: null
                            end_date: null
                            end_terms: null
                            day_of_debit: FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15
                            day_of_debit_dtstart: null
                            process_type: 5
                            custom_cycle_type: 0
                            custom_cycle: 0
                            custom_cycle_type_text: ''
                            frequency: Monthly
                          one_off:
                            enabled: 0
                            schedule_name: null
                            amount: null
                            description: null
                            payment_date: null
                          created_at: '2026-10-28 09:00:00'
                          updated_at: '2026-10-28 09:00:00'
                          deleted_at: null
                      current_page: 1
                      per_page: 20
                      total: 1
                invalidIdentifiers:
                  summary: Invalid identifier
                  value:
                    code: 1
                    message: Business id is invalid
                    data: {}
        '429':
          description: >-
            Rate limit exceeded. API requests share a limit of 120 requests per
            minute, normally counted by source IP; this is not a separate
            allowance for each endpoint. Wait for the seconds specified by
            Retry-After.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
          content:
            application/json:
              schema:
                type: object
                description: Rate limit response.
                properties:
                  message:
                    type: string
                    description: Rate limit message.
              example:
                message: Too Many Attempts.
      security:
        - oauth2: []
      x-codeSamples:
        - lang: Shell
          label: Request example
          source: |-
            curl --get "${BASE_URL}/api/v2/plan/list" \
              -H "Authorization: Bearer ${ACCESS_TOKEN}" \
              -H "Accept: application/json" \
              --data-urlencode merchant_id=48290713 \
              --data-urlencode page=1 \
              --data-urlencode page_size=20
        - lang: Python
          label: Request example
          source: >
            import json

            import os

            import urllib.parse

            import urllib.request


            base_url = os.environ["BASE_URL"].rstrip("/")

            url = base_url + "/api/v2/plan/list"

            headers = {"Accept": "application/json"}

            headers["Authorization"] = "Bearer " + os.environ["ACCESS_TOKEN"]

            params = {
                "merchant_id": "48290713",
                "page": "1",
                "page_size": "20",
            }

            url += "?" + urllib.parse.urlencode(params)

            body = None


            request = urllib.request.Request(url, data=body, headers=headers,
            method="GET")

            with urllib.request.urlopen(request, timeout=30) as response:
                print(response.read().decode("utf-8"))
        - lang: JavaScript
          label: Request example
          source: |
            const env = (name) => {
              const value = process.env[name];
              if (!value) throw new Error(`Missing environment variable: ${name}`);
              return value;
            };
            const baseUrl = env("BASE_URL").replace(/\/+$/, "");
            const url = new URL(baseUrl + "/api/v2/plan/list");
            const headers = { Accept: "application/json" };
            headers.Authorization = `Bearer ${env("ACCESS_TOKEN")}`;
            const params = new URLSearchParams({
              "merchant_id": "48290713",
              "page": "1",
              "page_size": "20",
            });
            url.search = params.toString();

            const response = await fetch(url, {
              method: "GET",
              headers,
              signal: AbortSignal.timeout(30_000),
            });
            console.log(await response.text());
        - lang: PHP
          label: Request example
          source: |
            <?php
            $env = static function (string $name): string {
                $value = getenv($name);
                if ($value === false || $value === '') {
                    throw new RuntimeException("Missing environment variable: " . $name);
                }
                return $value;
            };
            $baseUrl = rtrim($env('BASE_URL'), '/');
            $url = $baseUrl . "/api/v2/plan/list";
            $headers = ['Accept: application/json'];
            $headers[] = 'Authorization: Bearer ' . $env('ACCESS_TOKEN');
            $params = [
                "merchant_id" => "48290713",
                "page" => "1",
                "page_size" => "20",
            ];
            $url .= '?' . http_build_query($params, '', '&', PHP_QUERY_RFC3986);

            $curl = curl_init($url);
            curl_setopt_array($curl, [
                CURLOPT_CUSTOMREQUEST => "GET",
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
            ]);
            $response = curl_exec($curl);
            if ($response === false) {
                $error = curl_error($curl);
                curl_close($curl);
                throw new RuntimeException($error);
            }
            curl_close($curl);
            echo $response, PHP_EOL;
        - lang: Go
          label: Request example
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "net/url"
                "os"
                "strings"
                "time"
            )

            func mustEnv(name string) string {
                value := os.Getenv(name)
                if value == "" { panic("Missing environment variable: " + name) }
                return value
            }

            func main() {
                baseURL := strings.TrimRight(mustEnv("BASE_URL"), "/")
                endpoint := baseURL + "/api/v2/plan/list"
                params := url.Values{}
                params.Set("merchant_id", "48290713")
                params.Set("page", "1")
                params.Set("page_size", "20")
                endpoint += "?" + params.Encode()
                req, err := http.NewRequest("GET", endpoint, nil)
                if err != nil { panic(err) }
                req.Header.Set("Accept", "application/json")
                req.Header.Set("Authorization", "Bearer " + mustEnv("ACCESS_TOKEN"))
                client := &http.Client{Timeout: 30 * time.Second}
                response, err := client.Do(req)
                if err != nil { panic(err) }
                defer response.Body.Close()
                result, err := io.ReadAll(response.Body)
                if err != nil { panic(err) }
                fmt.Println(string(result))
            }
        - lang: Java
          label: Request example
          source: |
            import java.io.ByteArrayOutputStream;
            import java.net.URI;
            import java.net.URLEncoder;
            import java.net.http.HttpClient;
            import java.net.http.HttpRequest;
            import java.net.http.HttpResponse;
            import java.nio.charset.StandardCharsets;
            import java.nio.file.Files;
            import java.nio.file.Path;
            import java.time.Duration;
            import java.util.LinkedHashMap;
            import java.util.Map;
            import java.util.UUID;
            import java.util.stream.Collectors;

            public class Example {
                static String requireEnv(String name) {
                    String value = System.getenv(name);
                    if (value == null || value.isEmpty()) {
                        throw new IllegalArgumentException("Missing environment variable: " + name);
                    }
                    return value;
                }

                public static void main(String[] args) throws Exception {
                    String baseUrl = requireEnv("BASE_URL").replaceAll("/+$", "");
                    String endpoint = baseUrl + "/api/v2/plan/list";
                    Map<String, String> params = new LinkedHashMap<>();
                    params.put("merchant_id", "48290713");
                    params.put("page", "1");
                    params.put("page_size", "20");
                    String encoded = params.entrySet().stream()
                        .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + "="
                            + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
                        .collect(Collectors.joining("&"));
                    endpoint += "?" + encoded;
                    HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(endpoint))
                        .timeout(Duration.ofSeconds(30))
                        .header("Accept", "application/json");
                    builder.header("Authorization", "Bearer " + requireEnv("ACCESS_TOKEN"));
                    HttpRequest request = builder.method("GET", HttpRequest.BodyPublishers.noBody()).build();
                    HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build();
                    HttpResponse<String> response = client.send(request,
                        HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
                    System.out.println(response.body());
                }
            }
        - lang: Ruby
          label: Request example
          source: |
            require "net/http"
            require "uri"

            base_url = ENV.fetch("BASE_URL").sub(%r{/+$}, "")
            uri = URI(base_url + "/api/v2/plan/list")
            params = {
              "merchant_id" => "48290713",
              "page" => "1",
              "page_size" => "20",
            }
            uri.query = URI.encode_www_form(params)
            request = Net::HTTP::Get.new(uri)
            request["Accept"] = "application/json"
            request["Authorization"] = "Bearer " + ENV.fetch("ACCESS_TOKEN")
            http = Net::HTTP.new(uri.host, uri.port)
            http.use_ssl = uri.scheme == "https"
            http.open_timeout = 30
            http.read_timeout = 30
            puts http.request(request).body
components:
  schemas:
    PlanListResponse:
      type: object
      description: Success response.
      properties:
        code:
          type: integer
          description: 0 means the template list was retrieved successfully.
          enum:
            - 0
        message:
          type: string
          description: Response message.
        data:
          type: object
          description: Pagination structure. The template array is located at data.data.
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/PlanTemplate'
              description: Templates on the current page.
            current_page:
              type: integer
              description: Current page number.
            per_page:
              type: integer
              description: Items per page.
            total:
              type: integer
              description: Total matching templates.
          required:
            - data
            - current_page
            - per_page
            - total
      required:
        - code
        - message
        - data
    BusinessError:
      type: object
      description: Business error. HTTP status is usually still 200.
      properties:
        code:
          type: integer
          description: >-
            Business and authentication errors use 1; request parameter and
            upload file property validation errors use 400.
          enum:
            - 1
            - 400
        message:
          type: string
          description: Error reason. The exact message varies by cause.
        data:
          oneOf:
            - type: object
              description: Empty object or error context.
              properties:
                customer_id:
                  type: string
                  description: >-
                    If a later createDdr step fails, this may identify a
                    customer that was created and retained. Reuse this ID when
                    retrying.
            - type: array
              items: {}
              description: Usually an empty array.
          description: >-
            Error data: may be [], {} or customer context containing
            customer_id.
      required:
        - code
        - message
        - data
    PlanTemplate:
      type: object
      description: Template available for V2 subscription creation.
      properties:
        plan_id:
          type: string
          description: Template ID.
          nullable: true
        plan_name:
          type: string
          description: Template name.
          nullable: true
        description:
          type: string
          description: Template description.
          nullable: true
        status:
          type: integer
          description: Template status. This list currently returns only 1 Active.
          nullable: true
          enum:
            - 1
            - null
        invoice_account_code:
          type: string
          description: Invoice accounting code.
          nullable: true
        invoice_theme_id:
          type: string
          description: Invoice theme ID.
          nullable: true
        surcharge_config:
          type: object
          description: Boolean enabled state for each surcharge type.
          properties:
            direct_debit_surcharge:
              type: boolean
              description: Whether direct_debit_surcharge is enabled.
            visa_domestic_surcharge:
              type: boolean
              description: Whether visa_domestic_surcharge is enabled.
            visa_international_surcharge:
              type: boolean
              description: Whether visa_international_surcharge is enabled.
            mastercard_domestic_surcharge:
              type: boolean
              description: Whether mastercard_domestic_surcharge is enabled.
            mastercard_international_surcharge:
              type: boolean
              description: Whether mastercard_international_surcharge is enabled.
            amex_domestic_surcharge:
              type: boolean
              description: Whether amex_domestic_surcharge is enabled.
            amex_international_surcharge:
              type: boolean
              description: Whether amex_international_surcharge is enabled.
          nullable: true
        surcharge_config_enabled:
          type: array
          items:
            type: string
            description: Surcharge type.
          description: List of enabled surcharge types.
        surcharge_config_selected:
          type: array
          items:
            type: string
            description: Surcharge type or the credit_card_surcharge group.
          description: Display selection list. Card options may be combined into a group.
        recurring:
          type: object
          description: Recurring segment.
          properties:
            enabled:
              type: integer
              description: 'Whether the recurring segment is enabled: 0/1.'
              enum:
                - 0
                - 1
            schedule_name:
              type: string
              description: Recurring segment name.
              nullable: true
            recurring_type:
              type: integer
              description: >-
                Subscription end condition: 1 after a number of successful
                payments; 2 at a cumulative amount; 3 until cancelled; 4 on an
                end date; 5 By agreement, which creates a debit authorization
                for later payment schedules.
              nullable: true
            amount:
              oneOf:
                - type: number
                  multipleOf: 0.01
                  nullable: true
                - type: string
                  pattern: ^\d+(\.\d{1,2})?$
              description: >-
                Recurring unit price in the latest template version; null when
                disabled. Amounts use major currency units and may be returned
                as numbers or decimal strings. Null when no amount applies.
              nullable: true
            total_amount:
              oneOf:
                - type: number
                  multipleOf: 0.01
                  nullable: true
                - type: string
                  pattern: ^\d+(\.\d{1,2})?$
              description: >-
                Cumulative amount limit. Amounts use major currency units and
                may be returned as numbers or decimal strings. Null when no
                amount applies.
              nullable: true
            start_date:
              type: string
              description: >-
                Always null in template lists. The caller must supply a date
                override when creating the subscription.
              nullable: true
            end_date:
              type: string
              description: End date; may be null.
              nullable: true
            end_terms:
              type: integer
              description: Target number of successful payments; may be null.
              nullable: true
            day_of_debit:
              type: string
              description: RFC 5545 RRULE string; may be null.
              nullable: true
            day_of_debit_dtstart:
              type: string
              description: First debit anchor in YYYY-MM-DD or MM-DD format.
              nullable: true
            process_type:
              type: integer
              description: >-
                Frequency: 1 One-off, 2 Daily, 3 Weekly, 4 Fortnightly, 5
                Monthly, 6 Quarterly, 7 Half Yearly, 8 Yearly, 9 Minutely, 10
                Hourly, 11 Datetime, 12 Custom, 13 Direct Payment, 14 By
                Agreement.
              nullable: true
            custom_cycle_type:
              type: integer
              description: >-
                Custom unit: 1 days, 2 weeks, 3 months, 4 years. Non-Custom
                values may be 0/null.
              nullable: true
            custom_cycle:
              type: integer
              description: Custom interval. Non-Custom values may be 0/null.
              nullable: true
            custom_cycle_type_text:
              type: string
              description: >-
                Custom unit text: days/weeks/months/years. Empty string if there
                is no matching unit.
            frequency:
              type: string
              description: Frequency description for display.
          required:
            - enabled
            - schedule_name
            - recurring_type
            - amount
            - total_amount
            - start_date
            - end_date
            - end_terms
            - day_of_debit
            - day_of_debit_dtstart
            - process_type
            - custom_cycle_type
            - custom_cycle
            - custom_cycle_type_text
            - frequency
        one_off:
          type: object
          description: One-off segment.
          properties:
            enabled:
              type: integer
              description: 'Whether the one-off segment is enabled: 0/1.'
              enum:
                - 0
                - 1
            schedule_name:
              type: string
              description: One-off segment name.
              nullable: true
            amount:
              oneOf:
                - type: number
                  multipleOf: 0.01
                  nullable: true
                - type: string
                  pattern: ^\d+(\.\d{1,2})?$
              description: >-
                One-off amount in major currency units. May be returned as a
                number or decimal string. Null when no amount applies.
              nullable: true
            description:
              type: string
              description: One-off description.
              nullable: true
            payment_date:
              type: string
              description: >-
                Original one-off date in the template; may be null. Creation
                uses the date override from the request.
              nullable: true
          required:
            - enabled
            - schedule_name
            - amount
            - description
            - payment_date
        created_at:
          type: string
          description: Creation time in YYYY-MM-DD HH:mm:ss format.
          nullable: true
        updated_at:
          type: string
          description: Update time in YYYY-MM-DD HH:mm:ss format.
          nullable: true
        deleted_at:
          type: string
          description: Deletion time in YYYY-MM-DD HH:mm:ss format; usually null.
          nullable: true
      required:
        - plan_id
        - plan_name
        - description
        - status
        - invoice_account_code
        - invoice_theme_id
        - surcharge_config
        - surcharge_config_enabled
        - surcharge_config_selected
        - recurring
        - one_off
        - created_at
        - updated_at
        - deleted_at
  securitySchemes:
    oauth2:
      type: oauth2
      description: >-
        OAuth2 client_credentials authorization. Obtain a new access_token when
        it expires.
      flows:
        clientCredentials:
          tokenUrl: /oauth/token
          scopes: {}

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.