curl --request PATCH \
--url https://api.bachs.io/v1/subscriptions/{subscription_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"product_id": "prod_premium",
"proration_behavior": "invoice_now"
}
'{
"id": "sub_1a2b3c4d5e6f",
"payment_method_id": "pm_7h8i9j0k",
"status": "active",
"collection_method": "charge_automatically",
"currency": "USD",
"amount": "10.00",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"quantity": 1,
"current_period_start": "2026-07-13T12:00:00Z",
"current_period_end": "2026-08-13T12:00:00Z",
"previously_billed_at": "2026-07-13T12:00:00Z",
"next_billed_at": "2026-08-13T12:00:00Z",
"trial_end": null,
"cancel_at_period_end": false,
"canceled_at": null,
"created_at": "2026-07-13T12:00:00Z",
"product": {
"id": "prod_abc123",
"name": "Pro plan",
"description": "Everything in Pro.",
"status": "active",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"trial_period": null,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
},
"items": [
{
"id": "si_11aa22bb",
"status": "active",
"quantity": 1,
"recurring": true,
"price_type": "fixed",
"unit_amount": "10.00",
"currency": "USD",
"previously_billed_at": "2026-07-13T12:00:00Z",
"next_billed_at": "2026-08-13T12:00:00Z",
"price": {
"id": "price_pro_usd",
"product_id": "prod_abc123",
"price_type": "fixed",
"currency": "USD",
"unit_amount": "10.00",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"trial_period": null,
"seat_tiers": null,
"is_archived": false,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
},
"product": {
"id": "prod_abc123",
"name": "Pro plan",
"status": "active",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"trial_period": null,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
},
"created_at": "2026-07-13T12:00:00Z",
"updated_at": "2026-07-13T12:00:00Z"
}
],
"customer": {
"customer_id": "cust_xyz789",
"email": "customer@example.com",
"name": "Jane Doe",
"phone_number": "+2348012345678",
"metadata": {},
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
}
}{
"detail": "Invalid request parameters",
"error_code": "VALIDATION_ERROR",
"errors": [
{
"field": "amount",
"message": "Amount must be a positive decimal string",
"type": "value_error"
}
]
}{
"detail": "Invalid API key",
"error_code": "UNAUTHORIZED"
}{
"detail": "API key does not have permission for this operation",
"error_code": "FORBIDDEN"
}{
"detail": "Resource not found",
"error_code": "NOT_FOUND"
}{
"detail": "Rate limit exceeded. Please retry after a few seconds.",
"error_code": "TOO_MANY_REQUESTS"
}{
"detail": "An unexpected error occurred. Please try again later.",
"error_code": "INTERNAL_SERVER_ERROR"
}Update a subscription
Change a subscription. Send exactly one intent: change the plan, move a trial, or change the payment method. Returns the full updated subscription.
curl --request PATCH \
--url https://api.bachs.io/v1/subscriptions/{subscription_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"product_id": "prod_premium",
"proration_behavior": "invoice_now"
}
'{
"id": "sub_1a2b3c4d5e6f",
"payment_method_id": "pm_7h8i9j0k",
"status": "active",
"collection_method": "charge_automatically",
"currency": "USD",
"amount": "10.00",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"quantity": 1,
"current_period_start": "2026-07-13T12:00:00Z",
"current_period_end": "2026-08-13T12:00:00Z",
"previously_billed_at": "2026-07-13T12:00:00Z",
"next_billed_at": "2026-08-13T12:00:00Z",
"trial_end": null,
"cancel_at_period_end": false,
"canceled_at": null,
"created_at": "2026-07-13T12:00:00Z",
"product": {
"id": "prod_abc123",
"name": "Pro plan",
"description": "Everything in Pro.",
"status": "active",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"trial_period": null,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
},
"items": [
{
"id": "si_11aa22bb",
"status": "active",
"quantity": 1,
"recurring": true,
"price_type": "fixed",
"unit_amount": "10.00",
"currency": "USD",
"previously_billed_at": "2026-07-13T12:00:00Z",
"next_billed_at": "2026-08-13T12:00:00Z",
"price": {
"id": "price_pro_usd",
"product_id": "prod_abc123",
"price_type": "fixed",
"currency": "USD",
"unit_amount": "10.00",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"trial_period": null,
"seat_tiers": null,
"is_archived": false,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
},
"product": {
"id": "prod_abc123",
"name": "Pro plan",
"status": "active",
"billing_cycle": {
"interval": "month",
"frequency": 1
},
"trial_period": null,
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
},
"created_at": "2026-07-13T12:00:00Z",
"updated_at": "2026-07-13T12:00:00Z"
}
],
"customer": {
"customer_id": "cust_xyz789",
"email": "customer@example.com",
"name": "Jane Doe",
"phone_number": "+2348012345678",
"metadata": {},
"created_at": "2026-07-01T09:00:00Z",
"updated_at": "2026-07-01T09:00:00Z"
}
}{
"detail": "Invalid request parameters",
"error_code": "VALIDATION_ERROR",
"errors": [
{
"field": "amount",
"message": "Amount must be a positive decimal string",
"type": "value_error"
}
]
}{
"detail": "Invalid API key",
"error_code": "UNAUTHORIZED"
}{
"detail": "API key does not have permission for this operation",
"error_code": "FORBIDDEN"
}{
"detail": "Resource not found",
"error_code": "NOT_FOUND"
}{
"detail": "Rate limit exceeded. Please retry after a few seconds.",
"error_code": "TOO_MANY_REQUESTS"
}{
"detail": "An unexpected error occurred. Please try again later.",
"error_code": "INTERNAL_SERVER_ERROR"
}Authorizations
Bearer token authentication. Pass your API key as Authorization: Bearer sk_.... See Authentication for keys, scopes, and sandbox vs production.
Path Parameters
The subscription's public ID (sub_...).
Body
A single change to a subscription. Send exactly one intent per request: change the plan (product_id), move a trial (trial_end), change the payment method (payment_method_id), or update metadata (metadata). Combining intents returns 400.
Move the subscription to this product (plan). The price is resolved from the product for the subscription's currency.
64"prod_xyz456"
Future = add/extend the trial; past-or-now = end it and bill now.
"2026-05-01T00:00:00Z"
Point the subscription at a different saved card. If past_due/unpaid, retries immediately. Stands alone.
64"pm_9f8e7d6c5b"
Merge key-value metadata into the subscription (up to 20 keys total). Sent keys are added or overwritten; a key sent with an empty-string value is removed; send an empty string ("") to clear all metadata. Stands alone: it cannot be combined with a plan, trial, or payment-method change.
{ "plan": "pro", "seat_count": "5" }
How a plan change is settled, and only meaningful alongside product_id. invoice_now: the change is settled straight away on a new invoice, and this is the default when you omit the field. next_cycle: the proration is accrued and drains into the next cycle's invoice. none: the plan changes with no proration charged or credited.
invoice_now, next_cycle, none "invoice_now"
Response
The updated subscription
Unique identifier for the subscription.
"sub_1a2b3c4d5e6f"
The customer billed on each renewal, expanded inline so you can show who is being charged without a second call.
Show child attributes
Show child attributes
The saved payment method billed on each renewal. null until a payment method is attached.
"pm_7h8i9j0k"
Status of the subscription. Set automatically by Bachs as payments succeed or fail. trialing: In a free trial. No payment has been collected yet. trial_end marks when billing begins. active: Active and paid. Bachs is billing this subscription automatically each cycle. past_due: A cycle payment failed. Bachs is retrying the payment while access continues. unpaid: Payment retries have been exhausted. Access should be restricted. canceled: Canceled and will not renew. This is a terminal state. paused: Temporarily suspended. Billing is halted until the subscription resumes.
trialing, active, past_due, unpaid, canceled, paused "active"
How renewals are collected. charge_automatically bills the saved card each cycle.
"charge_automatically"
The currency the subscription is billed in, as an ISO 4217 code. Subscriptions are USD only today.
"USD"
Recurring amount as a decimal string
"10.00"
How often the subscription renews, as an interval unit and a frequency, for example month with a frequency of 1 for monthly billing.
Show child attributes
Show child attributes
Total billable quantity across the subscription's line items.
1
Start of the period currently being billed for, in UTC.
"2026-04-01T00:00:00Z"
End of the period currently being billed for, in UTC. The next charge lands at this time unless the subscription is canceled first.
"2026-05-01T00:00:00Z"
Start of the period that was last billed
"2026-04-01T00:00:00Z"
Next scheduled charge date
"2026-05-01T00:00:00Z"
When the free trial ends and billing begins, in UTC. null if the subscription is not trialing.
"2026-04-15T00:00:00Z"
When true, the subscription stays active until current_period_end and is not renewed. When false, it renews normally.
false
When the subscription was canceled, in UTC. null if it has not been canceled.
null
When the subscription was created, in UTC.
"2026-03-01T12:00:00Z"
The catalog product this subscription bills for, or null when the subscription is not tied to a single product.
Show child attributes
Show child attributes
The line items that make up the subscription. Each item ties a product and its price to a billed quantity.
Show child attributes
Show child attributes
Your own key-value data attached to the subscription at creation, returned unchanged.
{ "plan": "pro", "seat_count": "5" }

