We needed a reliable way to make sure a subscription bought on the web showed as active inside the app. Our approach was to write the web checkout result to our backend, call RevenueCat (or Adapty) APIs to grant entitlement, and store the mapping id so the app could fetch the updated status.
The tricky parts were race conditions and retries. We added idempotency keys and a short reconciliation job to re-sync anything that looked off. That cut false negatives in revenue reporting to almost zero.
How do you handle delayed webhook calls or retries when a web payment needs to reflect instantly in the app?
We wrote the web checkout to our server first, then pushed the change to RevenueCat with an idempotent key.
If the push failed we queued a retry. A nightly reconciliation checked for mismatches and fixed them automatically.
It felt complex at first but it made app and web reporting line up.
Idempotency and retries are everything. We send a user and purchase id to RevenueCat and use webhooks to confirm state.
That flow made subscription state consistent fast and let us trust revenue metrics for experiments.
We added a short entry that the app reads on launch. If it sees a valid web purchase id it asks RevenueCat for entitlements. That avoided many edge cases where the app thought the user was unsubscribed.
Push web sale to backend
Call RevenueCat
Retry and reconcile
Design the flow as: web checkout → backend write → call RevenueCat/Adapty API → emit webhook → app reads consistent state. Use idempotency tokens for every purchase and keep a reconciliation job that compares web purchases to the subscription provider state. For latency issues, surface interim access via a short lived server flag so the app can grant access immediately while the provider sync completes.
This reduces race conditions and keeps analytics accurate.
We added a small retry queue and it fixed most failed syncs within an hour.
We relied on RevenueCat webhooks and a short retry loop. Simple and effective.
Make reconciliation part of your daily pipeline. Saves headaches later.