Subscription infrastructure

Ship the paywall. We'll do the rest.

Kebabty is the subscription layer for mobile apps — StoreKit purchases validated on our servers before they're finished, paywalls you change without an App Store release, and revenue numbers that agree with the stores.

iOS · StoreKit 2 native Android with Play Billing next No credit card to start
MRR
$48,320
+6.4%
Premium.tsx SDK 0.3
import { Kebabty } from '@kebabty/react-native'

await Kebabty.configure({ apiKey: 'pk_kbty_…' })

// entitlements, straight off the profile
const { entitlements } = await Kebabty.getProfile()
if (entitlements.premium?.isActive) unlock()

// or let the dashboard decide what to show
const res = await Kebabty.fire('PREMIUM_LOCKED')
01
The platform

Everything between the tap
and the receipt.

One SDK call in the app, one dashboard for everything the app shouldn't have to know: who is entitled, what they see, what it earned, and where that has to be forwarded.

Entitlements in one line

Ask the profile whether the customer is in. Grace periods, billing retries, refunds and Family Sharing are already folded into the answer before your code sees it.

entitlements.premium?.isActive

A purchase finishes last

The StoreKit transaction is only finished once our server has recorded it. One that never landed stays unfinished, and the next launch retries it — a paid customer can't quietly end up with nothing.

no silent revenue loss

Action keys, not releases

Put PREMIUM_LOCKED in your code once. Which paywall it opens, for which audience, in which experiment arm — every part of that answer lives server-side.

ship copy, price and layout mid-review

One event taxonomy

Apple's V2 notifications and Google's RTDN arrive signature-verified and land on one set of names, so a trial that converted reads the same on both stores.

trial_converted · entered_grace_period · subscription_refunded

Audiences that show their work

Build a rule, see the reach with its denominator attached — 24% of 5,000 profiles, never a bare percentage that could mean anything.

country · version · attributes · entitlement state

Your stack, still yours

Processed events go out to webhooks, Amplitude, AppsFlyer or Meta CAPI — or the store's own payload, byte-for-byte, if you'd rather parse it yourself.

durable delivery · retried for ~8 hours
02
Paywalls

Change the offer
while the app
sits in review.

Pick a template, edit it against a live phone preview, publish. The device gets flat, localized strings and renders — every decision was already made on the server.

  • Prices in the customer's own currency, read from StoreKit — including the struck-through "before" price a discount implies.
  • Exit offers, up to three hops. A close tap can lead to a better deal instead of an empty screen.
  • Dismiss surveys that answer back. Ask why they're leaving; a "too expensive" can show the annual plan and hand the paywall back.
  • Every string, any locale, translated in one click and reviewable before it ships.
Everything
unlocked.
  • Unlimited sessions
  • Offline mode
  • No ads, ever
SAVE 40%
12 months
7 days free
$79.99
$47.99
1 month
billed monthly
$7.99
Start 7 days free
Cancel anytime · Restore purchase
rendered from fire('PREMIUM_LOCKED')
03
Flows & boosters

Design the exit,
not just the offer.

Most of the revenue is decided after the close tap. Draw what happens there once, on a canvas, and the SDK plays it out — survey, info screen, second offer, push — without another line of app code.

not entitled day 1 close tap close tap “too expensive” “not now” Entry rulesaudience Paywall · Premiumlive · 62% of traffic Paywall · Welcomehard paywall Exit survey4 answers Exit offer −40%recovered 118 Win-back pusht+48h Info screenvalue pitch

Four kinds of booster

Info screen, survey, message and push notification — each edited and previewed as the screen it will actually be, not as a row in a list.

Every branch reports

How many were leaving, how many stopped to answer, how many stayed, and what that was worth. Recovered revenue is the number that stands on its own.

The objection tally

One reason for leaving usually dominates — that's the headline. The sentences people typed sit underneath it, because those are what tell you how to fix it.

04
Analytics & experiments

Numbers that agree
with the stores.

Built on the store's own notifications rather than on what the app remembered to send — so a refund is a refund, a grace period isn't churn, and an experiment never shows a lift without the confidence beside it.

Overview · last 30 days DayWeekMonth
MRR
$48,320
▲ 6.4%
Trials started
1,284
▲ 11.2%
Trial conversion
38.6%
▲ 1.9 pts
Churn rate
4.1%
▲ 0.3 pts
This period Previous period
Retentionby weekly cohort,
week 1 → week 8

Cohorts, not vanity totals

Curves and triangles side by side, pooled or split, so "retention improved" has a week attached to it. Break any metric down by store, product or country.

Experiments with a verdict

The page answers one question — can this be shipped yet. Lift and confidence appear together, and neither appears at all until both arms have enough views to mean anything.

05
Integrations

Delivered, or told
exactly why not.

Every outbound event is written down before anything is sent, so a crash mid-flight leaves a row to retry instead of a hole in your funnel. Connect each destination up to three times — one per environment, per consumer, per account.

Webhookcanonical envelope
{ }Raw webhookthe store's own payload
AAmplitudeHTTP V2 · revenue fields
AFAppsFlyerS2S in-app event
MMeta CAPIapp events
1SOneSignalbooster push channel

Retry ladder

30s 2m 10m 1h 6h dead

Six attempts over roughly eight hours. A timeout, a 429 or a 5xx is retried; a 4xx is your side and would fail identically forever, so it stops. And a customer who declined tracking is skipped, never failed — consent is not an error rate.

06
Moving in

Day one shouldn't
look like a quiet week.

A fresh subscription dashboard normally starts empty and fills up one webhook at a time. Kebabty backfills instead, and hands the workspace to a team rather than to one login.

Import your Apple history

Pull 180 days of production transactions (30 in sandbox — that's Apple's window, not ours) into profiles, transactions and events. Preview the shape before you commit, watch it run, resume it if it stalls.

a run that ended with failures is never shown as green

Names you already know

The event taxonomy is Adapty-compatible on purpose, so the feed reads the way your team already reads it and your downstream dashboards don't need rewriting on the day you switch.

same names, different plumbing

A workspace, not an account

The organization owns the apps and the billing. Invite by link, hand out one of five roles, and keep a sensitive app visible to only the people on it.

owner · admin · developer · analyst · member

Keys that can't wander

Store credentials are encrypted at rest, webhook URLs are per-connection and token-pinned, and the analyst who reads revenue never sees a device id.

two-factor · recovery codes · session revoke

Prove who's asking

The public SDK key proves which app is calling, never which person. Turn on signed identity and your backend signs every user id the app claims — a stolen key can't claim someone else's subscription.

X-Kebabty-Signature · HMAC-SHA256
07
Pricing

Free until it's
worth paying for.

Every feature on this page is in every plan. You start paying when the revenue we track for you is real — not when you want a second app or an experiment.

Starter
$0
up to $10k monthly tracked revenue
  • The whole platform, nothing gated
  • Unlimited paywalls, flows and experiments
  • All six integration destinations
  • 3 team members
Start now
MOST APPS
Growth
1%
of monthly tracked revenue, after the first $10k
  • Everything in Starter
  • Unlimited apps and team members
  • Historical import from the App Store
  • Priority support
Start now
Enterprise
Talk
volume pricing and contracts
  • Custom rate on tracked revenue
  • Extended data retention
  • Migration support and onboarding
  • SLA and a named contact
Contact us
Questions

Before you wire it up.

Is Android supported?
Not in the SDK yet — iOS ships today on StoreKit 2, and Android arrives with the Play Billing module. Everything behind it is already cross-platform: the dashboard, the offerings, the paywalls and the Google Play RTDN mapper are in place and waiting for it.
Do I need an App Store release to change a paywall?
No. Your code only ever names an action key. The paywall behind it, its copy, its prices, its audience rules, its experiment arms and its exit chain are all resolved server-side and delivered to the device as flat strings.
What happens if a purchase never reaches your servers?
The StoreKit transaction stays unfinished. Nothing else finishes it, so the next launch picks it up and retries — the customer keeps their purchase and you keep the record. A transaction that belongs to a different account is refused rather than destroyed, and retried the moment the app identifies that user.
Can I keep the analytics stack I already have?
Yes. Forward processed events to Amplitude, AppsFlyer, Meta CAPI or your own webhook — and if you'd rather trust nobody's mapping but your own, take the store's raw notification byte-for-byte.
How do you know which customer is which?
Anonymous until your app hands over its own user id, then that id owns the profile across reinstalls and devices. Apps that need it stronger turn on signed identity: your backend HMACs the id and the server refuses any claim that isn't signed.
We're already on another provider.
Then you'll recognise the event names — the taxonomy is deliberately Adapty-compatible. Import your Apple transaction history on the way in so the dashboard has real numbers before the first webhook lands, and run both in parallel for as long as you like.
Ready when you are

Put your subscriptions
on the skewer.

Create a workspace, connect the store, drop in the SDK. The first entitlement check works before you've written a paywall.