1. App API
Salla Platform Docs
  • Get Started
  • Create Your First App
  • App Events
  • Handling Add-On Subscriptions
  • Root
  • App Snippets
    • Intro to App Snippets
    • HTML to JavaScript Snippet Migration
  • App Details Builder
    • Get Started
    • App Information
    • App Features
    • App Reviews
    • App Brands
    • App FAQ
    • App Statistics
  • Settings
    • App Setting Details
      GET
    • Update App Settings
      POST
  • Subscriptions
    • App Subscription Details
      GET
    • Subscription Renew
      POST
    • Update Subscription Balance
      POST
Merchant
Merchant
  • Merchant API
  • Embedded SDK
  • Salla OAuth 2.0
Storefront
Storefront
  • Twilight Engine
  • Twilight SDK
  • Web Components
  • Ecommerce Events
  • Component Bundle
  • Checkout APIs
  • Change Log
App Functions
Partner APIs
Partner APIs
  • App API
  • Shipments & Fulfillment APIs
  • Salla AWB
  • Recurring Payments API
  • Billing System Salla partners
  • Communication Apps
Dev Tools
Dev Tools
  • Partners Agent Kit
  • Salla Apps Playbook
  • Salla CLI
Merchant
Merchant
  • Merchant API
  • Embedded SDK
  • Salla OAuth 2.0
Storefront
Storefront
  • Twilight Engine
  • Twilight SDK
  • Web Components
  • Ecommerce Events
  • Component Bundle
  • Checkout APIs
  • Change Log
App Functions
Partner APIs
Partner APIs
  • App API
  • Shipments & Fulfillment APIs
  • Salla AWB
  • Recurring Payments API
  • Billing System Salla partners
  • Communication Apps
Dev Tools
Dev Tools
  • Partners Agent Kit
  • Salla Apps Playbook
  • Salla CLI
Salla - Opensource
Salla - Developers Community
  1. App API

Handling Add-On Subscriptions

Add-On Subscriptions: The Full Lifecycle#

Background reading
Before you build anything, read the Add-Ons Pricing article on Salla Developers. It covers how to configure add-on pricing for your app from the Partners Portal, separate from your main plan pricing.
Add-On Subscriptions is available by request only. Applications using it without prior approval may be rejected during review.
An add-on looks like a subscription, and the API tracks it as one, but it doesn't behave like your app's main plan. The biggest difference: for a recurring add-on, Salla doesn't bill the merchant on its own. You do.

The two types#

You choose this once, when you set up pricing in the Partners Portal. Everything else in this article depends on which one you picked.
One-time (once)
A single charge. You'll receive app.subscription.started once, and that's it, no renewal cycle exists for this type. Use that event to provision the feature for the merchant right away. The merchant can still cancel at any point, which sends app.subscription.canceled the same way it does for any other add-on.
Partner-recurring (external_recurring)
You own the billing cycle. Salla doesn't attempt a wallet deduction automatically, and doesn't store an end_date for it. You bill the merchant again yourself, on the monthly or yearly cadence they agreed to, and you'll receive app.subscription.renewed each time that succeeds.
Always check item_type before acting on any of these webhooks. The same event names fire for your app's base plan too. Skip the check and an add-on event can get processed as a base plan event, granting or revoking the wrong thing.

The full lifecycle#

Step by step#

1
Started
Fires once, the moment the merchant completes the purchase, for both one-time and partner-recurring add-ons. The event you'll receive is app.subscription.started.
Provision the feature for the merchant immediately when this arrives.
If the add-on involves a countable entitlement, credits, seats, requests, read quantity from the payload and record it on your side. Salla doesn't track usage. Whatever the merchant has used or has left is your responsibility from this point forward.
If the add-on is one-time, app.subscription.started is the only event you'll ever get for it. There's no renewal cycle to track, stop here.
2
Triggering Renewal
For partner-recurring add-ons, nothing renews on its own, you're the one who makes the call. No webhook tells you a cycle is due, that part is entirely on you to track.
The merchant agreed to a monthly or yearly cadence when they bought the add-on. Salla isn't holding an end_date to remind you, so track each merchant's next due date yourself based on when they started and the period they signed up for.
When a cycle is due, call:
POST https://api.salla.dev/admin/v2/apps/subscriptions/{subscription_id}/renew
The subscription_id here is the old subscription ID, the one from the merchant's most recent webhook event. Use the merchant's bearer token.
Don't call this before the cycle is actually due, and don't call it more than once for the same cycle. It's rate limited specifically to catch that, calling it early or repeatedly is what causes a double charge.
3
Renewal result: success or failure
The call you just made resolves one of two ways.
Success
Failure
The subscription is renewed for the period the merchant chose, monthly or yearly, and a new subscription_id is generated. The old subscription record moves to renewed status, the new one is active. You'll also receive app.subscription.renewed as confirmation, it arrives with the new subscription_id, update your entitlement to point at it.
Key your entitlement records on (merchant, item_slug), never on subscription_id. The ID changes every cycle, the merchant and the add-on slug don't. And don't revoke access when you see renewed, it means the cycle closed successfully, not that anything ended.
4
Canceled
The merchant can end the add-on at any point, regardless of which type it is, not just after a renewal. The event is app.subscription.canceled.
Revoke access as soon as it arrives. The merchant already knows why, no explanation needed on your end.

Confirming where things actually stand#

If your own records and what the merchant is telling you don't agree, check the App Subscriptions API directly:
GET https://api.salla.dev/admin/v2/apps/{app_id}/subscriptions
with the merchant's bearer token. Two statuses matter for add-ons:
StatusMeaning
activeThe add-on is live, the merchant has access.
renewedThis specific record was replaced by a new one this cycle. Access didn't end, it continued on the record that replaced it.
Modified at 2026-08-19 19:48:55
Previous
App Events
Next
Intro to App Snippets