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

# Add a payment schedule to a By agreement DDR

> ### Parameters by schedule type

Supply `merchant_id`, `plan_id`, `type`, `amount` and `start_date`. The target DDR must be active, have a bound payment method and allow a new schedule.

| type | Schedule type | Additional required fields |
| --- | --- | --- |
| 1 | Successful payment count | `day_of_debit`, `end_terms` |
| 2 | Total amount | `day_of_debit`, `total_amount` |
| 3 | Until cancelled | `day_of_debit` |
| 4 | End date | `day_of_debit`, `end_date`, with the end date no earlier than `start_date` |
| 6 | One-off | `day_of_debit` is not required |

Quarterly, half-yearly and yearly frequencies require `day_of_debit_dtstart`. Custom frequencies require `process_type=12`, `custom_cycle_type` and `custom_cycle`, consistent with the RRULE. See each field for start dates, first debit dates and full value limits.

Adds a payment schedule only to an activated By agreement DDR with a payment method already attached. The schedule uses that DDR's payment method. If any schedule is Paused, including a Deposit, resume or cancel it first. If an Active non-Deposit schedule exists, wait until it ends or is cancelled before adding another. Nonstandard RRULE expressions require process_type=12, custom_cycle_type and custom_cycle. start_date cannot precede the DDR start date. The first actual debit must be no earlier than tomorrow in the service business timezone and must comply with the DDR start date and frequency rules. Retain both plan_id and schedule_no from the response.

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 post /api/v2/subscription/createSchedule
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/subscription/createSchedule:
    post:
      tags:
        - Subscriptions
      summary: Add a payment schedule to a By agreement DDR
      description: >-
        ### Parameters by schedule type


        Supply `merchant_id`, `plan_id`, `type`, `amount` and `start_date`. The
        target DDR must be active, have a bound payment method and allow a new
        schedule.


        | type | Schedule type | Additional required fields |

        | --- | --- | --- |

        | 1 | Successful payment count | `day_of_debit`, `end_terms` |

        | 2 | Total amount | `day_of_debit`, `total_amount` |

        | 3 | Until cancelled | `day_of_debit` |

        | 4 | End date | `day_of_debit`, `end_date`, with the end date no
        earlier than `start_date` |

        | 6 | One-off | `day_of_debit` is not required |


        Quarterly, half-yearly and yearly frequencies require
        `day_of_debit_dtstart`. Custom frequencies require `process_type=12`,
        `custom_cycle_type` and `custom_cycle`, consistent with the RRULE. See
        each field for start dates, first debit dates and full value limits.


        Adds a payment schedule only to an activated By agreement DDR with a
        payment method already attached. The schedule uses that DDR's payment
        method. If any schedule is Paused, including a Deposit, resume or cancel
        it first. If an Active non-Deposit schedule exists, wait until it ends
        or is cancelled before adding another. Nonstandard RRULE expressions
        require process_type=12, custom_cycle_type and custom_cycle. start_date
        cannot precede the DDR start date. The first actual debit must be no
        earlier than tomorrow in the service business timezone and must comply
        with the DDR start date and frequency rules. Retain both plan_id and
        schedule_no from the response.


        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: v2CreateSchedule
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateScheduleRequest'
            examples:
              oneOff:
                summary: One-off payment schedule
                value:
                  merchant_id: '48290713'
                  plan_id: DDR73019482
                  type: 6
                  schedule_name: Usage charge
                  amount: '10.00'
                  start_date: '2030-01-15'
              count:
                summary: End after a number of successful payments
                value:
                  merchant_id: '48290713'
                  plan_id: DDR73019482
                  type: 1
                  amount: '10.00'
                  start_date: '2030-01-15'
                  end_terms: 12
                  day_of_debit: FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15
              amount:
                summary: End at a cumulative amount
                value:
                  merchant_id: '48290713'
                  plan_id: DDR73019482
                  type: 2
                  amount: '10.00'
                  total_amount: '100.00'
                  start_date: '2030-01-15'
                  day_of_debit: FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15
              endDate:
                summary: End on a specified date
                value:
                  merchant_id: '48290713'
                  plan_id: DDR73019482
                  type: 4
                  amount: '10.00'
                  start_date: '2030-01-15'
                  end_date: '2030-12-31'
                  day_of_debit: FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15
              ongoing:
                summary: Continue until cancelled
                value:
                  merchant_id: '48290713'
                  plan_id: DDR73019482
                  type: 3
                  amount: '10.00'
                  start_date: '2030-01-15'
                  day_of_debit: FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15
      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/CreateScheduleResponse'
                  - $ref: '#/components/schemas/BusinessError'
              examples:
                success:
                  summary: Created successfully
                  value:
                    code: 0
                    message: ok
                    data:
                      schedule_id: 947281
                      schedule_no: s1893452400000462
                      status: 2
                      plan_id: DDR73019482
                failure:
                  summary: DDR is not active
                  value:
                    code: 1
                    message: DDR is not active
                    data: []
                activeExists:
                  summary: A schedule is already in progress
                  value:
                    code: 1
                    message: >-
                      Plan has an active schedule; please wait for it to
                      complete or cancel before adding a new one
                    data: []
                validation:
                  summary: Missing parameters
                  value:
                    code: 400
                    message: The plan id field is required.
                    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: One-off payment schedule
          source: |-
            curl -X POST "${BASE_URL}/api/v2/subscription/createSchedule" \
              -H "Authorization: Bearer ${ACCESS_TOKEN}" \
              -H "Accept: application/json" \
              -H "Content-Type: application/json" \
              --data-raw '{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 6,
              "schedule_name": "Usage charge",
              "amount": "10.00",
              "start_date": "2030-01-15"
            }'
        - lang: Shell
          label: End after a number of successful payments
          source: |-
            curl -X POST "${BASE_URL}/api/v2/subscription/createSchedule" \
              -H "Authorization: Bearer ${ACCESS_TOKEN}" \
              -H "Accept: application/json" \
              -H "Content-Type: application/json" \
              --data-raw '{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 1,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_terms": 12,
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }'
        - lang: Shell
          label: End at a cumulative amount
          source: |-
            curl -X POST "${BASE_URL}/api/v2/subscription/createSchedule" \
              -H "Authorization: Bearer ${ACCESS_TOKEN}" \
              -H "Accept: application/json" \
              -H "Content-Type: application/json" \
              --data-raw '{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 2,
              "amount": "10.00",
              "total_amount": "100.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }'
        - lang: Shell
          label: End on a specified date
          source: |-
            curl -X POST "${BASE_URL}/api/v2/subscription/createSchedule" \
              -H "Authorization: Bearer ${ACCESS_TOKEN}" \
              -H "Accept: application/json" \
              -H "Content-Type: application/json" \
              --data-raw '{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 4,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_date": "2030-12-31",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }'
        - lang: Shell
          label: Continue until cancelled
          source: |-
            curl -X POST "${BASE_URL}/api/v2/subscription/createSchedule" \
              -H "Authorization: Bearer ${ACCESS_TOKEN}" \
              -H "Accept: application/json" \
              -H "Content-Type: application/json" \
              --data-raw '{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 3,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }'
        - lang: Python
          label: One-off payment schedule
          source: >
            import json

            import os

            import urllib.parse

            import urllib.request


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

            url = base_url + "/api/v2/subscription/createSchedule"

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

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

            payload = json.loads(r'''{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 6,
              "schedule_name": "Usage charge",
              "amount": "10.00",
              "start_date": "2030-01-15"
            }''')

            body = json.dumps(payload).encode("utf-8")

            headers["Content-Type"] = "application/json"


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

            with urllib.request.urlopen(request, timeout=30) as response:
                print(response.read().decode("utf-8"))
        - lang: Python
          label: End after a number of successful payments
          source: >
            import json

            import os

            import urllib.parse

            import urllib.request


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

            url = base_url + "/api/v2/subscription/createSchedule"

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

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

            payload = json.loads(r'''{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 1,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_terms": 12,
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }''')

            body = json.dumps(payload).encode("utf-8")

            headers["Content-Type"] = "application/json"


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

            with urllib.request.urlopen(request, timeout=30) as response:
                print(response.read().decode("utf-8"))
        - lang: Python
          label: End at a cumulative amount
          source: >
            import json

            import os

            import urllib.parse

            import urllib.request


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

            url = base_url + "/api/v2/subscription/createSchedule"

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

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

            payload = json.loads(r'''{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 2,
              "amount": "10.00",
              "total_amount": "100.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }''')

            body = json.dumps(payload).encode("utf-8")

            headers["Content-Type"] = "application/json"


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

            with urllib.request.urlopen(request, timeout=30) as response:
                print(response.read().decode("utf-8"))
        - lang: Python
          label: End on a specified date
          source: >
            import json

            import os

            import urllib.parse

            import urllib.request


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

            url = base_url + "/api/v2/subscription/createSchedule"

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

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

            payload = json.loads(r'''{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 4,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_date": "2030-12-31",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }''')

            body = json.dumps(payload).encode("utf-8")

            headers["Content-Type"] = "application/json"


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

            with urllib.request.urlopen(request, timeout=30) as response:
                print(response.read().decode("utf-8"))
        - lang: Python
          label: Continue until cancelled
          source: >
            import json

            import os

            import urllib.parse

            import urllib.request


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

            url = base_url + "/api/v2/subscription/createSchedule"

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

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

            payload = json.loads(r'''{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 3,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }''')

            body = json.dumps(payload).encode("utf-8")

            headers["Content-Type"] = "application/json"


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

            with urllib.request.urlopen(request, timeout=30) as response:
                print(response.read().decode("utf-8"))
        - lang: JavaScript
          label: One-off payment schedule
          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/subscription/createSchedule");

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

            headers.Authorization = `Bearer ${env("ACCESS_TOKEN")}`;

            const payload = {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 6,
              "schedule_name": "Usage charge",
              "amount": "10.00",
              "start_date": "2030-01-15"
            };

            const body = JSON.stringify(payload);

            headers["Content-Type"] = "application/json";


            const response = await fetch(url, {
              method: "POST",
              headers,
              body,
              signal: AbortSignal.timeout(30_000),
            });

            console.log(await response.text());
        - lang: JavaScript
          label: End after a number of successful payments
          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/subscription/createSchedule");

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

            headers.Authorization = `Bearer ${env("ACCESS_TOKEN")}`;

            const payload = {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 1,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_terms": 12,
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            };

            const body = JSON.stringify(payload);

            headers["Content-Type"] = "application/json";


            const response = await fetch(url, {
              method: "POST",
              headers,
              body,
              signal: AbortSignal.timeout(30_000),
            });

            console.log(await response.text());
        - lang: JavaScript
          label: End at a cumulative amount
          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/subscription/createSchedule");

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

            headers.Authorization = `Bearer ${env("ACCESS_TOKEN")}`;

            const payload = {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 2,
              "amount": "10.00",
              "total_amount": "100.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            };

            const body = JSON.stringify(payload);

            headers["Content-Type"] = "application/json";


            const response = await fetch(url, {
              method: "POST",
              headers,
              body,
              signal: AbortSignal.timeout(30_000),
            });

            console.log(await response.text());
        - lang: JavaScript
          label: End on a specified date
          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/subscription/createSchedule");

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

            headers.Authorization = `Bearer ${env("ACCESS_TOKEN")}`;

            const payload = {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 4,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_date": "2030-12-31",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            };

            const body = JSON.stringify(payload);

            headers["Content-Type"] = "application/json";


            const response = await fetch(url, {
              method: "POST",
              headers,
              body,
              signal: AbortSignal.timeout(30_000),
            });

            console.log(await response.text());
        - lang: JavaScript
          label: Continue until cancelled
          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/subscription/createSchedule");

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

            headers.Authorization = `Bearer ${env("ACCESS_TOKEN")}`;

            const payload = {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 3,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            };

            const body = JSON.stringify(payload);

            headers["Content-Type"] = "application/json";


            const response = await fetch(url, {
              method: "POST",
              headers,
              body,
              signal: AbortSignal.timeout(30_000),
            });

            console.log(await response.text());
        - lang: PHP
          label: One-off payment schedule
          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/subscription/createSchedule";
            $headers = ['Accept: application/json'];
            $headers[] = 'Authorization: Bearer ' . $env('ACCESS_TOKEN');
            $body = <<<'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 6,
              "schedule_name": "Usage charge",
              "amount": "10.00",
              "start_date": "2030-01-15"
            }
            JSON;
            $headers[] = 'Content-Type: application/json';

            $curl = curl_init($url);
            curl_setopt_array($curl, [
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_POSTFIELDS => $body,
            ]);
            $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: PHP
          label: End after a number of successful payments
          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/subscription/createSchedule";
            $headers = ['Accept: application/json'];
            $headers[] = 'Authorization: Bearer ' . $env('ACCESS_TOKEN');
            $body = <<<'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 1,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_terms": 12,
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON;
            $headers[] = 'Content-Type: application/json';

            $curl = curl_init($url);
            curl_setopt_array($curl, [
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_POSTFIELDS => $body,
            ]);
            $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: PHP
          label: End at a cumulative amount
          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/subscription/createSchedule";
            $headers = ['Accept: application/json'];
            $headers[] = 'Authorization: Bearer ' . $env('ACCESS_TOKEN');
            $body = <<<'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 2,
              "amount": "10.00",
              "total_amount": "100.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON;
            $headers[] = 'Content-Type: application/json';

            $curl = curl_init($url);
            curl_setopt_array($curl, [
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_POSTFIELDS => $body,
            ]);
            $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: PHP
          label: End on a specified date
          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/subscription/createSchedule";
            $headers = ['Accept: application/json'];
            $headers[] = 'Authorization: Bearer ' . $env('ACCESS_TOKEN');
            $body = <<<'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 4,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_date": "2030-12-31",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON;
            $headers[] = 'Content-Type: application/json';

            $curl = curl_init($url);
            curl_setopt_array($curl, [
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_POSTFIELDS => $body,
            ]);
            $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: PHP
          label: Continue until cancelled
          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/subscription/createSchedule";
            $headers = ['Accept: application/json'];
            $headers[] = 'Authorization: Bearer ' . $env('ACCESS_TOKEN');
            $body = <<<'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 3,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON;
            $headers[] = 'Content-Type: application/json';

            $curl = curl_init($url);
            curl_setopt_array($curl, [
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_POSTFIELDS => $body,
            ]);
            $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: One-off payment schedule
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "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/subscription/createSchedule"
                payload := `{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 6,
              "schedule_name": "Usage charge",
              "amount": "10.00",
              "start_date": "2030-01-15"
            }`
                body := strings.NewReader(payload)
                req, err := http.NewRequest("POST", endpoint, body)
                if err != nil { panic(err) }
                req.Header.Set("Accept", "application/json")
                req.Header.Set("Authorization", "Bearer " + mustEnv("ACCESS_TOKEN"))
                req.Header.Set("Content-Type", "application/json")
                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: Go
          label: End after a number of successful payments
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "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/subscription/createSchedule"
                payload := `{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 1,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_terms": 12,
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }`
                body := strings.NewReader(payload)
                req, err := http.NewRequest("POST", endpoint, body)
                if err != nil { panic(err) }
                req.Header.Set("Accept", "application/json")
                req.Header.Set("Authorization", "Bearer " + mustEnv("ACCESS_TOKEN"))
                req.Header.Set("Content-Type", "application/json")
                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: Go
          label: End at a cumulative amount
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "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/subscription/createSchedule"
                payload := `{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 2,
              "amount": "10.00",
              "total_amount": "100.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }`
                body := strings.NewReader(payload)
                req, err := http.NewRequest("POST", endpoint, body)
                if err != nil { panic(err) }
                req.Header.Set("Accept", "application/json")
                req.Header.Set("Authorization", "Bearer " + mustEnv("ACCESS_TOKEN"))
                req.Header.Set("Content-Type", "application/json")
                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: Go
          label: End on a specified date
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "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/subscription/createSchedule"
                payload := `{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 4,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_date": "2030-12-31",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }`
                body := strings.NewReader(payload)
                req, err := http.NewRequest("POST", endpoint, body)
                if err != nil { panic(err) }
                req.Header.Set("Accept", "application/json")
                req.Header.Set("Authorization", "Bearer " + mustEnv("ACCESS_TOKEN"))
                req.Header.Set("Content-Type", "application/json")
                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: Go
          label: Continue until cancelled
          source: |
            package main

            import (
                "fmt"
                "io"
                "net/http"
                "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/subscription/createSchedule"
                payload := `{
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 3,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }`
                body := strings.NewReader(payload)
                req, err := http.NewRequest("POST", endpoint, body)
                if err != nil { panic(err) }
                req.Header.Set("Accept", "application/json")
                req.Header.Set("Authorization", "Bearer " + mustEnv("ACCESS_TOKEN"))
                req.Header.Set("Content-Type", "application/json")
                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: One-off payment schedule
          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/subscription/createSchedule";
                    String payload =
                        "{\n" +
                        "  \"merchant_id\": \"48290713\",\n" +
                        "  \"plan_id\": \"DDR73019482\",\n" +
                        "  \"type\": 6,\n" +
                        "  \"schedule_name\": \"Usage charge\",\n" +
                        "  \"amount\": \"10.00\",\n" +
                        "  \"start_date\": \"2030-01-15\"\n" +
                        "}";
                    HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(endpoint))
                        .timeout(Duration.ofSeconds(30))
                        .header("Accept", "application/json");
                    builder.header("Authorization", "Bearer " + requireEnv("ACCESS_TOKEN"));
                    builder.header("Content-Type", "application/json");
                    HttpRequest request = builder.method("POST", HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8)).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: Java
          label: End after a number of successful payments
          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/subscription/createSchedule";
                    String payload =
                        "{\n" +
                        "  \"merchant_id\": \"48290713\",\n" +
                        "  \"plan_id\": \"DDR73019482\",\n" +
                        "  \"type\": 1,\n" +
                        "  \"amount\": \"10.00\",\n" +
                        "  \"start_date\": \"2030-01-15\",\n" +
                        "  \"end_terms\": 12,\n" +
                        "  \"day_of_debit\": \"FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15\"\n" +
                        "}";
                    HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(endpoint))
                        .timeout(Duration.ofSeconds(30))
                        .header("Accept", "application/json");
                    builder.header("Authorization", "Bearer " + requireEnv("ACCESS_TOKEN"));
                    builder.header("Content-Type", "application/json");
                    HttpRequest request = builder.method("POST", HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8)).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: Java
          label: End at a cumulative amount
          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/subscription/createSchedule";
                    String payload =
                        "{\n" +
                        "  \"merchant_id\": \"48290713\",\n" +
                        "  \"plan_id\": \"DDR73019482\",\n" +
                        "  \"type\": 2,\n" +
                        "  \"amount\": \"10.00\",\n" +
                        "  \"total_amount\": \"100.00\",\n" +
                        "  \"start_date\": \"2030-01-15\",\n" +
                        "  \"day_of_debit\": \"FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15\"\n" +
                        "}";
                    HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(endpoint))
                        .timeout(Duration.ofSeconds(30))
                        .header("Accept", "application/json");
                    builder.header("Authorization", "Bearer " + requireEnv("ACCESS_TOKEN"));
                    builder.header("Content-Type", "application/json");
                    HttpRequest request = builder.method("POST", HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8)).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: Java
          label: End on a specified date
          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/subscription/createSchedule";
                    String payload =
                        "{\n" +
                        "  \"merchant_id\": \"48290713\",\n" +
                        "  \"plan_id\": \"DDR73019482\",\n" +
                        "  \"type\": 4,\n" +
                        "  \"amount\": \"10.00\",\n" +
                        "  \"start_date\": \"2030-01-15\",\n" +
                        "  \"end_date\": \"2030-12-31\",\n" +
                        "  \"day_of_debit\": \"FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15\"\n" +
                        "}";
                    HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(endpoint))
                        .timeout(Duration.ofSeconds(30))
                        .header("Accept", "application/json");
                    builder.header("Authorization", "Bearer " + requireEnv("ACCESS_TOKEN"));
                    builder.header("Content-Type", "application/json");
                    HttpRequest request = builder.method("POST", HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8)).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: Java
          label: Continue until cancelled
          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/subscription/createSchedule";
                    String payload =
                        "{\n" +
                        "  \"merchant_id\": \"48290713\",\n" +
                        "  \"plan_id\": \"DDR73019482\",\n" +
                        "  \"type\": 3,\n" +
                        "  \"amount\": \"10.00\",\n" +
                        "  \"start_date\": \"2030-01-15\",\n" +
                        "  \"day_of_debit\": \"FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15\"\n" +
                        "}";
                    HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(endpoint))
                        .timeout(Duration.ofSeconds(30))
                        .header("Accept", "application/json");
                    builder.header("Authorization", "Bearer " + requireEnv("ACCESS_TOKEN"));
                    builder.header("Content-Type", "application/json");
                    HttpRequest request = builder.method("POST", HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8)).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: One-off payment schedule
          source: |
            require "net/http"
            require "uri"

            base_url = ENV.fetch("BASE_URL").sub(%r{/+$}, "")
            uri = URI(base_url + "/api/v2/subscription/createSchedule")
            request = Net::HTTP::Post.new(uri)
            request["Accept"] = "application/json"
            request["Authorization"] = "Bearer " + ENV.fetch("ACCESS_TOKEN")
            request["Content-Type"] = "application/json"
            request.body = <<~'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 6,
              "schedule_name": "Usage charge",
              "amount": "10.00",
              "start_date": "2030-01-15"
            }
            JSON
            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
        - lang: Ruby
          label: End after a number of successful payments
          source: |
            require "net/http"
            require "uri"

            base_url = ENV.fetch("BASE_URL").sub(%r{/+$}, "")
            uri = URI(base_url + "/api/v2/subscription/createSchedule")
            request = Net::HTTP::Post.new(uri)
            request["Accept"] = "application/json"
            request["Authorization"] = "Bearer " + ENV.fetch("ACCESS_TOKEN")
            request["Content-Type"] = "application/json"
            request.body = <<~'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 1,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_terms": 12,
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON
            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
        - lang: Ruby
          label: End at a cumulative amount
          source: |
            require "net/http"
            require "uri"

            base_url = ENV.fetch("BASE_URL").sub(%r{/+$}, "")
            uri = URI(base_url + "/api/v2/subscription/createSchedule")
            request = Net::HTTP::Post.new(uri)
            request["Accept"] = "application/json"
            request["Authorization"] = "Bearer " + ENV.fetch("ACCESS_TOKEN")
            request["Content-Type"] = "application/json"
            request.body = <<~'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 2,
              "amount": "10.00",
              "total_amount": "100.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON
            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
        - lang: Ruby
          label: End on a specified date
          source: |
            require "net/http"
            require "uri"

            base_url = ENV.fetch("BASE_URL").sub(%r{/+$}, "")
            uri = URI(base_url + "/api/v2/subscription/createSchedule")
            request = Net::HTTP::Post.new(uri)
            request["Accept"] = "application/json"
            request["Authorization"] = "Bearer " + ENV.fetch("ACCESS_TOKEN")
            request["Content-Type"] = "application/json"
            request.body = <<~'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 4,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "end_date": "2030-12-31",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON
            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
        - lang: Ruby
          label: Continue until cancelled
          source: |
            require "net/http"
            require "uri"

            base_url = ENV.fetch("BASE_URL").sub(%r{/+$}, "")
            uri = URI(base_url + "/api/v2/subscription/createSchedule")
            request = Net::HTTP::Post.new(uri)
            request["Accept"] = "application/json"
            request["Authorization"] = "Bearer " + ENV.fetch("ACCESS_TOKEN")
            request["Content-Type"] = "application/json"
            request.body = <<~'JSON'
            {
              "merchant_id": "48290713",
              "plan_id": "DDR73019482",
              "type": 3,
              "amount": "10.00",
              "start_date": "2030-01-15",
              "day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
            }
            JSON
            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:
    CreateScheduleRequest:
      type: object
      description: >-
        Adds a payment schedule to an activated By agreement DDR with a payment
        method attached, using that DDR's payment method. If any schedule is
        Paused, including a Deposit, resume or cancel it first. If an Active
        non-Deposit schedule exists, wait until it ends or is cancelled before
        adding another. Nonstandard RRULE expressions require process_type=12,
        custom_cycle_type and custom_cycle together.
      properties:
        merchant_id:
          type: string
          description: Business identifier assigned by BillBuddy.
          maxLength: 20
          minLength: 1
        plan_id:
          type: string
          description: DDR subscription ID.
          maxLength: 50
          minLength: 1
        type:
          type: integer
          description: >-
            Payment schedule type: 1 after a number of successful payments; 2 at
            a cumulative amount; 3 until cancelled; 4 on an end date; 6 One-off.
            Types 5 and 7 are not allowed.
          enum:
            - 1
            - 2
            - 3
            - 4
            - 6
        amount:
          oneOf:
            - type: number
              multipleOf: 0.01
              minimum: 0.01
              maximum: 9999999.99
            - type: string
              pattern: ^\d+(\.\d{1,2})?$
              allOf:
                - pattern: ^0*(?:[1-9]\d{0,6}(?:\.\d{1,2})?|0\.(?:0[1-9]|[1-9]\d?))$
          description: >-
            One-off or per-payment amount in major currency units, for example
            10.50 means AUD 10.50. At most two decimal places. Numbers and
            numeric strings are accepted, with a minimum of 0.01 and maximum of
            9999999.99; the same range applies to both types.
        start_date:
          type: string
          description: >-
            Payment schedule start date in YYYY-MM-DD format. Cannot precede the
            DDR start date. Past dates are accepted, but the first actual debit
            must be no earlier than tomorrow in the service business timezone
            and must comply with the DDR start date and RRULE date rules.
          format: date
          minLength: 1
        schedule_name:
          type: string
          description: Payment schedule name. Defaults to the DDR plan_name when omitted.
          nullable: true
          maxLength: 255
        total_amount:
          oneOf:
            - type: number
              multipleOf: 0.01
              minimum: 0.01
              nullable: true
            - type: string
              pattern: ^\d+(\.\d{1,2})?$
              allOf:
                - pattern: ^0*(?:[1-9]\d*(?:\.\d{1,2})?|0\.(?:0[1-9]|[1-9]\d?))$
          description: >-
            Target total amount in major currency units, with at most two
            decimal places and a minimum of 0.01. Accepts a number or numeric
            string. Required and non-null when type=2. The number of payments is
            calculated from the target amount.
          nullable: true
        day_of_debit:
          type: string
          description: >-
            RFC 5545 RRULE debit rule. Required and non-null for type=1/2/3/4;
            optional for type=6 (one-off). See the integration guide for
            frequency syntax.
          nullable: true
          maxLength: 255
        process_type:
          type: integer
          description: >-
            Provide 12 only for a custom frequency. Other frequencies are
            inferred from the RRULE; omit this field for them.
          nullable: true
          enum:
            - 12
            - null
        custom_cycle_type:
          type: integer
          description: >-
            Required for process_type=12: 1 days, 2 weeks, 3 months, 4 years.
            Must correspond to the RRULE FREQ. Non-Custom mode prohibits
            nonempty custom cycle parameters. Required and non-null when
            process_type=12.
          nullable: true
          enum:
            - 1
            - 2
            - 3
            - 4
            - null
        custom_cycle:
          type: integer
          description: >-
            Required for process_type=12. A positive integer equal to the RRULE
            INTERVAL. Minimum 5 for days and 1 for other units. Required and
            non-null when process_type=12.
          nullable: true
          minimum: 1
        day_of_debit_dtstart:
          type: string
          description: >-
            First debit anchor. Required for quarterly, half-yearly and yearly
            frequencies. YYYY-MM-DD is recommended; the date must be strictly
            after the corresponding start_date and within one billing cycle
            (3/6/12 months, clamped to month end). MM-DD is also accepted if it
            is a valid month/day; the full-date window restriction does not
            apply to that format.
          nullable: true
          pattern: ^(\d{4}-)?\d{2}-\d{2}$
        end_date:
          type: string
          description: >-
            End date, preferably YYYY-MM-DD. Required and non-null when type=4.
            When supplied, cannot precede start_date in the same segment.
          nullable: true
          format: date
        end_terms:
          type: integer
          description: >-
            Number of successful payments, an integer of at least 1. Required
            and non-null when type=1.
          nullable: true
          minimum: 1
      required:
        - merchant_id
        - plan_id
        - type
        - amount
        - start_date
      not:
        anyOf:
          - allOf:
              - required:
                  - type
                properties:
                  type:
                    enum:
                      - 1
              - not:
                  required:
                    - end_terms
                  properties:
                    end_terms:
                      not:
                        enum:
                          - null
          - allOf:
              - required:
                  - type
                properties:
                  type:
                    enum:
                      - 2
              - not:
                  required:
                    - total_amount
                  properties:
                    total_amount:
                      not:
                        enum:
                          - null
          - allOf:
              - required:
                  - type
                properties:
                  type:
                    enum:
                      - 4
              - not:
                  required:
                    - end_date
                  properties:
                    end_date:
                      not:
                        enum:
                          - null
                      minLength: 1
          - allOf:
              - required:
                  - type
                properties:
                  type:
                    enum:
                      - 1
                      - 2
                      - 3
                      - 4
              - not:
                  required:
                    - day_of_debit
                  properties:
                    day_of_debit:
                      not:
                        enum:
                          - null
                      minLength: 1
          - allOf:
              - required:
                  - process_type
                properties:
                  process_type:
                    enum:
                      - 12
              - not:
                  required:
                    - custom_cycle_type
                    - custom_cycle
                  properties:
                    custom_cycle_type:
                      not:
                        enum:
                          - null
                    custom_cycle:
                      not:
                        enum:
                          - null
          - allOf:
              - required:
                  - process_type
                  - custom_cycle_type
                properties:
                  process_type:
                    enum:
                      - 12
                  custom_cycle_type:
                    enum:
                      - 1
              - not:
                  required:
                    - custom_cycle
                  properties:
                    custom_cycle:
                      not:
                        enum:
                          - null
                      minimum: 5
          - allOf:
              - required:
                  - custom_cycle_type
                properties:
                  custom_cycle_type:
                    not:
                      enum:
                        - null
              - not:
                  required:
                    - process_type
                  properties:
                    process_type:
                      enum:
                        - 12
          - allOf:
              - required:
                  - custom_cycle
                properties:
                  custom_cycle:
                    not:
                      enum:
                        - null
              - not:
                  required:
                    - process_type
                  properties:
                    process_type:
                      enum:
                        - 12
    CreateScheduleResponse:
      type: object
      description: Success response.
      properties:
        code:
          type: integer
          description: >-
            0 means the payment schedule was created successfully. Does not
            indicate a completed charge.
          enum:
            - 0
        message:
          type: string
          description: Response message.
        data:
          type: object
          description: New payment schedule.
          properties:
            schedule_id:
              type: integer
              description: Payment schedule identifier.
            schedule_no:
              type: string
              description: >-
                Payment schedule number. Retain it together with plan_id to
                identify the schedule within the subscription.
            status:
              type: integer
              description: >-
                Payment schedule status: 1 Pending, 2 Active, 3 Paused, 4
                Cancelled, 5 Completed. Newly created schedules usually return
                2.
              enum:
                - 1
                - 2
                - 3
                - 4
                - 5
            plan_id:
              type: string
              description: DDR subscription ID.
          required:
            - schedule_id
            - schedule_no
            - status
            - plan_id
      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
  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.