curl -X POST "${BASE_URL}/api/v2/subscription/create" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
--data-raw '{
"merchant_id": "48290713",
"customer": {
"customer_id": "CUS48290713"
},
"plan": {
"plan_name": "Monthly membership",
"recurring": {
"enabled": 1,
"schedule_name": "Monthly fee",
"recurring_type": 3,
"amount": "25.50",
"start_date": "2030-01-10",
"day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
},
"surcharge_config": []
},
"notify_email": false,
"notify_sms": false
}'{
"code": 0,
"message": "ok",
"data": {
"customer_id": "CUS48290713",
"plan_id": "DDR73019482",
"status": 2,
"activation_url": "https://staging-api.billbuddyhq.com/api/v2/subscription/activatePage/73a9c4f128d60b5e9a2746cd801fb352",
"activation_html": "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><meta http-equiv=\"refresh\" content=\"0;url=https://staging-api.billbuddyhq.com/api/v2/subscription/activatePage/73a9c4f128d60b5e9a2746cd801fb352\"><style>html,body{height:100%;margin:0}body{display:flex;align-items:center;justify-content:center;font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:#444;background:#fff}.tip{text-align:center;font-size:16px}.spin{width:28px;height:28px;margin:0 auto 12px;border:3px solid #ddd;border-top-color:#888;border-radius:50%;animation:r .8s linear infinite}@keyframes r{to{transform:rotate(360deg)}}</style></head><body><div class=\"tip\"><div class=\"spin\"></div>Redirecting...</div><form method=\"get\" action=\"https://staging-api.billbuddyhq.com/api/v2/subscription/activatePage/73a9c4f128d60b5e9a2746cd801fb352\" target=\"_self\" id=\"checkform\" name=\"checkform\"></form><script>window.onload=function(){document.checkform.submit();};</script></body></html>"
}
}Create a hosted subscription
Choose a subscription mode
Use the recommended nested customer and plan fields. Choose one customer format: customer.customer_id for an existing customer, or customer.firstName, customer.lastName and customer.emailAddress for a new customer. Do not combine existing customer identification with new customer details.
| Mode | Fields to supply | Conditions |
|---|---|---|
| Manual subscription | plan.plan_name and at least one enabled plan.recurring or plan.one_off segment | Set each enabled segment’s enabled to 1; recurring and one-off segments can both be enabled |
| Template subscription | plan.template_id and the applicable template dates | Supply plan.start_date for a recurring segment and plan.payment_date for a one-off segment; omit plan_name to inherit the template name |
| By agreement | plan.plan_name and plan.schedule | Supply schedule_name, type, amount and start_date for the initial schedule; types 1, 2, 3, 4 and 6 are allowed |
The three modes are mutually exclusive. An enabled manual recurring segment requires schedule_name, recurring_type, amount, start_date and day_of_debit. An enabled one-off segment requires schedule_name, amount and payment_date. Dates must be no earlier than tomorrow in the business timezone.
| Recurring end condition | Additional required fields |
|---|---|
recurring_type=1 / schedule.type=1, successful payment count | end_terms |
recurring_type=2 / schedule.type=2, total amount | total_amount, with amount no greater than total_amount |
recurring_type=3 / schedule.type=3, until cancelled | No additional end condition |
recurring_type=4 / schedule.type=4, end date | end_date, no earlier than the same segment’s start_date |
schedule.type=6, one-off | day_of_debit is not required; this type is not available for recurring_type |
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 individual fields for ranges and date windows.
Top-level alternative fields remain supported. New integrations should use the nested format consistently. If both formats contain the same field, the nested value takes precedence.
A successful creation returns status=2 Inactive; the subscription is not yet activated. Give customers the complete activation_url unchanged, use it as an iframe src, or use activation_html as the iframe srcdoc. Customers enter payment details, authorize debits and activate on the BillBuddy-hosted page. Do not construct activation links or parse credentials. Keep the Client Secret and access_token on your server. Three definition modes are mutually exclusive: manual recurring/one_off, template_id, and By agreement schedule. Template mode requires dates for each enabled component: recurring start_date and one-off payment_date. New customer details and existing customer references are mutually exclusive. The nested customer/plan format is recommended; see field descriptions for alternatives. A successful response may omit the activation link. Contact BillBuddy to check the created subscription before proceeding in that case. No caller-supplied idempotency identifier is supported; do not blindly retry creation. 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.
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.
curl -X POST "${BASE_URL}/api/v2/subscription/create" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
--data-raw '{
"merchant_id": "48290713",
"customer": {
"customer_id": "CUS48290713"
},
"plan": {
"plan_name": "Monthly membership",
"recurring": {
"enabled": 1,
"schedule_name": "Monthly fee",
"recurring_type": 3,
"amount": "25.50",
"start_date": "2030-01-10",
"day_of_debit": "FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=15"
},
"surcharge_config": []
},
"notify_email": false,
"notify_sms": false
}'{
"code": 0,
"message": "ok",
"data": {
"customer_id": "CUS48290713",
"plan_id": "DDR73019482",
"status": 2,
"activation_url": "https://staging-api.billbuddyhq.com/api/v2/subscription/activatePage/73a9c4f128d60b5e9a2746cd801fb352",
"activation_html": "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><meta http-equiv=\"refresh\" content=\"0;url=https://staging-api.billbuddyhq.com/api/v2/subscription/activatePage/73a9c4f128d60b5e9a2746cd801fb352\"><style>html,body{height:100%;margin:0}body{display:flex;align-items:center;justify-content:center;font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:#444;background:#fff}.tip{text-align:center;font-size:16px}.spin{width:28px;height:28px;margin:0 auto 12px;border:3px solid #ddd;border-top-color:#888;border-radius:50%;animation:r .8s linear infinite}@keyframes r{to{transform:rotate(360deg)}}</style></head><body><div class=\"tip\"><div class=\"spin\"></div>Redirecting...</div><form method=\"get\" action=\"https://staging-api.billbuddyhq.com/api/v2/subscription/activatePage/73a9c4f128d60b5e9a2746cd801fb352\" target=\"_self\" id=\"checkform\" name=\"checkform\"></form><script>window.onload=function(){document.checkform.submit();};</script></body></html>"
}
}Authorizations
OAuth2 client_credentials authorization. Obtain a new access_token when it expires.
Body
Creates a subscription awaiting activation. Supply either an existing customer reference or new customer details. New customers require firstName, lastName and emailAddress in full. Exactly one subscription definition mode is required: manual, template or By agreement. Manual mode must enable at least one charge segment. plan_name is required outside template mode. The nested customer and plan format is recommended.
Business identifier assigned by BillBuddy.
1 - 20Whether to allow email notifications for this transaction or subscription. false prohibits them; true allows them. Omission or null uses the business's API email notification setting, which defaults to off. Actual delivery depends on notification preferences and applicable rules. Also accepts 0/1 and the strings "0"/"1".
Whether to allow SMS notifications for this transaction or subscription. false prohibits them; true allows them. Omission or null uses the business's API SMS notification setting, which defaults to off. Actual delivery depends on notification preferences and applicable rules. Also accepts 0/1 and the strings "0"/"1".
Supply customer_id to reuse a customer, or firstName, lastName and emailAddress to create one. These options are mutually exclusive.
Show child attributes
Show child attributes
Choose exactly one mode: manual recurring/one_off, template_id, or By agreement schedule.
Show child attributes
Show child attributes
Supported top-level alternative; use customer.customer_id for new integrations. If both forms supply this field, the nested value takes precedence.
BillBuddy customer identifier. Must identify a valid customer within the current merchant and business.
32Supported top-level alternative; use customer.firstName for new integrations. If both forms supply this field, the nested value takes precedence.
New customer's first name. Required when creating a new customer.
100Supported top-level alternative; use customer.lastName for new integrations. If both forms supply this field, the nested value takes precedence.
New customer's last name. Required when creating a new customer.
100Supported top-level alternative; use customer.emailAddress for new integrations. If both forms supply this field, the nested value takes precedence.
New customer's primary email address. Required when creating a new customer. If it already belongs to a customer in the same merchant and business, supply that existing customer_id instead.
500Supported top-level alternative; use customer.mobilePhoneNumber for new integrations. If both forms supply this field, the nested value takes precedence.
Customer mobile phone number.
20Supported top-level alternative; use customer.addressLine1 for new integrations. If both forms supply this field, the nested value takes precedence.
Customer address line 1.
255Supported top-level alternative; use customer.addressSuburb for new integrations. If both forms supply this field, the nested value takes precedence.
Customer city or suburb.
100Supported top-level alternative; use customer.addressState for new integrations. If both forms supply this field, the nested value takes precedence.
Customer state or province.
100Supported top-level alternative; use customer.addressPostCode for new integrations. If both forms supply this field, the nested value takes precedence.
Customer postcode.
50Supported top-level alternative; use plan.plan_name for new integrations. If both forms supply this field, the nested value takes precedence.
Subscription name. In template mode, omission or null inherits the template name. Required and nonempty in other modes.
255Supported top-level alternative; use plan.description for new integrations. If both forms supply this field, the nested value takes precedence.
Description.
500Supported top-level alternative; use plan.recurring for new integrations. If both forms supply this field, the nested value takes precedence.
Recurring subscription definition.
Show child attributes
Show child attributes
Supported top-level alternative; use plan.one_off for new integrations. If both forms supply this field, the nested value takes precedence.
One-off payment definition. Acts as a Deposit when enabled with recurring, or as a One-off when used alone.
Show child attributes
Show child attributes
Supported top-level alternative; use plan.schedule for new integrations. If both forms supply this field, the nested value takes precedence.
Initial By agreement payment schedule definition. Mutually exclusive with manual recurring/one_off mode and template_id mode.
Show child attributes
Show child attributes
Supported top-level alternative; use plan.surcharge_config for new integrations. If both forms supply this field, the nested value takes precedence.
Surcharge options, preferably an array of strings. See the schema and examples for allowed options. Omission, null or an empty array disables all options; non-array values are also treated as all disabled. Unknown options do not enable charges. credit_card_surcharge selects the credit card surcharge group. Actual charges depend on merchant business rules and payment method restrictions. Applies in manual mode. Template mode uses the template's surcharge options, which this field cannot override. By agreement schedule mode does not support this setting. Card surcharges remain subject to the applicable charging policy; if it prohibits them, selecting card options does not enable charges.
Surcharge option.
direct_debit_surcharge, visa_domestic_surcharge, visa_international_surcharge, mastercard_domestic_surcharge, mastercard_international_surcharge, amex_domestic_surcharge, amex_international_surcharge, credit_card_surcharge Supported top-level alternative; use plan.dishonour_fee_switch for new integrations. If both forms supply this field, the nested value takes precedence.
Whether to charge a customer dishonour fee. Omission or null defaults to off. Enabling it requires an applicable positive fee configuration; the signed terms determine the actual amount. Also accepts 0/1 and the strings "0"/"1". Applies only to manual recurring/one_off mode. Template mode and By agreement schedule mode do not support this setting through this field.
Supported top-level alternative; use plan.template_id for new integrations. If both forms supply this field, the nested value takes precedence.
Available template ID from GET /api/v2/plan/list. Only enabled, ACTIVE, non-tiered templates other than By agreement are accepted.
20Supported top-level alternative; use plan.start_date for new integrations. If both forms supply this field, the nested value takes precedence.
Date override for the template's recurring segment. Required when the template contains recurring. Must be no earlier than tomorrow in the service business timezone.
Supported top-level alternative; use plan.payment_date for new integrations. If both forms supply this field, the nested value takes precedence.
Date override for the template's one_off segment. Required when the template contains one_off. Must be no earlier than tomorrow in the service business timezone.
Response
HTTP 200. Distinguish success, business errors, validation errors and business authentication errors using the response body code.