---
title: "Verify every store purchase on your server · Agent Wranglers"
url: https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing/verify-store-purchases
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Verify every store purchase on your server

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Store review and listing](https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- ID: MOB-5
- Level: Required
- Chapter: [Store review and listing](https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing)
- Rule: Grant paid access only after your server has checked the purchase with the store's server API. Keep it current from the store's server notifications.
- Risk: Money lost or taken twice
- Applies when: The project takes payments.
- How: The app sends the transaction ID or purchase token to your server after a purchase. The server asks the App Store Server API or the Google Play Developer API for the signed purchase and stores the result. A modified app can fake a success inside the app, so the app's own answer never grants access. Subscribe to App Store Server Notifications version 2 and Google Play's notifications for renewals, refunds and cancellations. Handle each event once, as [make receivers idempotent](https://agentwranglers.se/playbook/api-design/webhooks-and-events/idempotent-receivers) says. Access then follows [give access from the subscription status](https://agentwranglers.se/playbook/payments/subscriptions/entitlements-from-status).
- Check: Send the server a made-up transaction ID and a made-up purchase token. Both are refused and grant nothing. A refund in the sandbox removes access within 1 hour.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### TypeScript example

```ts
const url = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/com.example.fittrack/purchases/subscriptionsv2/tokens/${purchaseToken}`;
const response = await fetch(url, { headers: { Authorization: `Bearer ${await googleAccessToken()}` } });
const purchase = await response.json();
const isActive = purchase.subscriptionState === 'SUBSCRIPTION_STATE_ACTIVE';
await entitlements.set(userId, 'premium', isActive);
```

### Python example

```python
service = build("androidpublisher", "v3", credentials=credentials)
purchase = service.purchases().subscriptionsv2().get(
    packageName="com.example.fittrack", token=purchase_token
).execute()
is_active = purchase["subscriptionState"] == "SUBSCRIPTION_STATE_ACTIVE"
entitlements.set(user_id, "premium", is_active)
```

## Sources

- [App Store Server API](https://developer.apple.com/documentation/appstoreserverapi)
- [Google Play Developer API, purchases.subscriptionsv2.get](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2/get)

## Related rules

- [Make receivers idempotent](https://agentwranglers.se/playbook/api-design/webhooks-and-events/idempotent-receivers) in API design
- [Give access from the subscription status](https://agentwranglers.se/playbook/payments/subscriptions/entitlements-from-status) in Payments

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing/verify-store-purchases">Agent Wranglers mobile apps playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Sell digital goods through the store's billing](https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing/store-billing)
- Next: [Offer a private sign-in next to social sign-in](https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing/private-sign-in-option)
- [Store review and listing](https://agentwranglers.se/playbook/mobile-apps/store-review-and-listing)
