API Reference
Subscriptions API
Product subscription settings, lease access, keep-your-products bundle ownership, and the current managed renewal and recovery policy.
SoundSync
Developer settings endpoints
These are developer-authenticated and mutate product subscription configuration.
/api/developer/products/:productId/subscription-settings
Return beta product subscription settings for a developer-owned product.
- Auth
- Account Bearer JWT
- Scope
- Developer-owned product settings.
- Returns
- settings { enabled, billingInterval, trialDays, failedPaymentGraceDays, cancellationBehavior }, betaEnabled.
- Side effects
- Ensures a product_subscription_settings row exists for the product.
Request, response and error reference
No request body fields are read by this operation.
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"settings": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"billingInterval": {
"type": "string",
"enum": [
"monthly",
"yearly"
]
},
"trialDays": {
"type": "integer",
"enum": [
0,
7,
14,
30
]
},
"failedPaymentGraceDays": {
"type": "integer",
"enum": [
0,
3,
7,
14
]
},
"cancellationBehavior": {
"type": "string",
"enum": [
"access_until_period_end",
"lock_immediately"
]
}
},
"additionalProperties": true
},
"betaEnabled": {
"type": "boolean"
}
},
"additionalProperties": true
}
Documented failures: 400, 500, 503.
/api/developer/products/:productId/subscription-settings
Update product subscription settings.
- Auth
- Account Bearer JWT
- Scope
- Developer-owned product settings.
- Request fields
- enabled: boolean
- billingInterval: monthly | yearly
- trialDays: 0 | 7 | 14 | 30
- failedPaymentGraceDays: 0 | 3 | 7 | 14
- cancellationBehavior: access_until_period_end | lock_immediately
- Returns
- Updated settings and betaEnabled.
- Side effects
- Writes subscription settings and records product setup activity.
- Notes
- This is a mutation and is not used during read-only screenshot capture. These are supported settings inputs, not authority to override the managed fourteen_days_v1 recovery policy. Review the subscription recovery guide for effective deadlines. Changing monthly/yearly cadence with active, trialing, past_due or unpaid standalone or linked bundle contracts returns 409 SUBSCRIPTION_BILLING_INTERVAL_LOCKED. Keep existing contracts on their cadence and create a separate offer for the new interval. This is a settings replacement, not a sparse PATCH: omitted enabled defaults false, billingInterval monthly, trialDays 0, failedPaymentGraceDays 14 and cancellationBehavior access_until_period_end. Read current settings and send the intended complete values. Legacy lock_immediately can be stored, but managed customer cancellation remains effective at paid-period end; legacy grace input does not replace fourteen_days_v1 recovery.
Request, response and error reference
Request (application/json)
{
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"billingInterval": {
"type": "string",
"enum": [
"monthly",
"yearly"
]
},
"trialDays": {
"type": "integer",
"enum": [
0,
7,
14,
30
]
},
"failedPaymentGraceDays": {
"type": "integer",
"enum": [
0,
3,
7,
14
]
},
"cancellationBehavior": {
"type": "string",
"enum": [
"access_until_period_end",
"lock_immediately"
]
}
},
"additionalProperties": true
}
HTTP 200 response (application/json)
{
"type": "object",
"properties": {
"settings": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"billingInterval": {
"type": "string",
"enum": [
"monthly",
"yearly"
]
},
"trialDays": {
"type": "integer",
"enum": [
0,
7,
14,
30
]
},
"failedPaymentGraceDays": {
"type": "integer",
"enum": [
0,
3,
7,
14
]
},
"cancellationBehavior": {
"type": "string",
"enum": [
"access_until_period_end",
"lock_immediately"
]
}
},
"additionalProperties": true
},
"betaEnabled": {
"type": "boolean"
}
},
"additionalProperties": true
}
Documented failures: 400, 500, 409, 503.
Operation errors: SUBSCRIPTION_BILLING_INTERVAL_LOCKED.
SoundSync
Verified subscription states
Only states normalized by the implementation are listed.
| State | Billing meaning | Customer access | Plugin access | Download access | Offline grace |
|---|---|---|---|---|---|
| incomplete | Stripe subscription setup has not completed. | No durable customer access until checkout completes. | Plugin should remain locked. | No protected downloads. | No offline grace. |
| trialing | Trial period is active. | Temporary access follows the eligible trial entitlement; a trial alone does not earn permanent ownership. | Plugin access follows entitlement/subscription payload. | Downloads follow the eligible trial entitlement. | Follow the installed package policy, not an extra client-created grace period. |
| active | Recurring billing is active. | Customer access is allowed. | Plugin access is allowed unless another denial applies. | Downloads are allowed. | Grace follows product validation rules. |
| past_due | Payment failed; the managed 14-day payment-recovery episode may still be active. | Use the server recovery deadline and entitlement state, not a legacy settings value. | Plugin may return subscription_payment_required after recovery ends. | Downloads follow the applicable entitlement and earned ownership. | Do not invent extra grace locally. |
| unpaid | Stripe marks subscription unpaid. | Lease access follows the managed recovery episode and access deadline. Previously earned keep-products ownership and independent purchases are separate. | Locks only the affected inactive entitlement; do not revoke unrelated or already earned ownership. | Downloads follow each product entitlement and earned ownership. | No offline grace for an explicit denial of the affected access. |
| canceled | Future renewal ended or is scheduled to end. | Lease access can remain through the paid-through date. Unreversed permanent products earned through keep_products remain owned. | Use the current product entitlement, not cancellation alone. | Downloads remain available for eligible paid-through or permanent product access. | No offline grace for an explicit denial of the affected access. |
Stripe billing and verified lifecycle events
Subscription checkout uses Stripe, not PayPal. Verified checkout, invoice payment/failure, subscription changes, and supported payment-method setup events drive renewal and recovery. A browser return alone does not prove payment or permanent ownership. Use the current subscription and invoice state before retrying collection.
SoundSync
Two subscription models
Selected products versus all products describes bundle membership, not a third ownership model. A trial, unpaid invoice, or manually granted access is not proof of permanent paid ownership.
| Model | Offer and API value | What the customer keeps |
|---|---|---|
| Own the products | Subscription bundle with fulfillmentMode: keep_products | Qualifying paid invoices earn permanent ownership under the plan. Ending future billing does not erase already earned products; a reversal of the qualifying payment can reverse that ownership. |
| Lease the products | Standalone product subscription, or subscription bundle with fulfillmentMode: access | Recurring access while entitled. Cancellation preserves the paid-through period. An unresolved recovery suspends the license while billing continues; cancel separately to stop future renewals. Separate purchases are unaffected. |
A fixed payment-recovery window
An unpaid renewal starts a 14-day recovery episode. Reminder opportunities fall on days 0, 5, 10, and 13, subject to eligibility and delivery readiness. Customers can update their payment method from their account. Eligible automatic collection attempts remain subject to provider limits and the current payment state; this is not a promise of a charge attempt every day.
Rental suspension is not subscription cancellation
After the 14-day recovery deadline, an unpaid rental/access subscription has its license suspended, not automatically canceled. The subscription and billing continue, further renewal invoices can arise, and eligible recovery of outstanding payments continues. Suspension does not stop billing or forgive unpaid invoices. Customers who want to stop future renewals must use the supported cancellation action; cancellation does not erase an existing balance.
Rental access is restored after provider-confirmed payment and reconciliation of all outstanding invoices. A newer paid invoice alone does not clear older arrears. Closed or uncertain invoices can require billing review rather than automatic restoration.
A keep-your-products plan has a different outcome: an unresolved renewal can end the recurring subscription after reconciliation, while products already earned from unreversed qualifying payments remain owned. No new permanent products are earned from an unpaid invoice. Pending or uncertain payments are reconciled before another collection attempt; do not start another checkout to bypass recovery. Plugin enforcement follows the installed package and its signed offline/online rules, not an instant remote change to every distributed binary.
Settings and effective recovery are different
The product-settings endpoint accepts legacy failedPaymentGraceDays values 0, 3, 7, and 14. New settings default to 14. The managed renewal/recovery policy uses the server-issued 14-day episode and returned access state; do not shorten or extend it in a client from a legacy setting. Payment-recovery grace and a plugin package's offline grace are different clocks.
SoundSync
Use the contract for the right action
Keep existing subscribers on their billing interval
Monthly and annual offers use different billing cadences. If a standalone subscription or a linked subscription bundle has active, trialing, past_due or unpaid contracts, changing its monthly/yearly interval is blocked. Create a separate offer for the new cadence rather than changing the period beneath current subscribers.
The settings and versioned-bundle APIs return 409 SUBSCRIPTION_BILLING_INTERVAL_LOCKED for this condition. Reload the existing offer and retain its interval. This guard does not convert ownership models, cancel existing subscriptions or migrate payment-provider billing authority.
Saved compatibility settings and effective lifecycle rules
PUT /api/developer/products/{productId}/subscription-settings replaces normalized settings; it is not a sparse PATCH. Read the current settings first and send the complete intended values. Omitted enabled defaults to false, billingInterval to monthly, trialDays to 0, failedPaymentGraceDays to 14 and cancellationBehavior to access_until_period_end.
Legacy cancellationBehavior:lock_immediately can still be accepted and stored, but managed customer cancellation takes effect at paid-period end. Legacy grace settings do not replace the managed fourteen_days_v1 failed-payment recovery policy. Read the effective subscription/recovery state rather than treating a compatibility field as permission to shorten paid access.
Permanent gifts and paid subscription ownership
A timed manual keep-products grant gives the customer permanent ownership of the products included when the developer makes that grant, without a payment. That original product snapshot remains owned after subscription cancellation, expiry or incomplete billing setup. Explicit developer access removal can revoke the grant. New products added later are not retroactively included.
A lifetime manual grant instead provides complimentary ongoing subscription access; it is not the timed-grant ownership model or evidence of a paid invoice. Ordinary access-only grants and unpaid checkout trials also do not create paid ownership.
Paid keep-products invoices establish their own product snapshots. Refunding or reversing a paid purchase affects that purchase, not an independent manual ownership grant. Future paid subscription benefits still require the separate billing setup, preview and customer confirmation; a gift is not permission to charge a card.
