Validate Google Play Store Purchase

POSThttps://app.botsi.com/api/v1/web-api/purchases/play-store/validate

Validates an in-app purchase or subscription completed through the Google Play Store. This endpoint confirms the purchase token with Google and links the transaction to the user profile and paywall context.

Follow the notes below for a successful request:
  • subscriptionOfferDetails is required for subscriptions and must match the purchased offer.

  • paywallId, isExperiment, and aiPricingModelId must match the values returned by the Get Paywall API.

  • Use environment: production for live apps and sandbox for testing.

  • If you previously called Get Paywall, include isExperiment and aiPricingModelId from that response to improve analytics attribution.

  • At least one of profileId or customerUserId must be provided to identify the user.


Finding the token

If you are having trouble finding the token, you can refer to the official Google documentation:


Note on trial periods

A trial period is identified when at least one element within pricingPhases contains priceAmountMicros = 0.

For a trial subscription, the system expects to receive a pricingPhase with:

  • priceAmountMicros: 0 (to indicate a free trial)

  • The usual fields: billingPeriod, recurrenceMode, and billingCycleCount

This zero-priced phase allows our system to correctly identify the event as a trial rather than a paid subscription.

If this zero-priced phase is missing, the event will be interpreted as a paid subscription, which will impact your revenue statistics.

Update: One-Time Purchase (OTP) Support

This endpoint supports both subscription and one-time purchase (OTP) validations. In addition to the existing subscriptionOfferDetails field, you can send oneTimePurchaseOfferDetails for one-time purchases.

Important: You must send either oneTimePurchaseOfferDetails or subscriptionOfferDetails, but not both. The choice depends on whether you're validating a one-time purchase or a subscription.

Critical: Experiment Attribution

While paywallId, isExperiment, and aiPricingModelId are technically optional, you should always include them if the purchase originated from a paywall fetched via the Get Paywall endpoint. These fields link the purchase to the correct experiment or control group.

Without them, Botsi cannot attribute the revenue to the right variant. This means experiment results become unreliable, and the AI model will train on incomplete conversion data — degrading future pricing predictions.

Request Body

application/json

ParameterTypeRequiredDescription
profileIdstringOptionalProvide profileId or customerUserId
customerUserIdstringRecommendedYour internal user ID. Provide either profileId or customerUserId
productIdstringRequiredGoogle Play product ID. Example: premium_monthly
purchaseTokenstringRequiredGoogle Play purchase token
paywallIdintegerRecommendedFrom Get Paywall response (data.id). Required for correct revenue attribution.
isExperimentbooleanRecommendedMust match data.isExperiment from Get Paywall. Required for experiment vs. control attribution.
aiPricingModelIdintegerRecommendedMust match data.aiPricingModelId from Get Paywall. Ties the purchase to the AI model for training.
placementIdstringOptionalPlacement ID used to fetch the paywall
pricenumberOptionalPrice. Example: 9.99
currencystringOptionalCurrency code. Example: USD
subscriptionOfferDetailsobjectOptionalSubscription offer details (for subscriptions)
basePlanIdstringOptionalBase plan identifier
offerIdstringOptionalOffer identifier
offerTokenstringOptionalOffer token
pricingPhasesarrayOptionalPricing phases array
billingPeriodstringOptionalBilling period. Example: P1M
recurrenceModeintegerOptional1=infinite, 2=finite, 3=non-recurring
billingCycleCountintegerOptionalNumber of billing cycles
formattedPricestringOptionalFormatted price. Example: $9.99
priceCurrencyCodestringOptionalCurrency code. Example: USD
priceAmountMicrosstringOptionalPrice in micros. Example: 9990000

Example Request

{
  "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
  "productId": "premium_monthly",
  "purchaseToken": "opaque-token-from-google-play",
  "paywallId": 42,
  "isExperiment": true,
  "aiPricingModelId": 32,
  "price": 9.99,
  "currency": "USD"
}

cURL Example

curl -X POST "https://app.botsi.com/api/v1/web-api/purchases/play-store/validate"      -H "Authorization: {{secret_key}}"      -H "Content-Type: application/json"      -d '{
       "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
       "productId": "premium_monthly",
       "purchaseToken": "opaque-token-from-google-play",
       "paywallId": 42,
       "isExperiment": true,
       "aiPricingModelId": 32,
       "price": 9.99,
       "currency": "USD"
     }'

Response

200Purchase validated
{
  "ok": true,
  "data": {
    "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
    "customerUserId": "user-123",
    "paid": true,
    "country": "US",
    "platform": "android"
  }
}

Try It Out

https://app.botsi.com/api/v1/web-api
Response
Click "Send API Request" to see the response here.