subscriptions
Stable. Describes behaviour that is built and covered by tests in this repository.
GET /v1/subscriptions #
Subscriptions, newest first
Parameters
| Name | In | Type | Description |
|---|---|---|---|
customer | query | string | Customer external id |
page_size | query | integer | |
page_token | query | string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | ListSubscriptionsResponse |
404 | Error envelope | Error |
Example response
{
"subscriptions": [
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}
],
"next_page_token": "string"
}curl
curl -X GET https://YOUR-API-ADDRESS/v1/subscriptions \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"POST /v1/subscriptions #
Subscribe a customer to a plan version (at most one overlapping subscription per customer)
Request body
| Field | Type | Description |
|---|---|---|
customer_external_id required | string | |
plan_code required | string | |
plan_version | integer | 0 = latest |
start_time | string · date-time | |
trial_days | integer | Left out: the package version's own default trial. 0: no trial whatever the default is |
interval | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | |
currency | string | Default is the customer's billing currency, then the tenant's |
provider | string | The payment provider that sells it (for example paddle); default is the tenant's default account |
coupon_code | string | A coupon to redeem on the new subscription |
quantity | integer | Seats: the fixed fee is multiplied by it, usage prices are not. Default 1. Only for a subscription Payrudder runs and bills in advance |
fee_timing | FEE_TIMING_ADVANCE | FEE_TIMING_ARREARS | Default advance: the fixed fee is invoiced at the start of each period, usage at the close of the month. Arrears (monthly only) bills the fee with the month's usage. A provider that renews subscriptions itself bills the fee. |
Example
{
"customer_external_id": "string",
"plan_code": "string"
}Responses
| Status | Meaning | Body |
|---|---|---|
201 | Created | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions \
-H "Authorization: Bearer $PAYRUDDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customer_external_id":"string","plan_code":"string"}'GET /v1/subscriptions/{id} #
One subscription with its state
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X GET https://YOUR-API-ADDRESS/v1/subscriptions/<id> \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"DELETE /v1/subscriptions/{id} #
End a subscription (now, or at end_time)
With credit_unused=true the fee paid in advance for the rest of the current period is credited to the customer's balance (for a subscription billed in advance that Payrudder runs, ended now, without a coupon). The response is always {subscription, credited_minor}; credited_minor is "0" when nothing was credited.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid | |
end_time | query | string · date-time | |
credit_unused | query | boolean |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | CancelSubscriptionResponse |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"subscription": {
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
},
"credited_minor": "string"
}curl
curl -X DELETE https://YOUR-API-ADDRESS/v1/subscriptions/<id> \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"POST /v1/subscriptions/{id}/pause #
Stop the fixed fee until the subscription is resumed (usage is still billed)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/pause \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"POST /v1/subscriptions/{id}/resume #
Resume a paused subscription
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/resume \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"POST /v1/subscriptions/{id}/cancel-at-period-end #
End the subscription at the end of its current billing period
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/cancel-at-period-end \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"DELETE /v1/subscriptions/{id}/cancel-at-period-end #
Withdraw a scheduled cancellation
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X DELETE https://YOUR-API-ADDRESS/v1/subscriptions/<id>/cancel-at-period-end \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"POST /v1/subscriptions/{id}/change-plan #
Move the subscription to another plan version now, prorating the fixed fee
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Request body
| Field | Type | Description |
|---|---|---|
plan_code required | string | |
plan_version | integer | 0 = latest |
change_time | string · date-time | Default now |
Example
{
"plan_code": "string"
}Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | ChangePlanResponse |
400 | Error envelope | Error |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"subscription": {
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
},
"old_plan_fee_minor": "string",
"new_plan_fee_minor": "string"
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/change-plan \
-H "Authorization: Bearer $PAYRUDDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"plan_code":"string"}'POST /v1/subscriptions/{id}/change-preview #
What a change of plan or interval would cost, without making it
The same calculation as the change itself, so the preview is what is then billed. For subscriptions whose fee is invoiced in advance.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Request body
| Field | Type | Description |
|---|---|---|
plan_code | string | Empty keeps the plan (to change the interval only) |
plan_version | integer | 0 = latest |
interval | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | Default keeps the interval |
timing | CHANGE_TIMING_IMMEDIATELY | CHANGE_TIMING_PERIOD_END | Default depends on the direction of the change |
proration | CHANGE_PRORATION_PRORATE | CHANGE_PRORATION_FULL | CHANGE_PRORATION_NONE | Default prorate. Prorate keeps the cycle within an interval; full starts a new cycle now; none moves no money now |
change_time | string · date-time | Default now; not in the future |
quantity | integer | The new number of seats; 0 or absent keeps it. A change of seats alone is immediate and prorated in either direction unless timing says otherwise: the unused time of the old seats is credited and the new seats are charged for the rest of the period |
Example
{}Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | ChangeQuote |
400 | Error envelope | Error |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"timing": "CHANGE_TIMING_IMMEDIATELY",
"proration": "CHANGE_PRORATION_PRORATE",
"effective_time": "2026-11-03T10:15:00Z",
"period_start": "2026-11-03T10:15:00Z",
"period_end": "2026-11-03T10:15:00Z",
"credit_minor": "string",
"charge_minor": "string",
"net_minor": "string",
"currency": "string",
"next_renewal_time": "2026-11-03T10:15:00Z",
"next_renewal_minor": "string",
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"quantity": 1
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/change-preview \
-H "Authorization: Bearer $PAYRUDDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'POST /v1/subscriptions/{id}/change #
Move a subscription to another plan version and/or interval, now or at the end of the paid period
An upgrade or monthly-to-yearly change is immediate and prorated; a downgrade or yearly-to-monthly change waits for the end of the period the customer has paid for
(a scheduled change, shown on the subscription). A change of quantity alone is immediate and prorated, more seats or fewer. Whatever moves money is invoiced, or becomes a credit balance when the new plan costs less than the unused old time was worth.
Answers 409 ABORTED if the fee of the current period has not been invoiced yet; try again in a moment.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Request body
| Field | Type | Description |
|---|---|---|
plan_code | string | Empty keeps the plan (to change the interval only) |
plan_version | integer | 0 = latest |
interval | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | Default keeps the interval |
timing | CHANGE_TIMING_IMMEDIATELY | CHANGE_TIMING_PERIOD_END | Default depends on the direction of the change |
proration | CHANGE_PRORATION_PRORATE | CHANGE_PRORATION_FULL | CHANGE_PRORATION_NONE | Default prorate. Prorate keeps the cycle within an interval; full starts a new cycle now; none moves no money now |
change_time | string · date-time | Default now; not in the future |
quantity | integer | The new number of seats; 0 or absent keeps it. A change of seats alone is immediate and prorated in either direction unless timing says otherwise: the unused time of the old seats is credited and the new seats are charged for the rest of the period |
Example
{}Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | ChangeSubscriptionResponse |
400 | Error envelope | Error |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"subscription": {
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
},
"quote": {
"timing": "CHANGE_TIMING_IMMEDIATELY",
"proration": "CHANGE_PRORATION_PRORATE",
"effective_time": "2026-11-03T10:15:00Z",
"period_start": "2026-11-03T10:15:00Z",
"period_end": "2026-11-03T10:15:00Z",
"credit_minor": "string",
"charge_minor": "string",
"net_minor": "string",
"currency": "string",
"next_renewal_time": "2026-11-03T10:15:00Z",
"next_renewal_minor": "string",
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"quantity": 1
},
"scheduled": false
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/change \
-H "Authorization: Bearer $PAYRUDDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'POST /v1/subscriptions/{id}/coupon #
Redeem a coupon on a subscription that has none
A coupon takes something off a fixed fee Payrudder invoices in advance. A subscription a provider renews uses a discount at the provider instead.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Request body
| Field | Type | Description |
|---|---|---|
code required | string |
Example
{
"code": "string"
}Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
400 | Error envelope | Error |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X POST https://YOUR-API-ADDRESS/v1/subscriptions/<id>/coupon \
-H "Authorization: Bearer $PAYRUDDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"code":"string"}'DELETE /v1/subscriptions/{id}/coupon #
Take the coupon off a subscription (the redemption is not given back)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X DELETE https://YOUR-API-ADDRESS/v1/subscriptions/<id>/coupon \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"DELETE /v1/subscriptions/{id}/scheduled-change #
Withdraw the change waiting for the end of the period
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string · uuid |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | Subscription |
404 | Error envelope | Error |
409 | Error envelope | Error |
Example response
{
"id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"customer_external_id": "string",
"plan_version_id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
"start_time": "2026-11-03T10:15:00Z",
"end_time": null,
"create_time": "2026-11-03T10:15:00Z",
"state": "SUBSCRIPTION_STATE_TRIALING",
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"currency": "string",
"trial_end_time": null,
"cancel_at_period_end": false,
"pause_time": null,
"provider": "string",
"provider_ref": "string",
"owner": "payrudder",
"plan_code": "string",
"plan_version": 1,
"fee_timing": "FEE_TIMING_ADVANCE",
"scheduled_change": {
"plan_code": "string",
"plan_version": 1,
"interval": "SUBSCRIPTION_INTERVAL_MONTH",
"effective_time": "2026-11-03T10:15:00Z",
"quantity": 1
},
"coupon_code": "string",
"quantity": 1,
"changed_from_id": "string"
}curl
curl -X DELETE https://YOUR-API-ADDRESS/v1/subscriptions/<id>/scheduled-change \
-H "Authorization: Bearer $PAYRUDDER_API_KEY"Models
ApplyCouponRequest
| Field | Type | Description |
|---|---|---|
code required | string |
CancelSubscriptionResponse
| Field | Type | Description |
|---|---|---|
subscription required | Subscription | |
credited_minor required | string · int64 | Minor units of the subscription's currency credited to the customer; "0" unless credit_unused credited something |
ChangePlanRequest
| Field | Type | Description |
|---|---|---|
plan_code required | string | |
plan_version | integer | 0 = latest |
change_time | string · date-time | Default now |
ChangePlanResponse
| Field | Type | Description |
|---|---|---|
subscription required | any | |
old_plan_fee_minor required | string · int64 | The old plan's share of the current month's fixed fee, up to change_time (informational; billing recomputes it) |
new_plan_fee_minor required | string · int64 | The new plan's share of the current month's fixed fee, from change_time (informational; billing recomputes it) |
ChangeQuote
| Field | Type | Description |
|---|---|---|
timing required | CHANGE_TIMING_IMMEDIATELY | CHANGE_TIMING_PERIOD_END | |
proration required | CHANGE_PRORATION_PRORATE | CHANGE_PRORATION_FULL | CHANGE_PRORATION_NONE | |
effective_time required | string · date-time | |
period_start required | string · date-time | |
period_end required | string · date-time | |
credit_minor required | string · int64 | The unused, prepaid part of the old fee |
charge_minor required | string | What the new plan costs from the change, format: int64 |
net_minor required | string · int64 | charge - credit: positive is invoiced, negative becomes a credit balance |
currency required | string | |
next_renewal_time required | string · date-time | |
next_renewal_minor required | string · int64 | |
plan_code required | string | |
plan_version required | integer | |
interval required | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | |
quantity required | integer | The seats after the change |
ChangeRequest
| Field | Type | Description |
|---|---|---|
plan_code | string | Empty keeps the plan (to change the interval only) |
plan_version | integer | 0 = latest |
interval | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | Default keeps the interval |
timing | CHANGE_TIMING_IMMEDIATELY | CHANGE_TIMING_PERIOD_END | Default depends on the direction of the change |
proration | CHANGE_PRORATION_PRORATE | CHANGE_PRORATION_FULL | CHANGE_PRORATION_NONE | Default prorate. Prorate keeps the cycle within an interval; full starts a new cycle now; none moves no money now |
change_time | string · date-time | Default now; not in the future |
quantity | integer | The new number of seats; 0 or absent keeps it. A change of seats alone is immediate and prorated in either direction unless timing says otherwise: the unused time of the old seats is credited and the new seats are charged for the rest of the period |
ChangeSubscriptionResponse
| Field | Type | Description |
|---|---|---|
subscription required | any | |
quote required | any | |
scheduled required | boolean | True when the change waits for the end of the period |
CreateSubscriptionRequest
| Field | Type | Description |
|---|---|---|
customer_external_id required | string | |
plan_code required | string | |
plan_version | integer | 0 = latest |
start_time | string · date-time | |
trial_days | integer | Left out: the package version's own default trial. 0: no trial whatever the default is |
interval | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | |
currency | string | Default is the customer's billing currency, then the tenant's |
provider | string | The payment provider that sells it (for example paddle); default is the tenant's default account |
coupon_code | string | A coupon to redeem on the new subscription |
quantity | integer | Seats: the fixed fee is multiplied by it, usage prices are not. Default 1. Only for a subscription Payrudder runs and bills in advance |
fee_timing | FEE_TIMING_ADVANCE | FEE_TIMING_ARREARS | Default advance: the fixed fee is invoiced at the start of each period, usage at the close of the month. Arrears (monthly only) bills the fee with the month's usage. A provider that renews subscriptions itself bills the fee. |
Error
| Field | Type | Description |
|---|---|---|
error required | object |
ListSubscriptionsResponse
| Field | Type | Description |
|---|---|---|
subscriptions required | array of Subscription | |
next_page_token required | string |
ScheduledChange
| Field | Type | Description |
|---|---|---|
plan_code required | string | |
plan_version required | integer | |
interval required | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | |
effective_time required | string · date-time | |
quantity required | integer | The seats the subscription has from then |
Subscription
| Field | Type | Description |
|---|---|---|
id required | string · uuid | |
customer_id required | string · uuid | |
customer_external_id required | string | |
plan_version_id required | string · uuid | |
start_time required | string · date-time | |
end_time required | string,null · date-time | |
create_time required | string · date-time | |
state required | SUBSCRIPTION_STATE_TRIALING | SUBSCRIPTION_STATE_ACTIVE | SUBSCRIPTION_STATE_PAST_DUE | SUBSCRIPTION_STATE_PAUSED | SUBSCRIPTION_STATE_CANCELLED | |
interval required | SUBSCRIPTION_INTERVAL_MONTH | SUBSCRIPTION_INTERVAL_YEAR | |
currency required | string | |
trial_end_time required | string,null · date-time | |
cancel_at_period_end required | boolean | |
pause_time required | string,null · date-time | |
provider required | string | |
provider_ref required | string | The provider's id of the subscription, once it is linked |
owner required | payrudder | provider | Who renews it and retries failed renewals; a provider-owned subscription is changed at the provider |
plan_code required | string | |
plan_version required | integer | |
fee_timing required | FEE_TIMING_ADVANCE | FEE_TIMING_ARREARS | |
scheduled_change required | any | |
coupon_code required | string | |
quantity required | integer | Seats: a plain multiplier of the plan's fixed fee, 1 unless set |
changed_from_id required | string |