Validating Apple iTunes In-App Purchases

The revenue reporting features in Attribution Analytics (AA) contain advanced receipt validation mechanisms that, when implemented, independently validate every in-app purchase. This eliminates revenue from fraudulent purchases and ensures that the revenue number you see in our dashboard is the most accurate.

To implement receipt validation, you must first send AA the iTunes purchase receipt data, which we then check against the iTunes API as well.

Note: If you are using the TUNE SDK and want to learn how the in-app purchase validation process can be implemented using our SDK, please read In-App Purchase Verification in our SDK section.

Validation Process

The validation process is a separate and independent process that happens after the event is measured and attributed. Due to this, the validation process will never lag / delay the measuring and attribution processes.

When the platform measures the event with a receipt ID, the event's purchase validation status is set to "Pending". 60 minutes after the event is measured, it is queued in the validation process. The validation process takes the receipt data and queries the Apple iTunes API to see if the purchase was successful or not.

If the purchase was successful, then the event's purchase validation status is set to "Verified" and aggregated revenue is incremented accordingly. If the purchase was not successful, then the event's purchase validation status is set to "Failed" and no revenue is incremented. This process will also check for and block duplicate purchases being sent based on receipt ID.

Collecting Your App's Receipt Data

Unlike our SDKs that collect the receipt data for you, when using our API you will need to collect the receipt data yourself. Refer to Apple's documentation to learn how to collect the purchase receipt data for your iOS app.

Handling Auto-Renewable Digital Subscriptions

If you offer auto-renewable digital subscriptions in your iOS app, you need to provide your iTunes Connect Shared Secret in the AA platform to enable AA to do validation. Auto-renewable subscriptions allow users to purchase in-app content, and the purchase is automatically renewed at the end of the period unless the user chooses to cancel the subscription.

Notifying AA via API

After you collect the purchase receipt data for your iOS app, you can send it to AA to verify your in-app purchases by posting it to your measurement URL for the purchase event.

Sample Measurement URL:,2&device_carrier=Verizon&country_code=US&currency_code=USD


  • data[]
    • For measuring the item that was purchased. Passed in the same way as a site event item.
  • store_receipt
    • Pass the base64 encoded receipt data in this field

Example POST

"data": [
"attribute_sub4": "attr4",
"attribute_sub2": "attr2",
"item": "Barrel Full o' Shiny",
"attribute_sub5": "attr5",
"quantity": "1",
"attribute_sub3": "attr3",
"revenue": "109.989998",
"attribute_sub1": "attr1",
"unit_price": "109.989998"

When we do validation on the in-app purchase for iOS, verified purchases have a purchase validation code of 0. If the purchase is not validated, however, the validation could will be different depending on a variety of reasons (as seen in the table below).

iOS Code Purchase Validation Status Explanation Verified Revenue Conversion Status
-3 Invalid Bundle Valid receipt but contains bundle id of a different site. No rejected
-2 Unknown Error Some error with our attempt occurred. No rejected
-1 No Receipt No receipt to validate. No approved
0 Validated We've validated this receipt successfully. Yes approved
21000 Unreadable JSON object The App Store could not read the JSON object you provided. No rejected
21002 Malformed receipt data The data in the receipt-data property was malformed. No rejected
21003 Failed Validation The receipt could not be authenticated. No rejected
21004 Invalid Shared Secret The shared secret you provided does not match the shared secret on file for your account. No rejected
21005 Receipt Server Unavailable The receipt server is not currently available. No rejected
21006 IAP subscription expired This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response. No rejected
21007 Sandbox receipt to Production This receipt is a sandbox receipt, but it was sent to the production service for verification. No rejected
21008 Production receipt to Sandbox This receipt is a production receipt, but it was sent to the sandbox service for verification. No rejected
Have a Question? Please contact for technical support.