Guides
GuidesLog In
Guides

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.storStringPurchase store type

event.properties

event.properties may contain fields below.

FieldTypeDescriptionPossible values
event.properties.product_idStringProduct ID
event.properties.reasonStringDepending on the event: the reason of an expiration of a subscription or the reason of refunduser_canceled billing_issue declined_price_increase unavailable_product unknown_error app_issue another_reason
event.properties.currencyStringLocal currency ISO code
event.properties.usd_priceFloatPrice in USD
event.properties.local_priceFloatPrice in local currency
event.properties.offer_typeStringIntroductory or promotional offer payment mode (iOS only).pay_up_front
pay_as_you_go
trial
event.properties.offer_idStringPromotional offer ID
event.properties.unitStringThe increment of time that a subscription period is specified (iOS only)day
week
month
year
event.properties.units_countIntegerThe number of units per subscription period (iOS only)
event.properties.family_sharedBoolIf purchase was used for family sharing option
event.properties.product_bundle_idStringInternal purchase indentifier

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.user_idStringUser ID
user.uidStringApphud user ID (browser user id)
user.payingBooleanIs the user currently paying or not
user.payments_countIntegerUser payments count
user.total_spentFloatUser total spent in USD
user.idfvStringDevice IDFV on iOS, and App Set ID on Android
user.subscriptions[]ArrayAn array containing information about all subscriptions of the user. View the description below.
user.created_atStringUser created date, example: 2022-03-12T09:38:38.081Z
user.variationsArrayArray of Experimets(A/B Tests) in which user was involved
user.country_iso_codeStringUser country code, example: US
user.time_zoneStringUser's current timezone, example: Asia/Jakarta
user.launguageStringUser's current language, example: en
user.propertiesArrayArray of custom user properties which have been assigned with Apphud SDK
user.devicesArrayArray of user deices

user.subscriptions[]

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

FieldTypeDescriptionPossible values
user.subscriptions[].idStringApphud subscription ID
user.subscriptions[].product_idStringProduct ID
user.subscriptions[].groupStringGroup name
user.subscriptions[].statusStringCurrent statustrial
intro
promo
regular
refunded
expired
promotional
user.subscriptions[].intro_periodBooleanIs subscription in an introductory period
user.subscriptions[].trial_periodBooleanIs subscription in the trial period.
user.subscriptions[].started_atDateSubscription start date, example:
2022-03-12T09:38:38.081Z
user.subscriptions[].expires_atDateSubscription expiration date, example:
2024-03-12T09:38:38.081Z
user.subscriptions[].cancelled_atDateSubscription cancellation date, example:
2024-03-12T09:38:38.081Z
user.subscriptions[].autorenew_enabledBooleanIs auto-renew enabled for the subscription
user.subscriptions[].in_retry_billingBooleanIs subscription in retry billing period
user.subscriptions[].introductory_activatedBooleanIs intro (including trial) was user by the user
user.subscriptions[].environmentStringSubscription environmentsandbox
production
user.subscriptions[].kindStringWhether current model is a subscription or a non-renewing purchaseautorenewable
nonrenewable
user.subscriptions[].original_transaction_idStringFor App Store:
original_transaction_id
For Google Play / Xiaomi Store:
purchase_token

Webhooks Examples

Subscription Started

{
  "app": {
    "uid": "89a413f4",
    "bundle_id": "com.apphud.testapplication",
    "package_name": "com.apphud.app"
  },
  "event": {
    "id": "a2472593-f6c5-4d4c-b3e3-5b1214651242",
    "created_at": "2022-05-05T07:24:02.000Z",
    "properties": {
      "currency": "USD",
      "usd_price": 2.49,
      "product_id": "com.apphud.test.trial1",
      "local_price": 2.49,
      "family_shared": false,
      "product_bundle_id": "bfb739d2"
    },
    "store": "play_store",
    "name": "subscription_started",
    "receipt": {
      "id": "106103fc-2eaa-4f9d-98ff-e91a08715252",
      "intro_period": false,
      "price_usd": 2.49,
      "purchased_at": "2022-05-05T07:24:02.000Z",
      "transaction_id": "GPA.3314-7278-3237-55030",
      "original_transaction_id": "mjngdagogcmgmfhcpldfegha.AO-J1Oz1Lvab6xCW5-LOdPU7tKu_xvo3NstnbPmKwinbqfXTh24h-XmqZFhWUn5RxEJOXoi1v8oYajJd2Ptxq3oaiG6eSm7gXA",
      "trial_period": false,
      "price": 2.49,
      "quantity": 1,
      "apple_share": 0.15,
      "proceeds_usd": 2.1165000000000003,
      "proceeds": 2.1165000000000003,
      "product_id": "com.apphud.test.trial1",
      "currency": "USD"
    }
  },
  "user": {
    "created_at": "2022-05-05T07:23:18.941Z",
    "user_id": "9b62fe05-f2b3-4876-a30c-61a2528d3c68",
    "total_spent": 0,
    "payments_count": 0,
    "uid": "36c21695",
    "idfv": null,
    "variations": [],
    "country_iso_code": "RU",
    "time_zone": "Europe/Moscow",
    "language": "en",
    "paying": false,
    "email": "[email protected]",
    "phone": null,
    "name": "",
    "age": null,
    "gender": null,
    "properties": [
      {
        "name": "$name",
        "value": ""
      },
      {
        "name": "$email",
        "value": "[email protected]"
      }
    ],
    "subscriptions": [
      {
        "id": "800e21d3-f111-4f0b-8d70-a5e7cda7ca7c",
        "status": "regular",
        "environment": "sandbox",
        "original_transaction_id": "mjngdagogcmgmfhcpldfegha.AO-J1Oz1Lvab6xCW5-LOdPU7tKu_xvo3NstnbPmKwinbqfXTh24h-XmqZFhWUn5RxEJOXoi1v8oYajJd2Ptxq3oaiG6eSm7gXA",
        "expires_at": "2022-05-05T07:30:59.000Z",
        "cancelled_at": null,
        "started_at": "2022-05-05T07:24:02.000Z",
        "autorenew_enabled": true,
        "in_retry_billing": false,
        "introductory_activated": false,
        "store": "play_store",
        "group": "Test_Experiment",
        "product_id": "com.apphud.test.trial1",
        "intro_period": false,
        "trial_period": false
      }
    ],
    "devices": [
      {
        "id": "c4c0613b-7eec-4506-b917-4f944dfd28c7",
        "device_id": "9b62fe05-f2b3-4876-a30c-61a2528d3c68",
        "device_type": "SM-A515F",
        "device_family": "samsung",
        "platform": "android",
        "app_version": "2.2.0",
        "sdk_version": "1.6.0",
        "os_version": "10",
        "idfa": "7b273674-4883-45b7-b171-ee1b33af38e1",
        "start_app_version": "2.2.0",
        "carrier": null,
        "push_token": null,
        "idfv": null
      }
    ]
  }
}

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: