Server-to-Server Webhooks

This guide describes how to add and configure custom server-to-server webhook.

📘

Note

Server-to-server webhooks are available on "Expert" and "Enterprise" plans.

Apphud's webhook system for subscriptions allows you to catch the moment when a subscription event occurs. You can use this data to implement custom logic or analytics on your own server. You simply need to specify a URL for POST-request.

Webhooks are being sent as POST request to specified URL.

How to Add Webhook?

Step 1

At Apphud go to the "Integrations" section, click S2S webhooks add click New webhook:

Step 2

Enter webhook name and specify webhook URL. Events will be sent to this URL using POST-request:

Step 3

You may optionally specify Secret token that will be sent with the webhook request in the X-Apphud-Token HTTP header. Use this token to validate received payloads.

Step 4

Choose which between Production and Sandbox events to be sent via webhook:

Step 5

Enable events which you would like to receive webhooks for:

Step 6

Enable and save the integration:

❗️

Important Note

Apphud sends only one request per webhook without retries.

Webhook Structure

The POST body for all webhooks follows the same structure:

{
    "app": {},
    "event": {},
    "user": {}
}

Let's look through each component of this structure.

App

This dictionary contains information about the app.

FieldTypeDescription
app.uidStringApphud app ID
app.bundle_idStringiOS Bundle ID
app.package_nameStringAndroid Package Name

Event

This dictionary contains information about events.

FieldTypeDescriptionPossible values
event.idStringApphud event ID
event.created_atDateDate when this event was created by Apphud.
event.nameStringEvent namee.g. "trial_started"
event.propertiesDictionaryA dictionary containing event properties. View the description below.
event.receiptDictionaryApphud receipt information related to the event. View the description below.
event.storeStringPurchase store type

event.properties

event.properties may contain fields below.


Field Type Description Possible values

event.properties.product_id

String

Product ID

event.properties.reason

String

Depending on the event: the reason of an expiration of a subscription, the reason of refund, or product_id for billing_issue_resolved events

user_canceled
billing_issue
declined_price_increase
unavailable_product
unknown_error
app_issue
another_reason
product_id

event.properties.currency

String

Local currency ISO code

event.properties.usd_price

Float

Price in USD

event.properties.local_price

Float

Price in local currency

event.properties.usd_tax

Float

Tax amount in USD

event.properties.local_tax

Float

Tax amount in local currency

event.properties.usd_proceeds

Float

Developer proceeds in USD after Apple/Google commission and taxes, if applicable

event.properties.local_proceeds

Float

Developer proceeds in local currency after Apple/Google commission and taxes, if applicable

event.properties.offer_type

String

Introductory or promotional offer payment mode (iOS only)

pay_up_front
pay_as_you_go
trial

event.properties.offer_id

String

Promotional offer ID

event.properties.unit

String

The increment of time that a subscription period is specified (iOS only)

day
week
month
year

event.properties.units_count

Integer

The number of units per subscription period (iOS only)

event.properties.family_shared

Boolean

Whether the purchase was used via Family Sharing

event.properties.product_bundle_id

String

Internal purchase identifier

event.properties.paywall_id

String

Internal Apphud paywall ID

event.properties.placement_id

String

Internal Apphud placement ID

event.properties.paywall_name

String

Paywall name as configured in Apphud

event.properties.paywall_identifier

String

Paywall identifier as configured in the app / SDK

event.receipt

event.receipt may contain the fields below.

❗️

Important Note

This is an internal Apphud receipt model.

FieldTypeDescription
event.receipt.idStringApphud receipt ID
event.receipt.product_idStringProduct ID
event.receipt.purchased_atDateTransaction date, example: 2022-03-12T09:38:38.081Z
event.receipt.intro_periodBooleanIs subscription in an introductory period
event.receipt.trial_periodBooleanIs subscription in the trial period.
event.receipt.transaction_idStringApp Store transaction ID / Android Order ID
event.receipt.original_transaction_idStringApp Store original transaction ID / Android Purchase Token
event.receipt.price_usdFloatPrice in USD
event.receipt.proceeds_usdFloatRevenue in USD after Apple / Google commission deduction
event.receipt.priceFloatPrice in local currency
event.receipt.proceedsFloatRevenue in local currency after Apple / Google commission deduction
event.receipt.currencyStringLocal currency ISO code, example: USD
event.receipt.quantityIntegerAlways 1
event.receipt.apple_shareFloatStore commission. It can be 0.15 or 0.3.

User

This dictionary contains information about the user.

FieldTypeDescription
user.created_atStringUser created date, example: `2022-03-12T09:38:38.081Z
user.user_idStringUser ID
user.total_spentFloatUser total spent in USD
user.payments_countIntegerUser payments count
user.ipStringUser IP address
user.uidStringApphud user ID (browser user id)
user.idfvStringDevice IDFV on iOS, and App Set ID on Android
user.country_iso_codeStringUser country code, example: US
user.time_zoneStringUser's current timezone, example: Asia/Jakarta
user.languageStringUser's current language, example: en
user.internal_attributionObjectIf available, shows captures data from Web-to-App flows , Apphud Flows, and Apple Search Ads Integration. The fields set may include: status, provider, ad network, campaign, ad set, keyword, and custom1(with Click vs Impresssion info for ASA).
user.partner_attributionObjectPartner attribution data, if available. May include attribution provider and campaign metadata such as campaign, ad network, ad set, keyword, and status.
user.variations[]Array of ObjectsList of Experiments (A/B tests) the user took part in. Each object may include experiment uidand name, variation_name, status, and timestamps for created_at and launched_at.
user.payingBooleanIs the user currently paying or not
user.currency_country_codeStringCountry code used for currency calculations (ISO 3166-1 alpha-2)
user.emailStringReserved User property for email which has been assigned with Apphud SDK.
user.nameStringReserved User property for name which has been assigned with Apphud SDK.
user.phoneStringReserved User property for phone which has been assigned with Apphud SDK.
user.ageStringReserved User property for age which has been assigned with Apphud SDK.
user.genderStringReserved User property for gender which has been assigned with Apphud SDK.
user.properties []ArrayArray of custom user properties which have been assigned with Apphud SDK
user.subscriptions[]ArrayAn array containing information about all subscriptions of the user. View the description below.
user.devices[]ArrayArray of user deices. View the description below.

user.subscriptions[]

user.subscriptions is an array containing user's subscriptions. Each element of this array is a dictionary with the following structure:

Field Type Description Possible values

user.subscriptions[].id

String

Apphud subscription ID

user.subscriptions[].product_id

String

Product ID

user.subscriptions[].group

String

Subscription group name

user.subscriptions[].status

String

Current subscription status

trial
intro
promo
regular
refunded
expired
promotional

user.subscriptions[].intro_period

Boolean

Whether the subscription is currently in an introductory period

user.subscriptions[].trial_period

Boolean

Whether the subscription is currently in a trial period

user.subscriptions[].started_at

Date

Subscription start date, example:
2022-03-12T09:38:38.081Z

user.subscriptions[].expires_at

Date

Subscription expiration date, example:
2024-03-12T09:38:38.081Z

user.subscriptions[].cancelled_at

Date

Subscription cancellation date, if cancelled, example:
2024-03-12T09:38:38.081Z

user.subscriptions[].autorenew_enabled

Boolean

Whether auto-renew is enabled for the subscription

user.subscriptions[].in_retry_billing

Boolean

Whether the subscription is in the retry billing period

user.subscriptions[].introductory_activated

Boolean

Whether any introductory offer, including a trial, has been used by the user

user.subscriptions[].environment

String

Subscription environment

sandbox
production

user.subscriptions[].store

String

Store where the subscription was purchased

app_store
play_store
stripe

user.subscriptions[].kind

String

Purchase type

autorenewable
nonrenewable

user.subscriptions[].original_transaction_id

String

For App Store:
original_transaction_id
For Google Play / Xiaomi Store:
purchase_token

user.devices[]

user.devices[] is an array containing user's devices. Each element of this array is a dictionary with the following structure

Field Type Description Possible values

user.devices[].id

String

Apphud device ID

user.devices[].device_id

String

Device identifier

user.devices[].device_type

String

Device model

user.devices[].device_family

String

Device family

user.devices[].platform

String

Device platform

ios
android

user.devices[].app_version

String

Current app version on the device

user.devices[].sdk_version

String

Apphud SDK version used on the device

user.devices[].os_version

String

Operating system version

user.devices[].idfa

String / Null

Identifier for Advertisers (IDFA), if available

user.devices[].start_app_version

String

App version installed when the user first started using the app on this device

user.devices[].carrier

String / Null

Mobile carrier name, if available

user.devices[].push_token

String / Null

Push notification token, if available

user.devices[].idfv

String / Null

Identifier for Vendors (IDFV), if available

user.devices[].adjust_data

Object / Null

Adjust attribution data for this device, if available

user.devices[].appsflyer_data

Object / Null

AppsFlyer attribution data for this device, if available

Webhooks Examples

Subscription Renewed

{
  "app": {
    "uid": "a1b2c3d4",
    "bundle_id": "com.example.vpnapp",
    "package_name": "com.example.vpnapp"
  },
  "event": {
    "id": "11111111-2222-3333-4444-555555555555",
    "created_at": "2026-03-03T16:33:05.619Z",
    "properties": {
      "usd_tax": 2.658333333333333,
      "currency": "GBP",
      "local_tax": 1.998333333333333,
      "usd_price": 15.95,
      "paywall_id": "pw_1234abcd",
      "product_id": "com.example.vpnapp.monthly",
      "local_price": 11.99,
      "placement_id": "pl_5678efgh",
      "usd_proceeds": 11.29791666666667,
      "family_shared": false,
      "local_proceeds": 8.492916666666666,
      "product_bundle_id": "pb_90ab12cd",
      "paywall_name": "Main Monthly Paywall",
      "paywall_identifier": "paywall_main_monthly"
    },
    "store": "app_store",
    "name": "subscription_renewed",
    "receipt": {
      "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "intro_period": false,
      "price_usd": 15.95,
      "purchased_at": "2026-03-04T00:31:08.000Z",
      "transaction_id": "500000000000001",
      "original_transaction_id": "500000000000000",
      "trial_period": false,
      "price": 11.99,
      "quantity": 1,
      "apple_share": 0.15,
      "proceeds_usd": 11.29791666666667,
      "proceeds": 8.492916666666666,
      "product_id": "com.example.vpnapp.monthly",
      "currency": "GBP"
    }
  },
  "user": {
    "created_at": "2025-04-26T18:48:01.627Z",
    "user_id": "USER-UUID-OBFUSCATED",
    "total_spent": 176.27324951,
    "payments_count": 11,
    "ip": "203.0.113.42",
    "uid": "user_ab12cd34",
    "idfv": "IDFV-OBFUSCATED",
    "country_iso_code": "GB",
    "time_zone": "Europe/London",
    "language": "en",
    "partner_attribution": null,
    "internal_attribution": {
      "ad_set": "brand keywords",
      "status": "Non-Organic",
      "keyword": "vpn app",
      "campaign": "UK_Search_Campaign",
      "provider": "Apple Search Ads Integration",
      "ad_network": "Apple Search Ads"
    },
    "variations": [],
    "paying": true,
    "currency_country_code": "GB",
    "email": null,
    "phone": null,
    "name": null,
    "age": null,
    "gender": null,
    "properties": [],
    "attribution": {
      "search_ads_data": {
        "iad-keyword": "vpn app",
        "iad-adgroup-name": "brand keywords",
        "iad-campaign-name": "UK_Search_Campaign",
        "iad-conversion-type": "Download",
        "iad-country-or-region": "GB"
      },
      "search_ads_raw_data": {
        "ad_id": -1,
        "org_id": 1234567,
        "claim_type": "Click",
        "keyword_id": 1111111111,
        "ad_group_id": 2222222222,
        "attribution": true,
        "campaign_id": 3333333333,
        "conversion_type": "Download",
        "country_or_region": "GB"
      },
      "facebook_data": null,
      "tiktok_data": null,
      "adjust_data": null,
      "apphud_data": null
    },
    "subscriptions": [
      {
        "id": "sub_11111111-2222-3333-4444-555555555555",
        "status": "regular",
        "environment": "production",
        "original_transaction_id": "500000000000000",
        "expires_at": "2026-04-03T23:31:08.000Z",
        "cancelled_at": null,
        "started_at": "2025-04-26T18:48:25.000Z",
        "autorenew_enabled": true,
        "in_retry_billing": false,
        "introductory_activated": true,
        "store": "app_store",
        "kind": "autorenewable",
        "group": "iOS",
        "product_id": "com.example.vpnapp.monthly",
        "intro_period": false,
        "trial_period": false
      }
    ],
    "devices": [
      {
        "id": "dev_11111111-2222-3333-4444-555555555555",
        "device_id": "DEVICE-ID-OBFUSCATED",
        "device_type": "iPhone 15 Pro",
        "device_family": "iPhone",
        "platform": "ios",
        "app_version": "3.3.0",
        "sdk_version": "3.6.2",
        "os_version": "18.5",
        "idfa": null,
        "start_app_version": "3.0.5",
        "carrier": null,
        "push_token": null,
        "idfv": "IDFV-OBFUSCATED",
        "adjust_data": null,
        "appsflyer_data": {
          "af_status": "Organic",
          "af_message": "organic install",
          "appsflyer_id": "af_1745693274391_xxxxxx",
          "is_first_launch": false
        }
      }
    ]
  }
}

How to Test Webhook

You can test webhooks using any service that may receive HTTP events, for example, RequestBin.com.

Step 1

Open RequestBin.com and click the "Create Request Bin" button.

Step 2

Copy Endpoint URL:

Step 3

Create new Webhook in Apphud using this URL. Make sure you selected "Sandbox" environment while configuring webhook.

Step 4

Make a test purchase on your device using Sandbox environment. You can read how to do this here. Now whenever webhook is triggered, you will see a full report on RequestBin: