Subscriptions
A customer's recurring commitment to one or more prices, billed at the end of each period.
See the subscriptions guide for the billing model, trials and dunning.
The subscription object
idstring
Prefixed
sub_.objectstring
subscriptioncustomerstring
statusenum
trialing, active, past_due, unpaid, canceled or paused.collection_methodenum
charge_automatically (saved card) or send_invoice (bank invoice).days_until_dueinteger | null
For
send_invoice.current_period_starttimestamp
current_period_endtimestamp
When the next invoice is issued.
cancel_at_period_endboolean
canceled_attimestamp | null
ended_attimestamp | null
trial_starttimestamp | null
trial_endtimestamp | null
pause_collectionobject | null
discountobject | null
amount_off or percent_off, duration.itemsarray
metadataobject
created_attimestamp
updated_attimestamp
Create a subscription
POST/v1/subscriptionsSecret key
The customer needs a default payment method for charge_automatically, or a kennitala for send_invoice. All items must share an interval and a currency, and at least one must be recurring.
Body
customerstringrequired
itemsarrayrequired
One or more
{ price, quantity?, credit_rollover?, included_units?, metadata? }.collection_methodenumdefault: charge_automatically
charge_automatically or send_invoice.trial_period_daysinteger
Free days before the first paid period.
days_until_dueinteger
For
send_invoice: days the customer has to pay each invoice.discountobject
{ amount_off?, percent_off?, duration: "once" }.metadataobject
Node.jsts
// The customer already has a saved card (payment_method.attached fired).
const subscription = await borga.subscriptions.create({
customer: "cus_8Jk2Lm4Np6Qr8St0Uv2Wx4Yz",
items: [{ price: "price_2Ab4Cd6Ef8Gh0Ij2Kl4Mn6Op", quantity: 3 }],
collection_method: "charge_automatically",
trial_period_days: 14,
metadata: { plan: "pro" },
});
console.log(subscription.status); // "trialing"
console.log(subscription.current_period_end);curlbash
curl https://api.borga.is/v1/subscriptions \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"customer": "cus_8Jk2Lm4Np6Qr8St0Uv2Wx4Yz",
"items": [{ "price": "price_2Ab4Cd6Ef8Gh0Ij2Kl4Mn6Op", "quantity": 3 }],
"collection_method": "charge_automatically",
"trial_period_days": 14
}'Response
{
"id": "sub_9Qw1Er3Ty5Ui7Op9As1Df3Gh",
"object": "subscription",
"customer": "cus_8Jk2Lm4Np6Qr8St0Uv2Wx4Yz",
"status": "trialing",
"collection_method": "charge_automatically",
"days_until_due": null,
"current_period_start": "2026-09-07T12:00:00.000Z",
"current_period_end": "2026-09-21T12:00:00.000Z",
"cancel_at_period_end": false,
"canceled_at": null,
"ended_at": null,
"trial_start": "2026-09-07T12:00:00.000Z",
"trial_end": "2026-09-21T12:00:00.000Z",
"pause_collection": null,
"discount": null,
"metadata": { "plan": "pro" },
"items": [
{
"id": "si_5Zx7Cv9Bn1Mq3We5Rt7Yu9Io",
"object": "subscription_item",
"subscription": "sub_9Qw1Er3Ty5Ui7Op9As1Df3Gh",
"price": "price_2Ab4Cd6Ef8Gh0Ij2Kl4Mn6Op",
"quantity": 3,
"credit_rollover": false,
"included_units": null,
"metadata": {},
"created_at": "2026-09-07T12:00:00.000Z",
"updated_at": "2026-09-07T12:00:00.000Z"
}
],
"created_at": "2026-09-07T12:00:00.000Z",
"updated_at": "2026-09-07T12:00:00.000Z"
}Errors: invalid_subscription, invalid_price_type, resource_not_found.
Retrieve a subscription
GET/v1/subscriptions/:idSecret key
Update a subscription
POST/v1/subscriptions/:idSecret key
Change items through subscription items.
Body
cancel_at_period_endboolean
discountobject | null
Set a discount or
null to remove it.collection_methodenum
days_until_dueinteger
metadataobject
Cancel a subscription
POST/v1/subscriptions/:id/cancelSecret key
Body
at_period_endbooleandefault: false
true keeps the subscription active until current_period_end, bills the final period, then cancels. false ends it immediately.Uncancel a subscription
POST/v1/subscriptions/:id/uncancelSecret key
Clears cancel_at_period_end. Fails with cannot_uncancel if no cancellation is pending.
Pause a subscription
POST/v1/subscriptions/:id/pauseSecret key
Stops billing. Fails with cannot_pause unless the subscription is active or trialing.
Resume a subscription
POST/v1/subscriptions/:id/resumeSecret key
Fails with not_paused if the subscription is not paused.
List subscriptions
GET/v1/subscriptionsSecret key
Query parameters
customerstring
statusenum
limitintegerdefault: 25
starting_afterstring
Node.jsts
const id = "sub_9Qw1Er3Ty5Ui7Op9As1Df3Gh";
// Change seats; Borga prorates the difference on the next invoice.
const [item] = (await borga.subscriptions.retrieve(id)).items;
await borga.subscriptionItems.update(item.id, {
quantity: 5,
proration_behavior: "create_prorations",
});
// Add a one-off charge to the next invoice.
await borga.invoiceItems.create({
customer: "cus_8Jk2Lm4Np6Qr8St0Uv2Wx4Yz",
subscription: id,
amount: 15000,
description: "Onboarding workshop",
});
// Cancel when the period ends (reversible with uncancel).
await borga.subscriptions.cancel(id, { at_period_end: true });
await borga.subscriptions.uncancel(id);
// Pause and resume billing.
await borga.subscriptions.pause(id);
await borga.subscriptions.resume(id);