Implementation guides
Creating a subscription
Qualy's API provides robust functionality for creating subscriptions, allowing developers to implement recurring payment systems with customizable schedules. This guide will take you through the process step by step, starting with a basic example and gradually introducing more complex subscription scenarios.
Before you start
You need to have an existing Contact to create a Subscription. The contact field accepts either the Contact ObjectId or the contact email. The service field accepts either the Service ObjectId or service name. See Smart references.
Creating a subscription
To create a subscription on Qualy, you will have to use the Subscription API.
When you create a Subscription, you can specify options like the name, amount, currency, billing details, and schedule:
curl -X POST https://api.qualyhq.com/v1/subscriptions/create \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "Monthly Service Plan",
"mode": "schedule",
"description": {
"internal": "Internal notes about this subscription",
"external": "Monthly service fee for Premium Support"
},
"contact": "john.doe@example.com",
"amount": 10000,
"service": "Premium Support",
"currency": "USD",
"billing": {
"startAt": "2026-10-01T00:00:00.000Z",
"endAt": "2027-10-01T00:00:00.000Z"
},
"schedule": {
"frequency": "every-month",
"dayOfMonth": 1
}
}'
const res = await fetch('https://api.qualyhq.com/v1/subscriptions/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'ApiKey your-api-key-here',
'X-TENANT-ID': 'your-tenant-id-here',
},
body: JSON.stringify({
name: 'Monthly Service Plan',
mode: 'schedule',
description: {
internal: 'Internal notes about this subscription',
external: 'Monthly service fee for Premium Support',
},
contact: 'john.doe@example.com',
amount: 10000, // amount in cents (100.00)
service: 'Premium Support',
currency: 'USD',
billing: {
startAt: '2026-10-01T00:00:00.000Z',
endAt: '2027-10-01T00:00:00.000Z',
},
schedule: {
frequency: 'every-month', // bill once a month…
dayOfMonth: 1, // …on the 1st
},
}),
});
const { data: subscription } = await res.json();
console.log(subscription._id);
use Illuminate\Support\Facades\Http;
$subscription = Http::withHeaders([
'Authorization' => 'ApiKey your-api-key-here',
'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/subscriptions/create', [
'name' => 'Monthly Service Plan',
'mode' => 'schedule',
'description' => [
'internal' => 'Internal notes about this subscription',
'external' => 'Monthly service fee for Premium Support',
],
'contact' => 'john.doe@example.com',
'amount' => 10000, // amount in cents (100.00)
'service' => 'Premium Support',
'currency' => 'USD',
'billing' => [
'startAt' => '2026-10-01T00:00:00.000Z',
'endAt' => '2027-10-01T00:00:00.000Z',
],
'schedule' => [
'frequency' => 'every-month', // bill once a month…
'dayOfMonth' => 1, // …on the 1st
],
])->json('data');
echo $subscription['_id'];
Subscription Scheduling Options
When creating a subscription, you need to define how frequently the payments should occur. This is controlled through the schedule property in your request:
Important
Once a subscription is created, new payment intents will be automatically generated following the subscription schedule. Each payment intent is editable until it's paid or canceled.
To manage the Payment Intents created by the subsription, check the Payment Intents API.
The schedule.frequency field is required and sets the cadence. Then, depending on the frequency, you pin the exact billing day with dayOfMonth or dayOfWeek.
Frequency values
frequency | Description |
|---|---|
every-week | Bills weekly. Pair with dayOfWeek. |
every-2-weeks | Bills every two weeks. Pair with dayOfWeek. |
every-month | Bills monthly. Pair with dayOfMonth. |
Billing-day parameters
| Parameter | Description |
|---|---|
dayOfMonth | Which day of the month to bill (1-28). Example: dayOfMonth: 15 bills on the 15th. Use with every-month. |
dayOfWeek | Which day of the week to bill (0-6, where 0 is Sunday). Example: dayOfWeek: 1 bills every Monday. Use with every-week / every-2-weeks. |
The `mode` field is required
Every subscription needs a mode. Use schedule for standard recurring billing on a fixed cadence (covered here). The other modes — amount-cap and payment-intent-partial — support advanced billing scenarios.
Subscription Billing Period
Every subscription must have a defined billing period through the billing object, which contains:
startAt: When the subscription begins (required)endAt: When the subscription ends (optional - if not provided, the subscription will continue indefinitely)
"billing": {
"startAt": "2025-10-01T00:00:00.000Z",
"endAt": "2026-10-01T00:00:00.000Z" // Optional
}
Tax calculation
Qualy's v1 API calculates the tax for each payment intent generated from a subscription based on the total amount. The tax settings you define when creating the subscription will be applied to all future payment intents generated from this subscription.
Check our Tax API to retrieve and create taxes. Learn more about Tax calculation in our dedicated guide.
Settlement currency and FX (Currency exchange)
Sometimes you may want to create a subscription in a specific currency (e.g. USD) but you want the end-user to pay in another (e.g. EUR). This is useful in many cases, especially when you want Qualy to pay the suppliers in the original currency, and to convert it automatically at the time of payout.
Set the property settlementCurrency as your desired currency. When payment intents are generated from the subscription and the end-user tries to pay, it will only display the payment options of the specified settlementCurrency.
Qualy will automatically fetch the most up-to-date FX rate for each payment intent generated from the subscription.
Here's an example of creating a subscription with a different settlement currency:
curl -X POST https://api.qualyhq.com/v1/subscriptions/create \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "Annual Service Plan",
"mode": "schedule",
"description": {
"internal": "Premium support subscription",
"external": "Annual subscription for Premium Support"
},
"contact": "john.doe@example.com",
"amount": 120000,
"service": "Premium Support",
"currency": "USD",
"settlementCurrency": "EUR",
"billing": {
"startAt": "2026-10-01T00:00:00.000Z",
"endAt": "2027-10-01T00:00:00.000Z"
},
"schedule": {
"frequency": "every-month",
"dayOfMonth": 1
}
}'
const res = await fetch('https://api.qualyhq.com/v1/subscriptions/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'ApiKey your-api-key-here',
'X-TENANT-ID': 'your-tenant-id-here',
},
body: JSON.stringify({
name: 'Annual Service Plan',
mode: 'schedule',
description: {
internal: 'Premium support subscription',
external: 'Annual subscription for Premium Support',
},
contact: 'john.doe@example.com',
amount: 120000, // 1,200.00 in USD
service: 'Premium Support',
currency: 'USD',
settlementCurrency: 'EUR', // customer pays in EUR
billing: {
startAt: '2026-10-01T00:00:00.000Z',
endAt: '2027-10-01T00:00:00.000Z',
},
schedule: {
frequency: 'every-month',
dayOfMonth: 1,
},
}),
});
const { data: subscription } = await res.json();
console.log(subscription._id);
use Illuminate\Support\Facades\Http;
$subscription = Http::withHeaders([
'Authorization' => 'ApiKey your-api-key-here',
'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/subscriptions/create', [
'name' => 'Annual Service Plan',
'mode' => 'schedule',
'description' => [
'internal' => 'Premium support subscription',
'external' => 'Annual subscription for Premium Support',
],
'contact' => 'john.doe@example.com',
'amount' => 120000, // 1,200.00 in USD
'service' => 'Premium Support',
'currency' => 'USD',
'settlementCurrency' => 'EUR', // customer pays in EUR
'billing' => [
'startAt' => '2026-10-01T00:00:00.000Z',
'endAt' => '2027-10-01T00:00:00.000Z',
],
'schedule' => [
'frequency' => 'every-month',
'dayOfMonth' => 1,
],
])->json('data');
echo $subscription['_id'];
Monitoring subscription status
After creating a subscription, you can monitor its status through the Qualy dashboard or via API. The subscription object contains important tracking statistics:
"stats": {
"nPaymentsCreated": 2, // Number of payment intents created so far
"total": 240000, // Total amount expected over the subscription lifetime
"lastPaymentCreatedAt": "2025-11-01T00:00:00.000Z", // When the last payment was created
"nextPaymentDueAt": "2025-12-01T00:00:00.000Z" // When the next payment will be created
}
Linking services to subscriptions
When creating a subscription, you should specify the service field to indicate what service the subscription is for. This helps with reporting and organization within your Qualy account.
"service": "Premium Support" // A Service ObjectId or name
Managing payment intents from subscriptions
Once a subscription is created, Qualy will automatically generate payment intents based on the subscription schedule. These payment intents behave like any other payment intent in the system and can be managed through the standard Payment Intent API.
Important
Each payment intent generated from a subscription is editable until it's paid or canceled. This allows you to make adjustments to individual payments without affecting the overall subscription.
Subscription lifecycle
- Creation: When you create a subscription, no payment intents are immediately created
- First payment: On the schedule start date, the first payment intent is generated
- Recurring payments: Subsequent payment intents are automatically created based on your frequency settings
- End date: If specified, no new payment intents will be created after the subscription end date
Updating a subscription
You can update certain subscription parameters after creation by using the Subscription Update API.