Validate Apple Store Purchase
POST https://api.botsi.com/v2/purchases/apple-store/validateCall this after a purchase completes in your app. It confirms the transaction with Apple and records the revenue against the Profile and the Paywall that produced it.
Identify the user with profileId.
Request body#
isExperiment and aiPricingModelId are optional on the v2 API, though the SDK surface requires them. Omitting them still validates the purchase — see the attribution note below for why you should send them anyway.
source is load-bearing, even though it is optional
It defaults to purchasing when omitted. restore short-circuits validation entirely, and purchasing selects the deduplication key, so the value you send changes what the endpoint does rather than just labelling the call. Send it deliberately.
This endpoint does not accept paywallSessionId
The token shortcut applies to Send Paywall Shown Event only. Keep passing paywallId, isExperiment, and aiPricingModelId here, exactly as Fetch Paywall returned them.
Omit them and the purchase still validates, but it detaches from the experiment that produced it, so the model gets no credit for the revenue it earned.
curl -X POST "https://api.botsi.com/v2/purchases/apple-store/validate" \
-H "Authorization: $BOTSI_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"placementId": "ai-placement-id",
"paywallId": 42,
"source": "purchasing",
"productId": "premium_annual",
"isSubscription": true,
"originalTransactionId": "2000000261699248",
"environment": "sandbox",
"transactionId": "2000000871590381",
"profileId": "fff3c120-0ca8-480f-9b19-3955a5428e39",
"isExperiment": true,
"aiPricingModelId": 32
}'Finding the identifiers#
StoreKit. transactionId and originalTransactionId come from the SKPaymentTransaction object. The Product identifier is SKPaymentTransaction.payment.productIdentifier, and the original price is on SKProduct.
StoreKit 2. All three come from the Transaction object, and the original price from Product.
Response#
A successful validation returns the updated Profile, including its Access Levels, subscriptions, and total revenue.
{
"ok": true,
"data": {
"profileId": "fff3c120-0ca8-480f-9b19-3955a5428e39",
"appUserId": "user-123",
"state": "subscribed",
"totalRevenueUsd": 49.99,
"accessLevels": {},
"subscriptions": {},
"nonSubscriptions": {}
}
}