A webhook is an endpoint used for server-to-server real-time notifications through HTTP.


In order to keep your users purchases statuses up-to-date on your server, you can setup an URL that iaptic will call whenever there's an important event changing the state of that user.

This Webhook will be called when the user validates a receipt or when Apple or Google themselves sends a notification (for subscription events).

The webhook URL is setup from the Settings page.


Webhook Request

Iaptic will make a request to your Webhook URLs using the POST method. The body will be a JSON object containing the webhook type and the associated data.

The format is described here: class Webhook.PurchasesUpdated.

Sandbox Webhook URL

In the settings you will find the Webhook URL and Sandbox Webhook URL fields.

  • If only the Webhook URL is set, all notifications will be sent to that URL.
  • If the Sandbox Webhook URL is set, it'll receive notifications for users making "sandbox" purchases.
    • the "Webhook URL" will then only receive notifications for users having made "production" purchases.

Multiple URLs

In each of those fields, you can set multiple URLs by separating them with a comma.


  • Your endpoint should use SSL, i.e. be an https:// endpoint. Self-signed certificates are accepted.
  • Make sure to return status 200 for all calls, even for unrecognized webhook types. The webhook might be extended with new message types.

Testing your Webhook

Next to the Webhook URL field, there's a Test button. Clicking this button will send a test webhook notification to ALL your Webhook URLs.

The content of the webhook will be as follows:

    "type": "test",
    "password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

See class Webhook.Test

Blacklisted URLs

If an endpoint is down for a period of time, iaptic will blacklist the URL for 30 days.

If you want to restore this URL, you make a forced call using the Test Webhook feature (see Testing your Webhook) above. If the call succeeds, the webhook will be de-blacklisted.


Since version 3.3, webhook calls include a notification field. This field lets your server know why the call was made.

It can be used to build analytics, for instance in your code:

const notification = webhook.notification;
if (notification.reason != "RECEIPT_VALIDATED") { // storing those is rarely useful
  notificationsDB.insert(,, notification.reason,
    notification.productId, notification.purchaseId);

// ...

// Count purchases since January 2023
notificationsDB.pseudoSQL('SELECT count(*) WHERE date > "2023-01-01" AND reason = "PURCHASED"');

// Count renewals since January 2023
notificationsDB.pseudoSQL('SELECT count(*) WHERE date > "2023-01-01" AND reason = "RENEWED"');

Check NotificationReason for the list of possible notification reasons.