For the complete documentation index, see llms.txt. This page is also available as Markdown.

Subscriptions

Work with auto-renewable subscriptions in OnsideKit: detect them, read the billing period, then purchase, restore, and validate them like any other product.

An auto-renewable subscription is an OnsideProduct like any other — you fetch it, purchase it, restore it, and validate it through the exact same APIs as a consumable or non-consumable. What sets a subscription apart is a small set of subscription-only properties describing its billing period.

The OnsideKit subscription API is intentionally small. Renewals, cancellations, upgrades, billing retries, and the subscription-management UI are handled by the Onside app and your backend — not by the SDK. In your app you only fetch, display, sell, restore, and validate subscriptions; everything on this page covers exactly that.

Detecting a subscription

A product is a subscription when its subscriptionPeriod is non-nil. That single check distinguishes a subscription from a one-time product:

if let period = product.subscriptionPeriod {
    // Subscription — billed once every `period`.
} else {
    // One-time product (consumable or non-consumable).
}

Subscription properties

These properties live on OnsideProduct. subscriptionPeriod and subscriptionGroupIdentifier are populated only for subscriptions and are nil on a one-time product. price is non-optional and present on every product; for a subscription it is the recurring per-period charge.

Property
Description

subscriptionPeriod: OnsidePeriod?

The recurring billing period. Non-nil only for subscriptions — use it to detect one.

subscriptionGroupIdentifier: String?

The subscription group the product belongs to.

price: OnsidePrice

The product price. For a subscription, the amount charged each billing period.

The pricing types

struct OnsidePrice {
    var value: Double
    var currencyCode: String   // ISO 4217, e.g. "EUR"
}

enum OnsidePeriod {
    case day(UInt)
    case week(UInt)
    case month(UInt)
    case year(UInt)
}
  • OnsidePrice — a numeric amount plus an ISO-4217 currency code.

  • OnsidePeriod — a unit with a count, e.g. .month(1) (monthly) or .year(1) (yearly).

Displaying a subscription

Combine the recurring price with the period:

OnsidePeriod is a resilient (non-frozen) enum — keep an @unknown default in every switch so your code stays forward-compatible with future cases. See Threading & Object Lifetime.

Purchasing a subscription

Buying a subscription is identical to buying any other product: wrap it in an OnsidePayment and add it to the payment queue. The resulting transaction flows through your observer with the same states (.purchasing, .purchased, .failed).

See Making a Purchase for the full flow — processing the transaction, finishing it, and the storefront safety gate.

Restoring a subscription

A subscription is restorable, just like a non-consumable. When the user reinstalls your app or switches devices, restoreCompletedTransactions(completion:) re-delivers it as a .restored transaction. See Restoring Purchases.

A renewal can also arrive unprompted: the payment queue reconciles it from the server and delivers it to your observer like any other transaction, so process and finish it the same way. See Transactions can appear without an explicit purchase.

Validating a subscription

The authoritative subscription status — whether it is active, when the current period expires, and whether it was cancelled — lives on the server. Verify it from your backend through the Merchant API: a subscription transaction carries an expires_at and a product_type of "SUBSCRIPTION".

Testing subscriptions locally

You can define subscriptions in a .storekit file and exercise the whole fetch → purchase → restore flow offline, with no backend. See Local Testing with a .storekit File.

Last updated

Was this helpful?