We’ve migrated our documentation to a new site, which means some URLs have changed.
Subscriptions

Webhooks


1. Webhooks overview

2. Types of webhooks

Unlock the full potential of our feature and take your skills to the next level! Dive into our Training Center and discover exclusive Best Practice resources that will elevate your implementation strategy. With expert tips and insider knowledge, you'll become a master in no time. Access the links below to learn more and gain a competitive edge.

Ready to get started? Our Training Center is just a click away: here.

*For more information about our Training center, please visit the article here.

Webhooks overview

If you may need access to the events later, we strongly recommend to use your own storage system (a database or Kafka) for more efficient processing and replay capabilities.
The search functionality of the publisher/webhook/list endpoint is designed only for ad-hoc investigations (not reporting or automated resend), especially when dealing with a large number of events, and may result in severe rate limiting (HTTP 429) or timeouts.
If the 'webhook.estimated_count.enabled' setting is enabled for apps with a high volume of events, we recommend scrolling without considering the actual "total" value to determine the call count. Continue scrolling while 'current_response.total > offset + count'.

Configuring your endpoint

Webhooks can be sent to any HTTP or HTTPS endpoint. To configure an endpoint login to your Piano dashboard and click ManageWebhooks. Toggle the webhooks indicator to the “on” position, click on the blue URL to edit the endpoint, and enter your endpoint URL.

The data sent in our webhooks is available within a query string and is encrypted. The query string should be run through this SDK (PHP, Java, Python) in order to decrypt the data you'll need to query the Piano API for additional information.

Your endpoint must respond with a 200 OK HTTP status code for it to be configured successfully. We are sending the webhook message just once if the response is 200. You are able to request resending the webhook again manually.

When sending a response to the target URL/endpoint, our webhook service will wait 7 seconds for a response before a timeout occurs and it considers the sending as unsuccessful. There is no limitation on the retention period for undelivered webhooks.

Webhooks can be enabled or disabled by event. Using the webhooks manager, you can select which webhooks to send to your endpoint by event. All enabled webhooks will be sent to the selected endpoint.

Webhook events are never batched, you will always receive one webhook message per single event.

Selecting webhooks

Once webhooks are enabled, webhook events can be selectively turned on or off inside the webhooks manager modal. By default, all webhook events will be set to fire when webhooks are enabled. This setting can be reversed by checking the box that selects all webhooks.

Individual webhooks can be turned off or on from this modal using the checkbox beside the webhook name.

Screen-Shot-2020-05-04-at-9.03.33-AM.png

Selected webhooks are displayed at the top of the webhook list. This setting can be undone by clicking the filter icon and selecting NO GROUPING.

Queueing, blocking, and skipping

All webhooks are by default sent sequentially; this prevents problems that would occur if they were sent out of order. For example, if someone cancels their annual subscription and then re-subscribes at the monthly rate, Piano would need to process those events in order for the user to maintain their access. If the cancel event was sent after the resubscribe event, the user would incorrectly end up without any access.

So, whenever an access event occurs in Piano, we place the webhook event into a single queue for processing. Every successful response that we get back from your endpoint will tell us to proceed with the next webhook. If your endpoint responds with a non-200 HTTP status code, this informs Piano that the endpoint was down or unable to process the webhook. We don’t guarantee the sending order for webhooks that failed at least once, only for those successfully being sent.

Although we aim to ensure prompt data transmission through our Webhook service, it's crucial to acknowledge that real-time delivery cannot be guaranteed. While most webhook deliveries occur within seconds, it's imperative to recognize the inherent variability in delivery times. Delays can range from 30 seconds to approximately one hour, influenced by the responsiveness of publisher servers and retries following timeouts. The expected p95 delivery time is 1 minute. This metric signifies that 95% of requests are processed and transmitted within this specified timeframe, ensuring that the vast majority of data transmissions occur promptly and efficiently.

Because webhooks are sent sequentially and are inherently “blocking” each other, your server should only respond with a non-200 HTTP status code in the case of true, exceptional failure. Any failures of business logic should be properly caught and handled inside of your application.

The retry frequency for failed webhooks is as follows:

1. We try to send a webhook every 30 seconds for 3 minutes;
2. Then we try to send the webhook every 60 seconds for 7 minutes;
3. Then we try to send the webhook every 5 minutes for 50 minutes;
4. Then we try to send the webhook once every 1 hour.

Please note that the above times are only indicative, as failed webhooks are queued and this can affect the retry times. In terms of total retry counts, we try to send every failed webhook no more than 237 times.

If the last 237th attempt is still not successfully sent, webhooks will be deactivated on your Piano application altogether.

If a webhook can't be delivered, it first receives the status failed and then transitions to inactive once we have reached the maximum sending attempts.

Checkout integration

Webhooks are sent asynchronously. Because of this, webhooks should not be used to determine access after new purchases. If webhooks were used in this manner, after a purchase it's possible that the user would continue to see a “doesn't-have-access” state because of a lag in webhook communication between your local entitlements database and Piano. If there is a failed webhook blocking future processing, this situation would exacerbate itself.

Piano instead recommends using an approach similar to the below, where you register the complete callback to synchronously fetch new entitlements (more info on the complete callback here). In this case, you would implement a /verify-conversion page that would perform the action of fetching the new user entitlements from the Piano API and updating your local datastore.

tp.offer.show({
    offerId: "O1234",
    templateId: "OTABCDEF",
    complete: function(conversion) {
        $.ajax({
            url: "/verify-conversion",
            method: "POST",
            data : {
                conversion : conversion
            },
            success: function(data) {
                // reload the page, update the user state, etc.
            }
        });
    }
});

Viewing webhooks

There are two ways to view all previously-sent webhooks in your account. You can either call the/publisher/webhook/list API method directly or you can log into your Piano application and navigate to the webhooks screen by going to ManageWebhooks.

The webhooks screen will provide you with a list of past webhook requests, the status of each request (success, pending, or failed), the date attempted, the associated user, and an option to resend the request. You can also view the webhook’s header, body, and response messages. Note, that we retain the response body only for unsuccessful requests. If your endpoint's response will contain additional data, this information will be logged in the body section of the webhook.

On the screen you'll also see an indicator that shows the current webhook status:

Webhooks

This indicates that webhooks are processing normally and no action is needed. If the webhooks indicator is red, this means that there is a webhook blocking future processing. In that case, you should filter the webhooks to find only the failing ones and either skip or resend them.

If you've determined that your system does not need to receive a webhook, you can skip it manually from the dashboard. From the webhooks page, click the down arrow next to the failing webhook and press the Skip button. After you do this, Piano will attempt to send the next webhook.

You can list all webhooks by calling the API endpoint /publisher/webhook/list​ but to get specific webhooks you would need to pass the parameter webhook_id. More information is available here.

The webhooks feature is designed primarily for delivering events to publisher endpoints and is not intended as a high-performance event storage or querying mechanism. As such, it is not recommended to rely on the /publisher/webhook/list API endpoint as an event storage system. If long-term access to events is necessary, you should implement a custom storage solution, such as a database or Kafka. These systems allow for efficient event processing and the ability to replay events as needed.

The search functionality available through this endpoint is intended solely for ad-hoc investigations. It is not designed for reporting or automated resending of events. Attempting to use this feature for complex queries, particularly those involving a large number of events, may result in significant performance issues, such as rate limiting (HTTP status code 429) or timeouts.

To improve performance and avoid these issues, we recommend narrowing your query filters. For example, reducing the timeframe to the last few days can help limit the scope of the search and improve response times.

The lifespan of webhooks is limited to 1 month. This means, that you will only be able to access webhooks (and the responses/data) sent in the past 30 days, either via the Piano dashboard directly or also the API.

We retain the response body only for unsuccessful requests, omitting successful (HTTP 200) responses.

Exponential backoff on failure

Piano will automatically attempt to resend a webhook event in case your server is unavailable at any given moment. After six consecutive failures, an email will be sent to you notifying you of the issue. A second email will be sent after 20 failures. From the 24th attempt onward, an email will be sent for each additional failure until the webhook is successfully delivered, skipped, or the webhook endpoint is disabled. This logic applies to every attempt made to deliver each individual webhook event.

The system will cease its attempt to send webhooks after seven days of failures, at which point the webhook endpoint will be deactivated in your Piano application. Additional emails will be sent 24 hours, 8 hours, and 1 hour before deactivation. In the case of deactivation, you will have to manually turn webhooks back on to continue processing and any access events that happened between the deactivation and re-enabling will be lost. You will have to manually query Piano's API to sync your local datastore again.

The email address receiving these emails can be configured under Edit Business → Notification email.

Types of webhooks

Piano webhooks are sent based on access and content locking events. Access event webhooks are sent based on certain events happening within Piano that affect a user's access to a resource. These access events are grouped into three categories: granting, modifying, and revoking. Content locking events, on the other hand, are separated into two categories: lock and unlock.

Below is a full list of all webhook events along with descriptions and information about whether these events are triggered by you, the user, or Piano's system. The format of webhooks is standardized across all Piano webhook events. There are two fields that you should key off of to determine what has happened: the type field, which indicates the high-level event that has occurred, and the event field, which provides more detail about the specific event. Formatting examples for each type of event are provided below each table of events.

Subscription created

This event indicates that a user's subscription has been created:

Type

Event

Triggered By

Notes

subscription_created

new_purchase

User

Sent when end-user makes a purchase where a financial transaction took place. It will also fire when Print Subscription Confirmation (PSC) is redeemed. For free trials and free periods, the payment_verified event is sent instead.

subscription_created

payment_verified

User

Sent when a user signs up for a free trial or purchases a free dynamic term period.

subscription_created

term_applied_by_publisher

You

Sent when the end-user is subscribed to a term by the client representative and a financial transaction takes place.

subscription_created

payment_verified_by_publisher

You

Sent when end-user is subscribed to a term with a free trial or a free period.

subscription_created

term_change_finished

You, or User, or Piano

Sent when a subscription was successfully upgraded (specifically when a new subscription for this upgrade was created and payment was successful). Or when subscription entered the grace period upon upgrade had successfully exited the grace period.

subscription_created

term_change_grace_period_started

User or Piano

Sent when an upgrade was executed, but the newly created subscription for the new term entered a grace period because of the payment failure.

subscription_created

subscription_imported

Piano

Sent when a subscription was created by the import tool used by the Piano support team.

Contents of the webhook

Field

Type

Value

type

string

webhook type: subscription_created

version

string

2

typeTitle

string

webhook type title: Subscription created

event

string

event:

  • new_purchase

  • payment_verified

  • term_applied_by_publisher

  • payment_verified_by_publisher

  • term_change_finished

  • term_change_grace_period_started

  • subscription_imported

eventTitle

string

event title:

  • New purchase: for new_purchase event

  • No payment purchase: for payment_verified event

  • New purchase by publisher: for term_applied_by_publisher event

  • No payment purchase by publisher: for payment_verified_by_publisher event

  • Upgrade finished: for term_change_finished event

  • Upgrade grace period started: for term_change_grace_period_started event

  • Subscription imported: for subscription_imported event

aid

string

application id

uid

string

end-user id

user_email

string

end-user’s email address

term_id

string

term id

term_type

string

term type:

  • DYNAMIC: for dynamic subscriptions

  • PAYMENT: for recurring payment subscriptions;

rid

string

resource id

access_id

string

main access id, associated with subscription (access of subscription owner):

  • <end-user’s access id>: for not shared subscription

  • <PARENT end-user’s access id>: for shared subscription

subscription_id

string

subscription id

status

string

subscription status:

  • ACTIVE

  • COMPLETED

  • PENDING

  • NOT STARTED

create_date

long

subscription creation date

start_date

long

subscription start date (differs from subscription crate date for subscriptions purchased with the future start date and imported subscriptions)

next_bill_date

long

the value of the “next billing date” field of the subscription (not null):

billing_plan

string

billing plan of the last purchased period:

  • <billing plan of the last purchased access period>: for dynamic subscription

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription

access_period_id

string

id of the access the last purchased access period:

  • <access period id>: for dynamic subscription

  • null: for payment subscription

active_billing_plan

string

billing plan of the active period:

  • <billing plan of the active access period>: for dynamic subscription (active access period billing plan may be different from the last purchased access period billing plan in case of external manual renewal; for newly created subscription always the same value as in billing_plan parameter)

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription (always the same value as in billing_plan parameter for this type of subscription)

active_access_period_id

string

id of the access the active access period:

  • <access period id>: for dynamic subscription (active access period may be different from the last purchased access period in case of external manual renewal; for newly created subscription always the same value as in access_period_id parameter)

  • null: for payment subscription

upi_id

string

id of the renewal payment method associated with the subscription

auto_renew

boolean

the state of the auto-renew toggle associated with the subscription:

  • true: auto-renewal enabled - for payment subscription; the only possible value for dynamic subscription

  • false: auto-renewal disabled - for payment subscription; impossible value for dynamic subscription

is_in_grace

boolean

shows if the subscription is currently in grace period

grace_period_start_date

long

grace period start date

grace_period_length

int

grace period length in days

failure_counter

int

number of payment failures

passive_churn_logic_id

string

id of the churn prevention logic

decline_reason

string

decline reason for a payment attempt

payment_id

string

id of a payment associated with subscription creation

created_by

string

id of a user initiated the action that result in subscription creation

Examples

Example 1. Response to a term_applied_by_publisher event on a payment term
{
"type": "subscription_created",
"version": 2,
"typeTitle": "Subscription created",
"event": "term_applied_by_publisher",
"eventTitle": "New purchase by publisher",
"aid": "ss1h4oKtfc",
"uid": "e34495b7-b4ab-442d-b86a-67e91bf228d1",
"user_email": "demo@user.io",
"term_id": "TMSJR8VIH86D",
"term_type": "PAYMENT",
"rid": "RAMON2M",
"access_id": "94pvQDQFpR3L",
"subscription_id": "RCA3J7CYFH28",
"status": "ACTIVE",
"create_date": 1731055696,
"start_date": 1731055694,
"next_bill_date": 1733647694,
"billing_plan": "$15.00 per month",
"access_period_id": null,
"active_billing_plan": "$15.00 per month",
"active_access_period_id": null,
"upi_id": "PMWIWEQT8JTD",
"auto_renew": true,
"is_in_grace": false,
"grace_period_start_date": null,
"grace_period_length": null,
"failure_counter": 0,
"passive_churn_logic_id": null,
"decline_reason": null,
"payment_id": "UPRWT1LNKFKW",
"created_by": "LlfvQvlIwk"
}
Example 2. Response to a term_applied_by_publisher event on a dynamic term
{
"type": "subscription_created",
"version": 2,
"typeTitle": "Subscription created",
"event": "term_applied_by_publisher",
"eventTitle": "New purchase by publisher",
"aid": "ss1h4oKtfc",
"uid": "e34495b7-b4ab-442d-b86a-67e91bf228d1",
"user_email": "demo@user.io",
"term_id": "TMC2P9M6J5YU",
"term_type": "DYNAMIC",
"rid": "RCO8VOC",
"access_id": "6K3QY4sDH5sx",
"subscription_id": "RCFJE8ZK209T",
"status": "ACTIVE",
"create_date": 1731055839,
"start_date": 1731055836,
"next_bill_date": 1733647822,
"billing_plan": "$10.00/every 1 month(s)",
"access_period_id": "APGPK0QRA1EH",
"active_billing_plan": "$10.00/every 1 month(s)",
"active_access_period_id": "APGPK0QRA1EH",
"upi_id": "PMWIWEQT8JTD",
"auto_renew": true,
"is_in_grace": false,
"grace_period_start_date": null,
"grace_period_length": null,
"failure_counter": 0,
"passive_churn_logic_id": null,
"decline_reason": null,
"payment_id": "UPRAXJ9T95OR",
"created_by": "LlfvQvlIwk"
}

Subscription updated

This event indicates that a user's subscription has been updated:

Type

Event

Triggered by

Notes

subscription_updated

subscription_activated

Piano

Sent when a subscription with a future start date is activated

subscription_updated

subscription_access_period_activated

Piano

Sent when dynamic subscription entered manually purchased next access period (via manual renew functionality)

subscription_updated

subscription_next_bill_date_updated

You

Sent when the subscription's next billing date is updated manually in UI or via API (not applicable for dynamic terms)

subscription_updated

subscription_payment_method_updated

You or User

Sent when payment method associated with a subscription is updated (changed)

subscription_updated

subscription_address_updated

You or User

Sent when the payment address associated with a subscription is updated (changed). Not when the address is edited

subscription_updated

subscription_shared_accounts_updated

You or User

Sent when the list of shared accounts of a subscription is updated: manually (via MA/PD/API) or automatically (when the shared subscription is purchased, imported, or upgraded).

subscription_updated

subscription_auto_renew_enabled

You or User

Sent when subscription's auto-renew status had been changed to enabled (only applicable for payment subscriptions)

subscription_updated

subscription_auto_renew_disabled

You or User

Sent when the subscription's auto-renew status had been changed to disabled (only applicable for payment subscriptions)

subscription_updated

subscription_dynamic_unlimited_period_converted

Piano

Sent when dynamic subscription unlimited period had been converted to a period of another type. Action initiated by You, but done asynchronously

subscription_updated

subscription_deferred_canceled

You or User

Sent when dynamic subscription had been canceled

subscription_updated

subscription_resumed

You or User

Sent when dynamic subscription had been resumed

subscription_updated

subscription_access_period_scheduled

You or Piano

Sent when a specific access period of dynamic subscription was selected for the next renewal

subscription_updated

subscription_access_period_unscheduled

You or Piano

Sent when specific access period of dynamic subscription was unselected for next renewal (renewal will occur according to currently up-to-date billing configuration)

subscription_updated

subscription_rescheduled

Piano

Sent when scheduled subscription is re-activated because there was a new period added to the schedule associated with the scheduled term

subscription_updated

subscription_grace_period_started

Piano

Sent when subscription entered grace period upon the automated renewal

subscription_updated

subscription_grace_period_ended

Piano

Sent when the subscription successfully exited the grace period upon the automated/manual renewal

subscription_updated

term_change_scheduled

You or User

Sent when a deferred upgrade was scheduled for a subscription

subscription_updated

term_change_canceled

You

Sent when a scheduled deferred upgrade was canceled by You

subscription_updated

term_change_suspended

User

Sent when a scheduled deferred upgrade was canceled by the end-user (this action also triggers a deferred subscription cancellation)

subscription_updated

term_change_resumed

User

Sent when subscription with the suspended deferred upgrade was resumed (this action also re-activates the subscription)

subscription_updated

term_change_grace_period_ended

Piano or User

Sent when a subscription that was in a grace period started upon the upgrade had successfully exited the grace period

Contents of the webhook

Field

Type

Value

type

string

webhook type: subscription_updated

version

string

2

typeTitle

string

webhook type title: Subscription updated

event

string

event:

  • subscription_activated

  • subscription_access_period_activated

  • subscription_next_bill_date_updated

  • subscription_payment_method_updated

  • subscription_address_updated

  • subscription_shared_accounts_updated

  • subscription_auto_renew_enabled

  • subscription_auto_renew_disabled

  • subscription_dynamic_unlimited_period_converted

  • subscription_deferred_canceled

  • subscription_resumed

  • subscription_access_period_scheduled

  • subscription_access_period_unscheduled

  • subscription_rescheduled

  • subscription_grace_period_started

  • subscription_grace_period_ended

  • term_change_scheduled

  • term_change_canceled

  • term_change_suspended

  • term_change_resumed

  • term_change_grace_period_ended

eventTitle

string

event title:

  • Subscription_activated: for subscription_activated event

  • Subscription access period activated: for subscription_access_period_activated event

  • Subscription next bill date updated: for subscription_next_bill_date_updated event

  • Subscription payment method updated: for subscription_payment_method_updated event

  • Subscription address updated: for subscription_address_updated event

  • Subscription shared accounts updated: for subscription_shared_accounts_updated event

  • Subscription auto-renew enabled: for subscription_auto_renew_enabled event

  • Subscription auto-renew disabled: for subscription_auto_renew_disabled event

  • Subscription unlimited period converted: for subscription_dynamic_unlimited_period_converted event

  • Subscription canceled (deferred cancel): for subscription_deferred_canceled event

  • Subscription resumed: for subscription_resumed event

  • Subscription access period scheduled: for subscription_access_period_scheduled event

  • Subscription access period unscheduled: for subscription_access_period_unscheduled event

  • Scheduled subscription period activated: for subscription_rescheduled event

  • Subscription renewal grace period started: for subscription_grace_period_started event

  • Subscription renewal grace period ended: for subscription_grace_period_ended event

  • Upgrade scheduled: for term_change_scheduled event

  • Upgrade canceled: for term_change_canceled event

  • Upgrade suspended: for term_change_suspended event

  • Upgrade resumed: for term_change_resumed event

  • Upgrade grace period ended: for term_change_grace_period_ended event

aid

string

application id

uid

string

end-user id

user_email

string

end-user’s email address

term_id

string

term id

term_type

string

term type:

  • DYNAMIC: for dynamic subscriptions;

  • PAYMENT: for recurring payment subscriptions;

rid

string

resource id

access_id

string

main access id, associated with subscription (access of subscription owner):

  • <end-user’s access id>: for not shared subscription

  • <PARENT end-user’s access id>: for shared subscription

subscription_id

string

subscription id

status

string

subscription status:

  • ACTIVE

  • FAIL_AND_RETRY

  • COMPLETED

  • PENDING

  • NOT STARTED

create_date

long

subscription create date

start_date

long

subscription start date (differs from subscription crate date for subscriptions purchased with deferred start and imported subscriptions)

next_bill_date

long

the value of the “next billing date” field of the subscription (not null):

  • <next auto-renewal of the subscription> (date in the future): for active subscription for which auto-renewal is expected

  • <last auto-renewal/purchase date of the subscription> (date in the past): for inactive subscription or for an active subscription that normally should not have an auto-renewal date, because auto-renewal is not expected (subscription on unlimited period, subscription with disabled auto-renewal, subscription with scheduled upgrade etc.)

billing_plan

string

billing plan of the last purchased period:

  • <billing plan of the last purchased access period>: for dynamic subscription

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription

access_period_id

string

id of the access the last purchased access period:

  • <access period id>: for dynamic subscription

  • null: for payment subscription

active_billing_plan

string

billing plan of the active period:

  • <billing plan of the active access period>: for dynamic subscription (active access period billing plan may be different from the last purchased access period billing plan in case of external manual renewal)

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription (always the same value as in billing_plan parameter for this type of subscription)

active_access_period_id

string

id of the last access the active access period:

  • <access period id>: for dynamic subscription (active access period may be different from the last purchased access period in case of external manual renewal)

  • null: for payment subscription

upi_id

string

id of the renewal payment method associated with the subscription

auto_renew

boolean

the state of the auto-renew toggle associated with the subscription:

  • true: auto-renewal enabled - for payment subscription; the only possible value for dynamic subscription

  • false: auto-renewal disabled - for payment subscription; impossible value for dynamic subscription

shared_accounts

Array [UserSubscriptionAccount]

array of all shared accounts currently associated with the shared subscription (includes accounts with both redeemed and not redeemed accesses) - see the UserSubscriptionAccount model below

is_in_grace

boolean

shows if the subscription is currently in grace period

grace_period_start_date

long

grace period start date

grace_period_length

int

grace period length in days

failure_counter

int

number of payment failures

passive_churn_logic_id

string

id of the churn prevention logic

decline_reason

string

decline reason for a payment attempt

updated_by

string

id of a user initiated the action that resulted in subscription updating

UserSubscriptionAccount

The UserSubscriptionAccount object as part of the shared_account array in the subscripiton webhooks:

Field

Type

Value

account_id

string

id of shared account (any item added to the list as a potential CHILD end-user, no matter if the access was redeemed or not, no matter if this shared account has an associated CHILD end-user or not)

user_id

string

id of CHILD end-user associated with shared account:

  • <end-user’s id>: for accounts that have an associated CHILD end-user after access redemption

  • null: for accounts that do not have an associated CHILD end-user yet (email is not registered in the application, access is not redeemed)

email

string

email of shared account:

  • <shared account’s email>: for accounts that do not have an associated CHILD end-user yet

  • <shared account’s email> = <end-user’s email>: for accounts that that have an associated CHILD end-user (user info must always be in sync with shared account info, after end-user appears)

  • all other values are impossible for this webhook type

first_name

string

first name of shared account:

  • <shared account’s first name>: for accounts that do not have an associated CHILD end-user yet

  • <shared account’s first name> = <end-user’s first name>: for accounts that that have an associated CHILD end-user (user info must always be in sync with shared account info, after end-user appears)

  • all other values are impossible for this webhook type

last_name

string

last name of shared account:

  • <shared account’s last name>: for accounts that do not have an associated CHILD end-user yet

  • <shared account’s last name> = <end-user’s last name>: for accounts that that have an associated CHILD end-user (user info must always be in sync with shared account info, after end-user appears)

  • all other values are impossible for this webhook type

personal_name

string

personal name of shared account:

  • <shared account’s first name> + <shared account’s last name>: for accounts that have both first and last name

  • <shared account’s first name>, <shared account’s last name> or null: for accounts that do not have full info

  • all other values are impossible for this webhook type

redeemed

long

CHILD access redemption date:

  • <date-time of access manual/auto access redemption>: for accounts that have an associated CHILD end-user and redeemed access

  • null: for accounts that do not have an associated CHILD end-user and redeemed access yet

  • all other values are impossible for this webhook type

Examples

Example 1. Response to a subscription_payment_method_updated event on a payment term
{
  "type": "subscription_updated",
  "version": 2,
  "typeTitle": "Subscription updated",
  "event": "subscription_payment_method_updated",
  "eventTitle": "Subscription payment method updated",
  "aid": "hcxX89Lysu",
  "uid": "a8db5940-e6b0-4f80-a1ca-ff2efeb46e72",
  "user_email": "testUserParent@io.io",
  "term_id": "TMZLF8VXAPHX",
  "term_type": "PAYMENT",
  "rid": "R2YEUGI",
  "access_id": "OXaeX4AK6AfH",
  "subscription_id": "RCYBDXV83B68",
  "status": "ACTIVE",
  "create_date": 1748266932,
  "start_date": 1748266930,
  "next_bill_date": 1753537330,
  "billing_plan": "$22.00 per month",
  "access_period_id": null,
  "active_billing_plan": "$22.00 per month",
  "active_access_period_id": null,
  "upi_id": "PM24JSGH13M9",
  "auto_renew": true,
  "shared_accounts": [
    {
      "account_id": "SAV115Q6YHJR",
      "user_id": "2f597da0-b188-48b8-87c5-cba46cfb2ba6",
      "email": "testUserChild@io.io",
      "first_name": "firstName",
      "last_name": "lastName",
      "personal_name": "firstName lastName",
      "redeemed": 1748266945
    },
    {
      "account_id": "SASU7Z7JZKTA",
      "user_id": null,
      "email": "testUserChild2@io.io",
      "first_name": null,
      "last_name": null,
      "personal_name": null,
      "redeemed": null
    }
  ],
  "is_in_grace": false,
  "grace_period_start_date": null,
  "grace_period_length": null,
  "failure_counter": 0,
  "passive_churn_logic_id": null,
  "decline_reason": null,
  "updated_by": "3QriFCs2yx"
}
Example 2. Response to a subscription_deferred_canceled event on a dynamic term 
{
  "type": "subscription_updated",
  "version": 2,
  "typeTitle": "Subscription updated",
  "event": "subscription_deferred_canceled",
  "eventTitle": "Subscription canceled (deferred cancel)",
  "aid": "vb45MHjPsu",
  "uid": "3dfc67fe-9099-4b1a-9500-fc88239e7ccc",
  "user_email": "testUser@io.io",
  "term_id": "TM0KCBAS5F1M",
  "term_type": "DYNAMIC",
  "rid": "RNQUDNX",
  "access_id": "bb4Ne8g5Xswl",
  "subscription_id": "RC53ANJSK7LS",
  "status": "COMPLETED",
  "create_date": 1748601911,
  "start_date": 1748601908,
  "next_bill_date": 1756550693,
  "billing_plan": "$22.00/every 1 month(s)",
  "access_period_id": "APLHUFACWIJZ",
  "active_billing_plan": "$11.00/every 1 month(s)",
  "active_access_period_id": "APTZW610TP94",
  "upi_id": "PMV8USHYJO5W",
  "auto_renew": true,
"shared_accounts": [
    {
      "account_id": "SAV115Q6YHJR",
      "user_id": "2f597da0-b188-48b8-87c5-cba46cfb2ba6",
      "email": "testUserChild@io.io",
      "first_name": "firstName",
      "last_name": "lastName",
      "personal_name": "firstName lastName",
      "redeemed": 1748266945
    },
    {
      "account_id": "SASU7Z7JZKTA",
      "user_id": null,
      "email": "testUserChild2@io.io",
      "first_name": null,
      "last_name": null,
      "personal_name": null,
      "redeemed": null
    }
  ],
  "is_in_grace": false,
  "grace_period_start_date": null,
  "grace_period_length": null,
  "failure_counter": 0,
  "passive_churn_logic_id": null,
  "decline_reason": null,
  "updated_by": "2Wkp0eI7hL"
}

Subscription renewal

This event indicates that a user's subscription has been renewed:

Type

Event

Triggered by

Notes

subscription_renewal

subscription_auto_renewed

Piano

Sent when Piano's system successfully auto-renews a user's subscription, including the successful completion of the grace period. If an auto-renewal fails, the subscription_auto_renewed_failure or subscription_auto_renewed_auth_failure event is sent instead.

subscription_renewal

subscription_manually_renewed

You or User

Sent when a user manually renews a subscription, or when you manually renew a user's subscription on the user's behalf.

subscription_renewal

subscription_auto_renewed_failure

Piano

Sent when Piano's system is unable to auto-renew a user's subscription due to any reason, but mostly because of the payment failure. This includes all cases of payment failure: immediate subscription expiration if there is no grace period, grace period starting after the first payment failure, all unsuccessful payment attempts in the grace period, and subscription expiration after the last payment attempt in the grace period. If an auto-renewal fails due to a 3DS authentication failure, the subscription_auto_renewed_auth_failure event is sent instead.

subscription_renewal

subscription_auto_renewed_auth_failure

Piano

Sent instead of the subscription_auto_renewed_failure event when an auto-renewal fails due to a 3DS authentication failure.

Contents of the webhook

Field

Type

Value

type

string

webhook type: subscription_renewal

version

string

2

typeTitle

string

webhook type title: Subscription renewal

event

string

event:

  • subscription_auto_renewed

  • subscription_manually_renewed

  • subscription_auto_renewed_failure

  • subscription_auto_renewed_auth_failure

eventTitle

string

event title:

  • Subscription was automatically renewed: for subscription_auto_renewed event

  • Subscription was manually renewed: for subscription_manually_renewed event

  • Failure of automatic subscription renewal: for subscription_auto_renewed_failure event

  • 3DS authentication payment error
    during automatic subscription renewal: for subscription_auto_renewed_auth_failure event

aid

string

application id

uid

string

end-user id

user_email

string

end-user’s email address

term_id

string

term id

term_type

string

term type:

  • DYNAMIC: for dynamic subscriptions;

  • PAYMENT: for recurring payment subscriptions;

rid

string

resource id

access_id

string

main access id, associated with subscription (access of subscription owner):

  • <end-user’s access id>: for not shared subscription

  • <PARENT end-user’s access id>: for shared subscription

subscription_id

string

subscription id

status

string

subscription status:

  • ACTIVE

  • UPGRADED

create_date

long

subscription create date

start_date

long

subscription start date (differs from subscription crate date for subscriptions purchased with deferred start and imported subscriptions)

next_bill_date

long

the value of the “next billing date” field of the subscription (not null):

  • <next auto-renewal of the subscription> (date in the future): for active subscription for which auto-renewal is expected

  • <last auto-renewal/purchase date of the subscription> (date in the past): for inactive subscription or for active subscription that normally should not have auto-renewal date, because auto-renewal is not expected (subscription on unlimited period, subscription with disabled auto-renewal, subscription with scheduled upgrade etc.)

billing_plan

string

billing plan of the last purchased period:

  • <billing plan of the last purchased access period>: for dynamic subscription

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription

access_period_id

string

id of the access the last purchased access period:

  • <access period id>: for dynamic subscription

  • null: for payment subscription

active_billing_plan

string

billing plan of the active period:

  • <billing plan of the active access period>: for dynamic subscription (active access period billing plan may be different from the last purchased access period billing plan in case of external manual renewal)

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription (always the same value as in billing_plan parameter for this type of subscription)

active_access_period_id

string

id of the last access the active access period:

  • <access period id>: for dynamic subscription (active access period may be different from the last purchased access period in case of external manual renewal)

  • null: for payment subscription

upi_id

string

id of the renewal payment method associated with the subscription

auto_renew

boolean

the state of the auto-renew toggle associated with the subscription:

  • true: auto-renewal enabled - for payment subscription; the only possible value for dynamic subscription

  • false: auto-renewal disabled - for payment subscription; impossible value for dynamic subscription

shared_accounts

Array [UserSubscriptionAccount]

array of all shared accounts currently associated with the shared subscription (includes accounts with both redeemed and not redeemed accesses) - see the UserSubscriptionAccount model above

is_in_grace

boolean

shows if the subscription is currently in grace period

grace_period_start_date

long

grace period start date

grace_period_length

int

grace period length in days

failure_counter

int

number of payment failures

passive_churn_logic_id

string

id of the churn prevention logic

decline_reason

string

decline reason for a payment attempt

payment_id

string

id of a payment associated with subscription creation

renewal_type

string

renewal type:

  • RENEWAL: for all renewals of recurring payment subscriptions, EVT subscriptions, linked subscriptions; for external renewal of dynamic subscription

  • BILLING: for internal renewal of dynamic subscription

renewed_by

string

id of a user initiated the action that resulted in subscription updating

Examples

Example 1. Response to a subscription_auto_renewed event on a payment term
{
  "type": "subscription_renewal",
  "version": 2,
  "typeTitle": "Subscription renewal",
  "event": "subscription_auto_renewed",
  "eventTitle": "Subscription was automatically renewed",
  "aid": "hcxX89Lysu",
  "uid": "a8db5940-e6b0-4f80-a1ca-ff2efeb46e72",
  "user_email": "testUserParent@io.io",
  "term_id": "TMZLF8VXAPHX",
  "term_type": "PAYMENT",
  "rid": "R2YEUGI",
  "access_id": "OXaeX4AK6AfH",
  "subscription_id": "RCYBDXV83B68",
  "status": "ACTIVE",
  "create_date": 1748266932,
  "start_date": 1748266930,
  "next_bill_date": 1753537330,
  "billing_plan": "$22.00 per month",
  "access_period_id": null,
  "active_billing_plan": "$22.00 per month",
  "active_access_period_id": null,
  "upi_id": "PM24JSGH13M9",
  "auto_renew": true,
  "shared_accounts": [
    {
      "account_id": "SAV115Q6YHJR",
      "user_id": "2f597da0-b188-48b8-87c5-cba46cfb2ba6",
      "email": "testUserChild@io.io",
      "first_name": "firstName",
      "last_name": "lastName",
      "personal_name": "firstName lastName",
      "redeemed": 1748266945
    },
    {
      "account_id": "SASU7Z7JZKTA",
      "user_id": null,
      "email": "testUserChild2@io.io",
      "first_name": null,
      "last_name": null,
      "personal_name": null,
      "redeemed": null
    }
  ],
  "is_in_grace": false,
  "grace_period_start_date": null,
  "grace_period_length": null,
  "failure_counter": 0,
  "passive_churn_logic_id": null,
  "decline_reason": null,
  "payment_id": "UPTXUR9N7YM0",
  "renewal_type": "RENEWAL",
  "renewed_by": "3QriFCs2yx"
}
Example 2. Response to a subscription_manually_renewed event on a dynamic term
{
  "type": "subscription_renewal",
  "version": 2,
  "typeTitle": "Subscription renewal",
  "event": "subscription_manually_renewed",
  "eventTitle": "Subscription was manually renewed by user",
  "aid": "vb45MHjPsu",
  "uid": "3dfc67fe-9099-4b1a-9500-fc88239e7ccc",
  "user_email": "testUser@io.io",
  "term_id": "TM0KCBAS5F1M",
  "term_type": "DYNAMIC",
  "rid": "RNQUDNX",
  "access_id": "bb4Ne8g5Xswl",
  "subscription_id": "RC53ANJSK7LS",
  "status": "ACTIVE",
  "create_date": 1748601911,
  "start_date": 1748601908,
  "next_bill_date": 1756550693,
  "billing_plan": "$22.00/every 1 month(s)",
  "access_period_id": "APLHUFACWIJZ",
  "active_billing_plan": "$11.00/every 1 month(s)",
  "active_access_period_id": "APTZW610TP94",
  "upi_id": "PMV8USHYJO5W",
  "auto_renew": true,
  "shared_accounts": [
    {
      "account_id": "SAV115Q6YHJR",
      "user_id": "2f597da0-b188-48b8-87c5-cba46cfb2ba6",
      "email": "testUserChild@io.io",
      "first_name": "firstName",
      "last_name": "lastName",
      "personal_name": "firstName lastName",
      "redeemed": 1748266945
    },
    {
      "account_id": "SASU7Z7JZKTA",
      "user_id": null,
      "email": "testUserChild2@io.io",
      "first_name": null,
      "last_name": null,
      "personal_name": null,
      "redeemed": null
    }
],
  "is_in_grace": false,
  "grace_period_start_date": null,
  "grace_period_length": null,
  "failure_counter": 0,
  "passive_churn_logic_id": null,
  "decline_reason": null,
  "payment_id": "UPN0R55BAXL5",
  "renewal_type": "RENEWAL",
  "renewed_by": "2Wkp0eI7hL"
}

Subscription ended

This event indicates that a user's subscription has ended:

Type

Event

Triggered by

Notes

subscription_ended

subscription_canceled

You or User

Sent when a subscription is canceled using the immediate cancellation button

subscription_ended

subscription_expired

Piano

Sent when subscription renewal had failed and there is no grace period configured OR when subscription was canceled and not going to renew OR when there's no next access period configured in the term for this subscription

subscription_ended

term_change_aborted

Piano

Sent for subscription FROM when subscription with suspended upgrade reached renewal date and didn't upgrade

subscription_ended

term_change_finished

You, or User, or Piano

Sent for subscription FROM when subscription upgrade was successfully executed

subscription_ended

term_change_failure

Piano

Sent for the subscription FROM when a scheduled upgrade was not successful and there is no grace period configured in the term TO

subscription_ended

term_change_grace_period_started

Piano

Sent when an upgrade was executed, but the newly created subscription for the new term entered a grace period because of a payment failure.

Contents of the webhook

Field

Type

Value

type

string

webhook type: subscription_ended

version

string

2

typeTitle

string

webhook type title: Subscription ended

event

string

event:

  • subscription_canceled

  • subscription_expired

  • term_change_aborted

  • term_change_finished

  • term_change_failure

  • term_change_grace_period_started

eventTitle

string

event title:

  • Subscription canceled (immediate cancel): for subscription_canceled event

  • Subscritption expired: for subscription_expired event

  • Upgrade aborted: for term_change_aborted event

  • Upgrade finished: for term_change_finished event

  • Upgrade failure: for term_change_failure event

  • Upgrade grace period started: for term_change_grace_period_started event

aid

string

application id

uid

string

end-user id

user_email

string

end-user’s email address

term_id

string

term id

term_type

string

term type:

  • DYNAMIC: for dynamic subscriptions;

  • PAYMENT: for recurring payment subscriptions;

  • all other values are impossible for this webhook type

rid

string

resource id

access_id

string

main access id, associated with subscription (access of subscription owner):

  • <end-user’s access id>: for not shared subscription

  • <PARENT end-user’s access id>: for shared subscription

subscription_id

string

subscription id

status

string

subscription status:

  • CANCELLED

  • EXPIRED_WITH_ERROR

  • EXPIRED

  • UPGRADED

create_date

long

subscription create date

start_date

long

subscription start date (differs from subscription crate date for subscriptions purchased with deferred start and imported subscriptions)

next_bill_date

long

the value of the “next billing date” field of the subscription (not null):

  • <last auto-renewal/purchase date of the subscription> (date in the past): for inactive subscription or for an active subscription that normally should not have an auto-renewal date, because auto-renewal is not expected (subscription on unlimited period, subscription with disabled auto-renewal, subscription with scheduled upgrade etc.)

  • all other values are impossible for this webhook type

billing_plan

string

billing plan of the last purchased period:

  • <billing plan of the last purchased access period>: for dynamic subscription

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription

access_period_id

string

id of the access the last purchased access period:

  • <access period id>: for dynamic subscription

  • null: for payment subscription

active_billing_plan

string

billing plan of the last active period:

  • <billing plan of the active access period>: for dynamic subscription (active access period billing plan may be different from the last purchased access period billing plan in case of external manual renewal)

  • <full billing plan of the payment subscription>: for recurring payment subscription with or without trial; same value for the full life of the subscription (always the same value as in billing_plan parameter for this type of subscription)

active_access_period_id

string

id of the last access the active access period:

  • <access period id>: for dynamic subscription (active access period may be different from the last purchased access period in case of external manual renewal)

  • null: for payment subscription

upi_id

string

id of the renewal payment method associated with the subscription

auto_renew

boolean

the state of the auto-renew toggle associated with the subscription:

  • true: auto-renewal enabled - for payment subscription; the only possible value for dynamic subscription

  • false: auto-renewal disabled - for payment subscription; impossible value for dynamic subscription

shared_accounts

Array [UserSubscriptionAccount]

array of all shared accounts currently associated with the shared subscription (includes accounts with both redeemed and not redeemed accesses) - see the UserSubscriptionAccount model above

is_in_grace

boolean

shows if the subscription is currently in a grace period:

  • false: subscription is not in the grace period of any type (ended subscription renewals are expected to be not in a grace period)

  • all other values are impossible for this webhook type

grace_period_start_date

long

grace period start date:

  • null: for subscription outside of a grace period (is_in_grace = false) (ended subscriptions renewal are expected to be not in a grace period)

  • all other values are impossible for this webhook type

grace_period_length

int

grace period length in days:

  • null: for subscription outside of a grace period (is_in_grace = false) (ended subscriptions renewal are expected to be not in a grace period)

  • all other values are impossible for this webhook type

failure_counter

int

number of payment failures:

  • <number of last failure> (1, 2, 3, 4… ): for subscriptions that become inactive after being in a grace period or after payment failure when the grace period could not start

  • 0: for subscriptions that become inactive while having 0 as failure_counter value (outside of grace period but been in grace period at least once)

  • null: for inactive subscriptions that have never been in a grace period

  • all other values are impossible for this webhook type

passive_churn_logic_id

string

id of the churn prevention logic:

  • <id>: for subscriptions that become inactive while being in a grace period (is_in_grace = true) when the passive churn prevention feature is enabled

  • null: for inactive subscription when the passive churn prevention feature is disabled

  • all other values are impossible for this webhook type

decline_reason

string

decline reason for a payment attempt:

  • <reason>: for all cases when passive_churn_logic_id has a value

  • null: for all cases when passive_churn_logic_id doesn’t have a value

ended_by

string

id of a user initiated the action that resulted in the subscription ending:

  • <end-user’s id>: subscription cancellation (immediate cancel) via MA

  • <client user’s id>: subscription cancellation (immediate cancel) via PD/API

  • <admin user’s id>: subscription cancellation (immediate cancel) via AD

  • null: expiration of a payment subscription with disabled auto-renewal; expiration of a canceled subscription (deferred cancel); expiration of a subscription with suspended pending upgrade; pending individual upgrade scheduled via MA/PD/onsite/API successful/unsuccessful execution; pending upgrade scheduled in bulk successful/unsuccessful execution; renewal failure with no grace period; payment failure on the last additional attempt in grace period after failure on upgrade or renewal

Examples

Example 1. Response to a subscription_canceled event on a payment term 
{
  "type": "subscription_ended",
  "version": 2,
  "typeTitle": "Subscription ended",
  "event": "subscription_canceled",
  "eventTitle": "Subscription canceled (immediate cancel)",
  "aid": "hcxX89Lysu",
  "uid": "a8db5940-e6b0-4f80-a1ca-ff2efeb46e72",
  "user_email": "testUserParent@io.io",
  "term_id": "TMZLF8VXAPHX",
  "term_type": "PAYMENT",
  "rid": "R2YEUGI",
  "access_id": "OXaeX4AK6AfH",
  "subscription_id": "RCYBDXV83B68",
  "status": "CANCELLED",
  "create_date": 1748266932,
  "start_date": 1748266930,
  "next_bill_date": 1753537330,
  "billing_plan": "$22.00 per month",
  "access_period_id": null,
  "active_billing_plan": "$22.00 per month",
  "active_access_period_id": null,
  "upi_id": "PM24JSGH13M9",
  "auto_renew": true,
  "shared_accounts": [
    {
      "account_id": "SAV115Q6YHJR",
      "user_id": "2f597da0-b188-48b8-87c5-cba46cfb2ba6",
      "email": "testUserChild@io.io",
      "first_name": "firstName",
      "last_name": "lastName",
      "personal_name": "firstName lastName",
      "redeemed": 1748266945
    },
    {
      "account_id": "SASU7Z7JZKTA",
      "user_id": null,
      "email": "testUserChild2@io.io",
      "first_name": null,
      "last_name": null,
      "personal_name": null,
      "redeemed": null
    }
  ],
  "is_in_grace": false,
  "grace_period_start_date": null,
  "grace_period_length": null,
  "failure_counter": 0,
  "passive_churn_logic_id": null,
  "decline_reason": null,
  "ended_by": "3QriFCs2yx"
}
Example 2. Response to a subscription_expired event on a dynamic term 
{
  "type": "subscription_ended",
  "version": 2,
  "typeTitle": "Subscription ended",
  "event": "subscription_expired",
  "eventTitle": "Subscription expired",
  "aid": "vb45MHjPsu",
  "uid": "3dfc67fe-9099-4b1a-9500-fc88239e7ccc",
  "user_email": "testUser@io.io",
  "term_id": "TM0KCBAS5F1M",
  "term_type": "DYNAMIC",
  "rid": "RNQUDNX",
  "access_id": "bb4Ne8g5Xswl",
  "subscription_id": "RC53ANJSK7LS",
  "status": "EXPIRED",
  "create_date": 1748601911,
  "start_date": 1748601908,
  "next_bill_date": 1759229093,
  "billing_plan": "$22.00/every 1 month(s)",
  "access_period_id": "APLHUFACWIJZ",
  "active_billing_plan": "$22.00/every 1 month(s)",
  "active_access_period_id": "APLHUFACWIJZ",
  "upi_id": "PMV8USHYJO5W",
  "auto_renew": true,
 "shared_accounts": [
    {
      "account_id": "SAV115Q6YHJR",
      "user_id": "2f597da0-b188-48b8-87c5-cba46cfb2ba6",
      "email": "testUserChild@io.io",
      "first_name": "firstName",
      "last_name": "lastName",
      "personal_name": "firstName lastName",
      "redeemed": 1748266945
    },
    {
      "account_id": "SASU7Z7JZKTA",
      "user_id": null,
      "email": "testUserChild2@io.io",
      "first_name": null,
      "last_name": null,
      "personal_name": null,
      "redeemed": null
    }
  ],
  "is_in_grace": false,
  "grace_period_start_date": null,
  "grace_period_length": null,
  "failure_counter": 0,
  "passive_churn_logic_id": null,
  "decline_reason": null,
  "ended_by": "2Wkp0eI7hL"
}

Subscription upgrade

This event indicates that a user's subscription has been changed to a new term:

Type

Event

Triggered by

Notes

term_change

term_change_scheduled

You or User

Sent when a user initiates a pending upgrade of their subscription, or when you initiate a pending upgrade of a user's subscription (including bulk upgrades).

term_change

term_change_finished

You, or User, or Piano

Sent when a user immediately upgrades their subscription, or when you immediately upgrade a user's subscription on the user's behalf. Also sent when Piano's system successfully completes a previously scheduled pending upgrade of a user's subscription, including the successful completion of the grace period. If an upgrade fails, the term_change_failure event is sent instead.

 term_change

 term_change_canceled

You

Sent when you cancel a previously scheduled pending upgrade of a user's subscription on the user's behalf.

 term_change

 term_change_suspended

 User

Sent when a user suspends a previously scheduled pending upgrade of their subscription.

 term_change

 term_change_resumed

User

Sent when a user resumed a previously suspended pending upgrade of their subscription.

term_change

 term_change_aborted

Piano

Sent when subscription with suspended upgrade reached renewal date and didn't upgrade

 term_change

 term_change_failure

Piano

Sent when Piano's system is unable to complete a previously scheduled pending upgrade of a user's subscription due to any reason, but mostly because of the payment failure. This includes all cases of payment failure: immediate old subscription expiration without creating a new one if there is no grace period, grace period start for a new subscription after first payment failure, all unsuccessful payment attempts in the grace period, new subscription expiration after last payment attempt in the grace period.

 term_change

term_change_grace_period_started

Piano

Sent when an upgrade was executed, but the newly created subscription for the new term entered a grace period because of a payment failure.

 term_change

term_change_grace_period_ended

Piano

Sent when the subscription exits grace period on renewal/billing attempt, grace period expiration or subscription cancellation.

 term_changed

term_change

You or User

Deprecated. Please useterm_change_scheduled and term_change_finished events of the term_change webhook type instead. Sent when a user initiates their subscription upgrade or when you upgrade a user's subscription.

term_change_finished

term_change_finished

Piano

Deprecated. Please useterm_change_finished event of the term_change webhook type instead. Sent on the day of the actual upgrade.

Contents of the webhook

Field

Type

Value

type

string

webhook type: term_change

version

string

2

typeTitle

string

webhook type title: Upgrade

event

string

event:

  • term_change_scheduled

  • term_change_finished

  • term_change_canceled

  • term_change_suspended

  • term_change_resumed

  • term_change_aborted

  • term_change_failure

  • term_change_grace_period_started

  • term_change_grace_period_ended

eventTitle

string

event title:

  • Upgrade scheduled: for term_change_scheduled event

  • Upgrade finished: for term_change_finished event

  • Upgrade canceled: for term_change_canceled event

  • Upgrade suspended: for term_change_suspended event

  • Upgrade resumed: for term_change_resumed event

  • Upgrade aborted: for term_change_aborted event

  • Upgrade failure: for term_change_failure event

  • Upgrade grace period started: for term_change_grace_period_started event

  • Upgrade grace period ended: for term_change_grace_period_ended event

aid

string

application id

uid

string

end-user id

user_email

string

end-user’s email address

previous_term_id

string

termFROM id

previous_term_name

string

termFROM name

previous_subscription_id

string

subscriptionFROM id

previous_subscription_rid

string

resourceFROM id

previous_subscription_access_id

string

accessFROM id

previous_billing_plan

string

billing plan of the last period of subscriptionFROM:

  • <billing plan of the last active access period of subscriptionFROM = AP with id from previous_access_period_id>: for dynamic subscription

  • <full billing plan of the payment subscriptionFROM>: for recurring payment subscription with or without trial; same value for the full life of the subscription

previous_access_period_id

string

access period id of the last period of subscriptionFROM:

  • <access period id>: for dynamic subscriptionFROM

  • null: for recurring subscriptionFROM

new_term_id

string

termTO id

new_term_name

string

termTO name

new_subscription_id

string

subscriptionTO id

new_subscription_rid

string

resourceTO id

new_subscription_access_id

string

accessTO id

new_billing_plan

string

billing plan of the first period of subscriptionTO (period, purchased on upgrade):

  • <billing plan of the access period purchased on upgrade = AP with id from new_subscription_access_id>: for dynamic subscription

  • <full billing plan of the payment subscriptionTO>: for recurring payment subscription with or without trial; same value for the full life of the subscription

new_access_period_id

string

access period id of the first period of subscriptionTO (period, purchased on upgrade):

  • <access period id>: for dynamic subscriptionTO

  • null: for recurring subscriptionTO

new_subscription_next_bill_date

long

the value of the “next billing date” field of the subscriptionTO (not null):

  • <next auto-renewal of the subscriptionTO> (date in the future): for active subscriptionTO for which auto-renewal is expected

  • <last auto-renewal/purchase date of the subscriptionTO> (date in the past): for inactive subscriptionTO or for active subscriptionTO that normally should not have auto-renewal date, because auto-renewal is not expected (subscription on unlimited period, subscription with disabled auto-renewal, subscription with scheduled upgrade etc.)

  • all other values are impossible for this webhook type

date_of_access_change

long

date of actual access change:

  • <date of granting temporary access for subscriptionTO = date of pending upgrade scheduling>: for pending upgrades when granting temporary access is configured for upgrade

  • <subscriptionTO start date = expected upgrade execution date for pending upgrade = upgrade execution date for immediate upgrade>: for pending upgrades when granting temporary access is not configured for upgrade; for immediate upgrade

date_of_billing_change

long

date of actual billing plan change:

  • <expected upgrade execution date>: for the cases of pending upgrade when the actual upgrade is only scheduled

  • <subscriptionTO start date = upgrade execution date>: for the cases where the upgrade has been executed and was successful or a grace period was provided

  • null: for the cases where the upgrade has been executed and failed without providing a grace period

upi_id

string

id of the renewal payment method associated with the subscriptionTO (same as for subscriptionFROM)

is_in_grace

boolean

shows if the subscriptionTO is currently in grace period:

  • true: subscriptionTO is in grace period of any type (for this webhook type only the case of grace period after upgrade failure is suitable)

  • false: subscriptionTO is not in grace period of any type

grace_period_start_date

long

grace period start date:

  • <date>: for subscriptionTO in a grace period (is_in_grace = true)

  • null: for subscriptionTO outside of a grace period (is_in_grace = false)

grace_period_length

int

grace period length in days:

  • <days>: for subscriptionTO in a grace period (is_in_grace = true)

  • null: for subscriptionTO outside of a grace period (is_in_grace = false)

failure_counter

int

number of payment failures for subscriptionTO:

  • 1: for active subscriptionTO in a grace period (is_in_grace = true) after first payment failure - grace period start

  • <number of failure> (2, 3, 4… ): for active subscriptionTO in a grace period (is_in_grace = true) after payment failure in the middle of the grace period

  • <number of last failure> (1, 2, 3, 4… ): for subscriptionTO that become inactive after being in grace period or after payment failure when grace period could not start

  • 0: for active subscriptionTO outside of a grace period (is_in_grace = false) that has been in grace period at least once (this also includes the case of successful end of the grace period); for subscription that become inactive while having 0 as failure_counter value

  • null: for active or inactive subscriptionTO outside of a grace period (is_in_grace = false) and never been in grace period

passive_churn_logic_id

string

id of the churn prevention logic:

  • <id>: for active subscriptionTO in a grace period (is_in_grace = true) when passive churn prevention feature is enabled; for subscriptionTO that become inactive while being in a grace period (is_in_grace = true) when passive churn prevention feature is enabled

  • null: for active or inactive subscriptionTO in grace period or outside of it when passive churn prevention feature is disabled; for active subscriptionTO outside of grace period (is_in_grace = false) when passive churn feature is enabled

decline_reason

string

decline reason for a payment attempt:

  • <reason>: for all cases when passive_churn_logic_id has a value

  • null: for all cases when passive_churn_logic_id doesn’t have a value

payment_id

string

id of a payment associated with upgrade:

<id>: for term_change_finished (for successfully executed upgrade with payment), term_change_grace_period_ended (for successful grace period end) events

null: for term_change_scheduled, term_change_finished (for successfully executed upgrade without payment/with refund), term_change_canceled, term_change_suspended, term_change_resumed, term_change_aborted, term_change_failure, term_change_grace_period_started, term_change_grace_period_ended (for unsuccessful grace period end without transaction attempt or for unsuccessful grace period end after last transaction attempt) events

changed_by

string

id of a user initiated the upgrade or upgrade related action:

  • <end-user’s id>: immediate individual upgrade via MA/onsite successful execution; immediate individual onsite upgrade failure execution with grace start; pending individual upgrade via MA/onsite scheduling; successful grace period end after additional manual attempt via MA; scheduled upgrade suspension via MA; suspended upgrade resumption via MA

  • <client user’s id>: immediate individual upgrade via PD/API successful execution; pending individual upgrade via PD/API scheduling; pending bulk upgrade scheduling; successful grace period end after additional manual attempt via PD; scheduled upgrade cancelation via PD

  • null: pending individual upgrade scheduled via MA/PD/onsite/API successful execution; pending individual upgrade scheduled via MA/PD/onsite/API failure execution with grace start; pending upgrade scheduled in bulk successful execution; pending upgrade scheduled in bulk failure execution with grace start; additional payment attempts in grace period; successful grace period end after additional automatic attempt; unsuccessful grace period end after last additional automatic attempt; unsuccessful grace period end without transaction attempt - subscriptionTO cancelation, subscriptionTO expiration; suspended upgrade abortion

Examples

Example 1. Response to a term_change_finished event upon a successful upgrade of a payment term
{
"type": "term_change",
"version": 2,
"typeTitle": "Upgrade",
"event": "term_change_finished",
"eventTitle": "Upgrade finished",
"aid": "O28Dlkumsu",
"uid": "915c1d38-de94-46b8-a53c-d61f5f9a33f3",
"user_email": "test1@piano.io",
"previous_term_id": "TMUVP8YL3VU1",
"previous_term_name": "Payment FROM",
"previous_subscription_id": "RC0QR1FFOAZH",
"previous_subscription_rid": "R7QL719",
"previous_subscription_access_id": "XiZ3apUFEInE",
"previous_billing_plan": "$5.00 per month",
"previous_access_period_id": null,
"new_term_id": "TM4M8XNBXDUK",
"new_term_name": "Payment TO",
"new_subscription_id": "RCL2OKUORZ5P",
"new_subscription_rid": "RYNS2PZ",
"new_subscription_access_id": "H9pzzXdR7iFh",
"new_billing_plan": "$10.00 per month",
"new_access_period_id": null,
"new_subscription_next_bill_date": 1736678844,
"date_of_access_change": 1734000444,
"date_of_billing_change": 1734001271,
"upi_id": "PMIAAO7HZ4XF",
"is_in_grace": false,
"grace_period_start_date": null,
"grace_period_length": null,
"failure_counter": 0,
"passive_churn_logic_id": null,
"decline_reason": null,
"payment_id": "UP54X6BTA44T",
"changed_by": "915c1d38-de94-46b8-a53c-d61f5f9a33f3"
}
Example 2. Response to term_change_failure event upon an unsuccessful upgrade of a payment term
{
"type": "term_change",
"version": 2,
"typeTitle": "Upgrade",
"event": "term_change_failure",
"eventTitle": "Upgrade failure",
"aid": "O28Dlkumsu",
"uid": "915c1d38-de94-46b8-a53c-d61f5f9a33f3",
"user_email": "test1@piano.io",
"previous_term_id": "TMUVP8YL3VU1",
"previous_term_name": "Payment FROM",
"previous_subscription_id": "RCURT95NV8FL",
"previous_subscription_rid": "R7QL719",
"previous_subscription_access_id": "EP9I7cmch94Y",
"previous_billing_plan": "$5.00 per month",
"previous_access_period_id": null,
"new_term_id": "TMIY12FRWXF7",
"new_term_name": "Payment TO without GRACE",
"new_subscription_id": null,
"new_subscription_rid": "R9O828L",
"new_subscription_access_id": null,
"new_billing_plan": "$10.00 per month",
"new_access_period_id": null,
"new_subscription_next_bill_date": null,
"date_of_access_change": 1734077643,
"date_of_billing_change": null,
"upi_id": "PMIAAO7HZ4XF",
"is_in_grace": null,
"grace_period_start_date": null,
"grace_period_length": null,
"failure_counter": null,
"passive_churn_logic_id": null,
"decline_reason": "CALL_ISSUER",
"payment_id": null,
"changed_by": null
}

Access granted

These are all of the events that result in new access:

Type

Event

Triggered by

Notes

access_granted

new_purchase

User

Sent when a user makes a purchase where a financial transaction that took place. It will also fire when Print Subscription Confirmation (PSC) is redeemed. For free trials, the payment_verified event is sent instead.

access_granted

payment_verified

User

Sent when a user signs up for a free trial. This event is only sent for free trials where the user will eventually be charged. If the user has a promo code that gives them 100% off of a fixed-time purchase, the free_promo_redemption event is sent instead.

access_granted

term_applied_by_publisher

You

Sent when you create a user's subscription via the dashboard on the user's behalf.

access_granted

payment_verified_by_publisher

You

Sent when end-user is subscribed to a term with a free trial or a free period.

access_granted

subscription_imported

You

Sent when a subscription is created by the import tool used by the Piano support team.

access_granted

free_access_granted

You

Sent when you use the Piano Dashboard to grant a user access.

access_granted

free_promo_redemption

User

Sent when a user redeems a promo code for 100% off of a fixed-time purchase. If a user redeems a promo code where there is a transaction that takes place (or will take place in the case of a free trial), either the new_purchase or payment_verified events are sent instead.

access_granted

psc_purchase

User

Sent when a user is granted access after providing their address information on your website for the purpose of the PSC.

access_granted

cross_app_access_granted

Piano

Sent when cross app access has been granted.

access_granted

new_registration_conversion

User

Sent when a user is granted access in return for registering on your website.

access_granted

new_custom_term_conversion

You

Sent when a user converts on a custom term.

access_granted

new_site_license_conversion

User

Sent when a user redeems access under site license.

access_granted

term_change_finished

You, or User, or Piano

Sent upon a successful subscription upgrade.
Triggered for accessTO (or PARENT accessTO if shared).

access_granted

term_change_grace_period_started

Piano

Sent when an upgrade was executed, but the newly created subscription for the new term entered a grace period because of a payment failure.
Triggered for accessTO (or PARENT accessTO if shared).

Contents of the webhook

Field

Type

Value

type

string

webhook type: access_granted

version

string

2

typeTitle

string

webhook type title: Access granted

event

string

event:

  • new_purchase

  • payment_verified

  • term_applied_by_publisher

  • payment_verified_by_publisher

  • subscription_imported

  • free_access_granted

  • free_promo_redemption

  • psc_purchase

  • cross_app_access_granted

  • new_registration_conversion

  • new_custom_term_conversion

  • new_site_license_conversion

  • term_change_finished

  • term_change_grace_period_started

eventTitle

string

event title:

  • New purchase: for new_purchase event

  • No payment purchase: for payment_verified event

  • New purchase by publisher: for term_applied_by_publisher event

  • No payment purchase by publisher: for payment_verified_by_publisher event

  • Subscription imported: for subscription_imported event

  • Granted free access: for free_access_granted event

  • Redemption of free promotion: for free_promo_redemption event

  • PSC purchase: for psc_purchase event

  • Cross app access granted: for cross_app_access_granted event

  • User converted with new registration: for new_registration_conversion event

  • User converted custom term: for new_custom_term_conversion event

  • New site license conversion: for new_site_license_conversion event

  • Upgrade finished: for term_change_finished event

  • Upgrade grace period started: for term_change_grace_period_started event

aid

string

application id

expires

long

access expiration date:

  • <access expiration date-time>: for access that has a fixed end date

  • null: for unlimited access

  • all other values are impossible for this webhook type

term_id

string

term id:

  • <term id>: for access granted on purchase of dynamic/any payment/any gift/any external/registration/custom/linked term, or for access granted on import of dynamic/recurring payment subscription, or for granted cross app access

  • <termTO id>: for access to subscriptionTO granted on successful immediate/pending upgrade execution, or for access to subscriptionTO granted on immediate/pending upgrade execution with grace period start

  • null: for access granted on redemption of SEA/ED contract, or for manually/automatically granted free access

uid

string

end-user id

rid

string

resource id

access_id

string

access id

user_email

string

end-user's email address

contract_id

string

contract id:

  • <contract id>: for access granted on redemption of SEA/ED contract

  • null: for access granted on purchase of dynamic/any payment/any gift/any external/registration/custom/linked term, or for access granted on import of dynamic/recurring payment subscription, or for manually/automatically granted free access, or for granted cross app access, or for access to subscriptionTO granted on successful immediate/pending upgrade execution, or for access to subscriptionTO granted on immediate/pending upgrade execution with grace period start

payment_id

string

user payment id:

  • <user payment id>: for access granted on purchase of dynamic/any payment/any gift term with payment, or for access to subscriptionTO granted on successful immediate upgrade execution with payment

  • null: for access that granted on purchase of dynamic/any payment/any gift term without payment, or for access granted on import of dynamic/recurring payment subscription, or for access granted on purchase of any external/registration/custom/linked term, or for access granted on redemption of SEA/ED contract, or for manually/automatically granted free access, or for granted cross app access, or for access to subscriptionTO granted on successful immediate upgrade execution without payment, or for access to subscriptionTO granted on successful pending upgrade execution, or for access to subscriptionTO granted on immediate/pending upgrade execution with grace period start

conversion_id

string

conversion id:

  • <conversion id>: for access granted on purchase of external term (CDS, Apple iTunes, Google/SwG or Newscycle), or for access granted on import of non-external subscription, or for access granted on redemption of SEA/ED contract

  • null: for access granted on purchase of non-external term, or for access to subscriptionTO granted on immediate/pending upgrade execution, or for manually/automatically granted free access, or for granted cross app access

Examples

Example 1. Response to a term_applied_by_publisher event on a payment term
{
  "type": "access_granted",
  "version": 2,
  "typeTitle": "Access granted",
  "event": "term_applied_by_publisher",
  "eventTitle": "New purchase by publisher",
  "aid": "hcxX89Lysu",
  "expires": 1751313599,
  "term_id": "TMZLF8VXAPHX",
  "uid": "a8db5940-e6b0-4f80-a1ca-ff2efeb46e72",
  "rid": "R2YEUGI",
  "access_id": "OXaeX4AK6AfH",
  "user_email": "testUserParent@io.io",
  "contract_id": null,
  "payment_id": "UPOI7Z4OISQ2",
  "conversion_id": null
}
Example 2. Response to a new_purchase event on a dynamic term
{
  "type": "access_granted",
  "version": 2,
  "typeTitle": "Access granted",
  "event": "new_purchase",
  "eventTitle": "New purchase",
  "aid": "cNDPkdkYsu",
  "expires": 1751313599,
  "term_id": "TM1661TNEBIP",
  "uid": "3dfc67fe-9099-4b1a-9500-fc88239e7ccc",
  "rid": "RHVJYOV",
  "access_id": "sAiSWHku14c2",
  "user_email": "testUser@io.io",
  "contract_id": null,
  "payment_id": "UPFM5KXK6RDD",
  "conversion_id": null
}

Note that the value for conversion_id is only being populated for external terms such as CDS, Apple iTunes, Google/SwG or Newscycle.

Access modified

These are all of the events that indicate that an access has been modified:

Type

Event

Triggered by

Notes

access_modified

subscription_activated

Piano

Sent when an access is modified after a subscription with a future start date is activated.

access_modified

subscription_auto_renewed

Piano

Sent when an access is modified after Piano's system successfully auto-renews a user's subscription. In case of a payment failure upon the auto-renewal, the webhook grace_period_extension_on_renewal is sent instead.

access_modified

subscription_manually_renewed

User

Sent when an access is modified after a user manually renews a subscription, or when you manually renew a user's subscription on the user's behalf.

access_modified

grace_period_extension_on_renewal

Piano

Sent when an access is modified after the Piano system grants additional days of access to a user whose subscription Piano is unable to automatically renew. After the grace period is over, we send the subscription_auto_renewed_failure event.

access_modified

subscription_deferred_canceled

You or User

Sent when an access is modified after a dynamic subscription is canceled and it modifies a user's access.

access_modified

subscription_resumed

You or User

Sent when an access is modified after a dynamic subscription is resumed and a user's access is extended.

access_modified

subscription_updated

You or User

Sent when an access is modified after you update the next bill date on a user's subscription or when a user's subscription is cancelled due to disabling their account.

access_modified

subscription_dynamic_unlimited_period_converted

You

Sent when an access is modified after a dynamic subscription's unlimited period is converted to a period of another type. The action is initiated by You, but done asynchronously.

access_modified

access_modified

You or User

Sent when an access is modified after you modify a user's non-subscription-based access. The access associated with the subscription is modified by updating the next bill date which triggers the subscription_updated event. This webhook also fires when a custom term's access is extended.

This webhook is also sent when a user requests an upgrade and their new access takes effect.

access_modified

cross_app_access_modified

Piano

Sent when a cross app access is modified.

access_modified

site_license_renewed

Piano

Sent when an access is modified after a site license is renewed.

Contents of the webhook

Field

Type

Value

type

string

webhook type: access_modified

version

string

2

typeTitle

string

webhook type title: Access modified

event

string

event:

  • subscription_activated

  • subscription_auto_renewed

  • subscription_manually_renewed*

  • grace_period_extension_on_renewal

  • subscription_deferred_canceled

  • subscription_resumed

  • subscription_updated

  • subscription_dynamic_unlimited_period_converted

  • access_modified

  • cross_app_access_modified

  • site_license_renewed

eventTitle

string

event title:

  • Subscription_activated: for subscription_activated event

  • Subscription was automatically renewed: for subscription_auto_renewed event

  • Subscription was manually renewed by user: for subscription_manually_renewed event

  • Grace period was extended: for grace_period_extension_on_renewal event

  • Subscription canceled (deferred cancel): for subscription_deferred_canceled event

  • Subscription resumed: for subscription_resumed event

  • Subscription updated: for subscription_updated event

  • Subscription unlimited period converted: for subscription_dynamic_unlimited_period_converted event

  • Access modified: for access_modified event

  • Cross app access modified: for cross_app_access_modified

  • Site license renewed: for site_license_renewed event

aid

string

application id

expires

long

access expiration date:

  • <access expiration date-time>: for access that has a fixed end date

  • null: for unlimited access

  • all other values are impossible for this webhook type

term_id

string

term id:

  • <term id>: for access modified on activation of dynamic/recurring payment subscription, or for access modified on successful manual/automatic renewal of dynamic/recurring payment/any external subscription, or for access modified on renewal with grace period start for dynamic/recurring payment subscription, or for access modified on deferred cancellation of dynamic subscription, or for access modified on resumption of cancelled dynamic subscription, or for access modified after manual change of next billing date for recurring payment subscription, for access modified after converting an unlimited access period of dynamic term, or for modified cross app access

  • null: for access modified on renewal of subscription associated with redeemed SEA/ED contract

uid

string

end-user id

rid

string

resource id

access_id

string

access id

user_email

string

end-user's email address

contract_id

string

contract id:

  • <contract id>: for access modified on renewal of subscription associated with redeemed SEA/ED contract

  • null: for access modified on activation of dynamic/recurring payment subscription, or for access modified on successful manual/automatic renewal of dynamic/recurring payment/any external subscription, or for access modified on renewal with grace period start for dynamic/recurring payment subscription, or for access modified on deferred cancellation of dynamic subscription, or for access modified on resumption of cancelled dynamic subscription, or for access modified after manual change of next billing date for recurring payment subscription, for access modified after converting an unlimited access period of dynamic term, or for modified cross app access

payment_id

string

user payment id:

  • <user payment id>: for access modified on successful manual/automatic renewal of dynamic/recurring payment subscription with payment

  • null: for access modified on activation of dynamic/recurring payment subscription, for access modified on successful manual/automatic renewal of dynamic/recurring payment subscription without payment, or for access modified on successful renewal of any external subscription, for access modified on renewal of subscription associated with redeemed SEA/ED contract, or for access modified on renewal with grace period start for dynamic/recurring payment subscription, or for access modified on deferred cancellation of dynamic subscription, or for access modified on resumption of cancelled dynamic subscription, or for access modified after manual change of next billing date for recurring payment subscription, for access modified after converting an unlimited access period of dynamic term, or for modified cross app access

conversion_id

string

conversion id:

  • <conversion id>: for access modified on renewal of external subscription (CDS, Apple iTunes, Google/SwG or Newscycle), or for access modified on renewal of subscription associated with redeemed SEA/ED contract

  • null: for access modified on activation of dynamic/recurring payment subscription, for access modified on renewal of non-external subscription, or for access modified on deferred cancellation of dynamic subscription, or for access modified on resumption of cancelled dynamic subscription, or for access modified after manual change of next billing date for recurring payment subscription, for access modified after converting an unlimited access period of dynamic term, for modified cross app access

*When a subscription is manually renewed while in the grace period, the system records the notification in the user’s history, but intentionally skips sending the access_modified webhook. This is because entering the grace period already grants access through the end of the current access period. The manual renewal resolves the overdue payment, and once the subscription exits the grace period, the user’s access remains unchanged and continues until the end of that period.

Examples

Example 1. Response to a subscription_auto_renewed event on a payment term
{
  "type": "access_modified",
  "version": 2,
  "typeTitle": "Access modified",
  "event": "subscription_auto_renewed",
  "eventTitle": "Subscription was automatically renewed",
  "aid": "hcxX89Lysu",
  "expires": 1751313599,
  "term_id": "TMZLF8VXAPHX",
  "uid": "a8db5940-e6b0-4f80-a1ca-ff2efeb46e72",
  "rid": "R2YEUGI",
  "access_id": "OXaeX4AK6AfH",
  "user_email": "testUserParent@io.io",
  "contract_id": null,
  "payment_id": "UPTXUR9N7YM0",
  "conversion_id": null
}
Example 2. Response to a subscription_deferred_canceled event on a dynamic term
{
  "type": "access_modified",
  "version": 2,
  "typeTitle": "Access modified",
  "event": "subscription_manually_renewed",
  "eventTitle": "Subscription was manually renewed by user",
  "aid": "vb45MHjPsu",
  "expires": 1759262399,
  "term_id": "TM0KCBAS5F1M",
  "uid": "3dfc67fe-9099-4b1a-9500-fc88239e7ccc",
  "rid": "RNQUDNX",
  "access_id": "bb4Ne8g5Xswl",
  "user_email": "testUser@io.io",
  "contract_id": null,
  "payment_id": "UPN0R55BAXL5",
  "conversion_id": null
}

Access revoked

These are all of the events that indicate revoked access:

Type

Event

Triggered by

Notes

access_revoked

access_revoked

You

Sent when a user's access is revoked.

access_revoked

subscription_auto_renewed_failure

Piano

Sent when Piano is unable to charge a user's credit card to renew their subscription, and there is no grace period or the grace period has ended.

access_revoked

access_ended

Piano

Sent when Piano determines that non-subscription-based access has ended. The access_ended event only fires when access “naturally” expires, meaning that it wasn't due to any user, publisher, admin, or Piano action. This event is never sent for access that is associated with subscriptions because subscription_auto_renewed_failure and subscription_expired events will be sent instead.

access_revoked

subscription_canceled

User

Sent when a user cancels their subscription or when you cancel a user's subscription on their behalf.

access_revoked

subscription_expired

Piano

Sent when Piano attempts to renew a user's subscription and determines that auto-renew is turned off.

access_revoked

cross_app_access_revoked

Piano

Sent when cross app access has been revoked.

access_revoked

site_license_expired

Piano

Sent when the end user's site license expires.

access_revoked

site_license_canceled

You

Sent when the end user's site license was canceled.

access_revoked

term_change_finished

You, or User, or Piano

Sent upon a successful upgrade execution.
Triggered for accessFROM (or PARENT accessFROM if shared).

access_revoked

term_change_aborted

Piano

Sent when a pending upgrade is suspended.
Triggered for accessFROM (or PARENT accessFROM if shared).

access_revoked

term_change_failure

Piano

Sent in case of failure on a pending upgrade, with no grace in termTO/periodTO.
Triggered for accessFROM (or PARENT accessFROM if shared).

access_revoked

term_change_grace_period_started

Piano

Sent when an upgrade was executed, but the newly created subscription for the new term entered a grace period because of a payment failure.
Triggered for accessFROM (or PARENT accessFROM if shared).

Contents of the webhook

Field

Type

Value

type

string

webhook type: access_revoked

version

string

2

typeTitle

string

webhook type title: Access revoked

event

string

event:

  • access_revoked

  • subscription_auto_renewed_failure

  • access_ended

  • subscription_canceled

  • subscription_expired

  • cross_app_access_revoked

  • site_license_expired

  • site_license_canceled

  • term_change_finished

  • term_change_aborted

  • term_change_failure

  • term_change_grace_period_started

eventTitle

string

event title:

  • Access revoked: for access_revoked event

  • Failure of automatic subscription renewal: for subscription_auto_renewed_failure event

  • Access ended: for access_ended event

  • Subscription canceled (immediate cancel): for subscription_canceled event

  • Subscritption expired: for subscription_expired event

  • Cross app access revoked: for cross_app_access_revoked event

  • Site license expired: for site_license_expired event

  • Site license canceled: for site_license_canceled event

  • Upgrade finished: for term_change_finished event

  • Upgrade aborted: for term_change_aborted event

  • Upgrade failure: for term_change_failure event

  • Upgrade grace period started: for term_change_grace_period_started event

aid

string

application id

expires

long

access expiration date:

  • <access expiration date-time>: for expired access of dynamic/payment/gift subscription, or for free access expired on access end date

  • <date-time when access was revoked on external provider’s end>: for revoked access of external subscription - where the expiration is managed by third-party providers such as Google or Apple

  • -1: for revoked access of dynamic/payment/gift subscription, or for revoked access to SEA/ED contract subscription, or for free access revoked manually

  • all other values are impossible for this webhook type

term_id

string

term id:

  • <term id>: for access revoked on renewal failure of recurring payment/external subscription, for access revoked on internal/external renewal failure of dynamic subscription, for access revoked on renewal grace period end of dynamic/recurring payment subscription, or for access revoked on immediate recurring payment/dynamic/external subscription cancellation, or for access expired on expiration of dynamic subscription after deferred cancellation, or for access expired on expiration of recurring payment subscription with turned off auto-renewal, or for single payment/registration term access expired at access end date, or for any gift/external/linked term access revoked on subscription expiration, or for revoked cross app access

  • <termFROM id>: for access to subscriptionFROM revoked on successful immediate/pending upgrade execution, or for access to subscriptionFROM revoked on immediate/pending upgrade execution with grace period start, or for access to subscriptionFROM revoked on immediate/pending upgrade execution failure, or for access to subscriptionFROM revoked on pending upgrade abortion

  • <termTO id>: for access revoked on upgrade grace period end of dynamic/recurring payment subscriptionTO

  • null: for access to SEA/ED contract revoked by client user/licensee representative, or for access to SEA/ED contract subscription revoked on subscription cancellation by end-user, or for access to SEA/ED contract expired on scheduled period end date, or for free access expired on access end date, or for free access revoked manually

uid

string

end-user id

rid

string

resource id

access_id

string

access id

user_email

string

end-user’s email address

contract_id

string

contract id:

  • <contract id>: for access to SEA/ED contract revoked by client user/licensee representative, or for access to SEA/ED contract subscription revoked on subscription cancellation by end-user, or for access to SEA/ED contract expired on scheduled period end date

  • null: for access revoked on renewal failure of recurring payment/external subscription, for access revoked on internal/external renewal failure of dynamic subscription, for access revoked on renewal grace period end of dynamic/recurring payment subscription, or for access revoked on immediate recurring payment/dynamic/external subscription cancellation, or for access expired on expiration of dynamic subscription after deferred cancellation, or for access expired on expiration of recurring payment subscription with turned off auto-renewal, or for single payment/registration term access expired at access end date, or for any gift/external/linked term access revoked on subscription expiration, or for revoked cross app access, or for access to subscriptionFROM revoked on successful immediate/pending upgrade execution, or for access to subscriptionFROM revoked on immediate/pending upgrade execution with grace period start, or for access to subscriptionFROM revoked on immediate/pending upgrade execution failure, or for access to subscriptionFROM revoked on pending upgrade abortion, or for access revoked on upgrade grace period end of dynamic/recurring payment subscriptionTO, or for free access expired on access end date, or for free access revoked manually

Examples

Example 1. Response to a subscription_canceled event on a payment term
{
  "type": "access_revoked",
  "version": 2,
  "typeTitle": "Access revoked",
  "event": "subscription_canceled",
  "eventTitle": "Subscription canceled (immediate cancel)",
  "aid": "hcxX89Lysu",
  "expires": -1,
  "term_id": "TMZLF8VXAPHX",
  "uid": "a8db5940-e6b0-4f80-a1ca-ff2efeb46e72",
  "rid": "R2YEUGI",
  "access_id": "OXaeX4AK6AfH",
  "user_email": "testUserParent@io.io",
  "contract_id": null
}
Example 2. Response to a subscription_expired event on a dynamic term
{
  "type": "access_revoked",
  "version": 2,
  "typeTitle": "Access revoked",
  "event": "subscription_expired",
  "eventTitle": "Subscription expired",
  "aid": "vb45MHjPsu",
  "expires": 1748603688,
  "term_id": "TM0KCBAS5F1M",
  "uid": "3dfc67fe-9099-4b1a-9500-fc88239e7ccc",
  "rid": "RNQUDNX",
  "access_id": "bb4Ne8g5Xswl",
  "user_email": "testUser@io.io",
  "contract_id": null
}

Shared access granted

These events indicate that a user has received access under a shared subscription.

Type

Event

Triggered by

Notes

shared_access_granted

shared_subscription_child_access_auto_redeemed

Piano

Sent when a child access is automatically redeemed due to the purchase, import, activation, update, upgrade, or grace period of the parent subscription.

shared_access_granted

shared_subscription_child_access_manually_redeemed

User

Sent when a user manually redeems their child access via a invitation link from email or via MA.

Contents of the webhook

Field

Type

Value

type

string

webhook type: shared_access_granted

version

string

2

typeTitle

string

webhook type title: Shared access granted

event

string

event:

  • shared_subscription_child_access_auto_redeemed

  • shared_subscription_child_access_manually_redeemed

eventTitle

string

event title:

  • Child access auto redeemed: for shared_subscription_child_access_auto_redeemed event

  • Child access manually redeemed: for shared_subscription_child_access_manually_redeemed event

aid

string

application id

uid

string

CHILD end-user's id

user_email

string

CHILD end-user’s email address

access_id

string

CHILD access id

expires

long

CHILD access expiration date:

  • <CHILD access expiration date-time>: for CHILD access that has a fixed end date

  • null: for unlimited CHILD access

  • all other values are impossible for this webhook type

term_id

string

term id of PARENT subscription:

  • <term id>: for CHILD access granted automatically on purchase of dynamic/recurring payment term, or for CHILD access granted automatically on import of recurring payment subscription, for CHILD access granted automatically on activation of dynamic/recurring payment subscription, or for CHILD access granted on manual access redemption by CHILD end-user

  • <termTO id>: for temporary CHILD access granted automatically on pending upgrade scheduling, or for CHILD access to subscriptionTO granted automatically on successful immediate/pending upgrade execution, or for temporary CHILD access granted automatically on pending upgrade resumption, or for CHILD access to subscriptionTO granted automatically on immediate/pending upgrade execution with grace period start

  • all other values are impossible for this webhook type

term_type

string

term type of PARENT subscription:

  • DYNAMIC: for CHILD access to dynamic subscription

  • PAYMENT: for CHILD access to recurring payment subscription

  • all other values are impossible for this webhook type

rid

string

resource id

parent_uid

string

PARENT end-user id

parent_subscription_id

string

PARENT subscription id

Examples

Example 1. Response to a shared_subscription_child_access_auto_redeemed event on a payment term
{
  "type": "shared_access_granted",
  "version": 2,
  "typeTitle": "Shared access granted",
  "event": "shared_subscription_child_access_auto_redeemed",
  "eventTitle": "Child access auto redeemed",
  "aid": "PfBGJcdpsu",
  "uid": "472aa39b-12e8-42af-b772-8c998bed77c6",
  "user_email": "testUserChild@io.io",
  "access_id": "PfP7PNuG8PD3",
  "expires": 1753905599,
  "term_id": "TMDW8TL68SRI",
  "term_type": "PAYMENT",
  "rid": "R7U33ER",
  "parent_uid": "53ed042d-1e2c-4063-a2e3-8bec3c15d576",
  "parent_subscription_id": "RC0TCFOY77BZ"
}
Example 2. Response to a shared_subscription_child_access_manually_redeemed event on a dynamic term
{
  "type": "shared_access_granted",
  "version": 2,
  "typeTitle": "Shared access granted",
  "event": "shared_subscription_child_access_manually_redeemed",
  "eventTitle": "Child access manually redeemed",
  "aid": "PfBGJcdpsu",
  "uid": "e4b13fc0-c120-4968-9165-a3ae07592cc3",
  "user_email": "testUserChild@io.io",
  "access_id": "wk7hRfKfAKtr",
  "expires": 1753905599,
  "term_id": "TMUGCTMDIKGX",
  "term_type": "DYNAMIC",
  "rid": "RGCMKA2",
  "parent_uid": "53ed042d-1e2c-4063-a2e3-8bec3c15d576",
  "parent_subscription_id": "RCDAZL03AIST"
}

Shared access modified

These events indicate that a user's child access under a shared subscription has been modified.

Type

Event

Triggered by

Notes

shared_access_modified

subscription_auto_renewed

Piano

Sent for a CHILD access modified when the auto-renewal of its PARENT subscription succeeds on the initial attempt.

shared_access_modified

subscription_manually_renewed

You or User

Sent for a CHILD access modified upon a successful manual renewal of the PARENT subscription.

shared_access_modified

subscription_
grace_period_started

Piano

Sent for a CHILD access modified when a grace period is started upon a failed auto-renewal of the PARENT subscription.

shared_access_modified

subscription_deferred_canceled

You or User

Sent for a CHILD access modified upon a deferred cancellation of the PARENT subscription (the subscription doesn't have a scheduled pending upgrade and is not on the last billing period of its access period).

shared_access_modified

subscription_resumed

You or User

Sent for a CHILD access modified upon a resumption of the PARENT subscription (the subscription doesn't have a scheduled pending upgrade and is not on the last billing period of its access period).

shared_access_modified

subscription_next_bill_date_updated

You

Sent for a CHILD access modified upon an update of the next billing period of the PARENT subscription via the Dashboard or API.

shared_access_modified

subscription_dynamic_unlimited_period_converted

You

Sent for a CHILD access modified upon a conversion of an unlimited access period for a dynamic term when the PARENT subscription is active on this period.

Contents of the webhook

Field

Type

Value

type

string

webhook type: shared_access_modified

version

string

2

typeTitle

string

webhook type title: Shared access modified

event

string

event:

  • subscription_auto_renewed

  • subscription_manually_renewed

  • subscription_grace_period_started

  • subscription_deferred_canceled

  • subscription_resumed

  • subscription_next_bill_date_updated

  • subscription_dynamic_unlimited_period_converted

eventTitle

string

event title:

  • Subscription was automatically renewed: for subscription_auto_renewed event

  • Subscription was manually renewed by user: for subscription_manually_renewed event

  • Subscription renewal grace period started: for subscription_grace_period_started event

  • Subscription canceled (deferred cancel): for subscription_deferred_canceled event

  • Subscription resumed: for subscription_resumed event

  • Subscription next bill date updated: for subscription_next_bill_date_updated event

  • Subscription unlimited period converted: for subscription_dynamic_unlimited_period_converted event

aid

string

application id

uid

string

CHILD end-user id

user_email

string

CHILD end-user’s email address

access_id

string

CHILD access id

expires

long

CHILD access expiration date:

  • <CHILD access expiration date-time>: for CHILD access that has a fixed end date

  • null: for unlimited CHILD access

  • all other values are impossible for this webhook type

term_id

string

term id of PARENT subscription:

  • <term id>: for CHILD access modified on successful manual/automatic renewal of dynamic/recurring payment subscription, or for CHILD access modified on renewal with grace period start for dynamic/recurring payment subscription, or for CHILD access modified on deferred cancellation of dynamic subscription, or for CHILD access modified on resumption of cancelled dynamic subscription, or for CHILD access modified after manual change of next billing date for recurring payment subscription, for CHILD access modified after converting an unlimited access period of dynamic term

  • all other values are impossible for this webhook type

term_type

string

term type of PARENT subscription:

  • DYNAMIC: for CHILD access to dynamic subscription

  • PAYMENT: for CHILD access to recurring payment subscription

  • all other values are impossible for this webhook type

rid

string

resource id

parent_uid

string

PARENT end-user id

parent_subscription_id

string

PARENT subscription id

Examples

Example 1. Response to a subscription_deferred_canceled event on a payment term
{
  "type": "shared_access_modified",
  "version": 2,
  "typeTitle": "Shared access modified",
  "event": "subscription_deferred_canceled",
  "eventTitle": "Subscription canceled (deferred cancel)",
  "aid": "PfBGJcdpsu",
  "uid": "472aa39b-12e8-42af-b772-8c998bed77c6",
  "user_email": "testUserChild@io.io",
  "access_id": "T0Q4I1gZBMHo",
  "expires": 1759607999,
  "term_id": "TMASFSUO3PWV",
  "term_type": "PAYMENT",
  "rid": "R7U33ER",
  "parent_uid": "53ed042d-1e2c-4063-a2e3-8bec3c15d576",
  "parent_subscription_id": "RC0TCFOY77BZ"
}
Example 2. Response to a subscription_resumed event on a dynamic term
{
  "type": "shared_access_modified",
  "version": 2,
  "typeTitle": "Shared access modified",
  "event": "subscription_resumed",
  "eventTitle": "Subscription resumed",
  "aid": "2rsQ4RqFsu",
  "uid": "5ebac7ac-4adc-4d18-9b72-0e8df95bb154",
  "user_email": "testUserChild@io.io",
  "access_id": "T0Q4I1gZBMHo",
  "expires": 1759607999,
  "term_id": "TMPIESUO3PWV",
  "term_type": "DYNAMIC",
  "rid": "RDVZ3X5",
  "parent_uid": "decbe198-27b5-469b-a2db-c62d78490950",
  "parent_subscription_id": "RCFJVD89OVEZ"
}

Shared access revoked

These events indicate that a user's child access under a shared subscription has been revoked.

Type

Event

Triggered by

Notes

shared_access_
revoked

shared_subscription_child_access_revoked

You,
or User,
or Piano

Sent when a parent user removes a child user from the list of shared accounts or when you do it via API or the dashboard on the parent user's behalf.

shared_access_
revoked

shared_subscription_child_left

You or User

Sent when a child user manually revokes their child access or when you do it via API on the child user's behalf.

shared_access_
revoked

subscription_canceled

You or User

Sent when a user cancels their subscription or when you cancel a user's subscription on their behalf. Triggered for CHILD accounts with redeemed access.

shared_access_
revoked

subscription_expired

Piano

Sent when a subscription renewal has failed and there is no grace period configured, or when a subscription has been canceled and will not renew, or when there's no next access period configured in the term for this subscription.

shared_access_
revoked

term_change_finished

You,
or User,
or Piano

Sent when a subscription is successfully upgraded.  Triggered for a CHILD account with redeemed access to the termFROM, when such a CHILD is being removed from the list of shared accounts.

shared_access_
revoked

term_change_aborted

Piano

Sent when a pending upgrade is suspended.

Triggered for a CHILD account with redeemed access to the termFROM, when such a CHILD is being removed from the list of shared accounts.

shared_access_
revoked

term_change_failure

Piano

Sent in case of failure on a pending upgrade, with no grace in termTO/periodTO.

Triggered for a CHILD account with redeemed access to the termFROM, when such a CHILD is being removed from the list of shared accounts.

shared_access_
revoked

term_change_grace_period_started

Piano

Sent when an upgrade was executed, but the newly created subscription for the new term entered a grace period because of the payment failure.

Triggered for a CHILD account with redeemed access to the termFROM, when such a CHILD is being removed from the list of shared accounts.

Contents of the webhook

Field

Type

Value

type

string

webhook type: shared_access_revoked

version

string

2

typeTitle

string

webhook type title: Shared access revoked

event

string

event:

  • shared_subscription_child_access_revoked

  • shared_subscription_child_left

  • subscription_canceled

  • subscription_expired

  • term_change_finished

  • term_change_aborted

  • term_change_failure

  • term_change_grace_period_started

eventTitle

string

event title:

  • Child access revoked: for shared_subscription_child_access_revoked event

  • Child left: for shared_subscription_child_left event

  • Subscription canceled (immediate cancel): for subscription_canceled event

  • Subscription expired: for subscription_expired event

  • Upgrade finished: for term_change_finished event

  • Upgrade aborted: for term_change_aborted event

  • Upgrade failure: for term_change_failure event

  • Upgrade grace period started: for term_change_grace_period_started event

aid

string

application id

uid

string

CHILD end-user id

user_email

string

CHILD end-user’s email address

access_id

string

CHILD access id

expires

long

CHILD access expiration date:

  • <CHILD access expiration date-time>: for expired CHILD access

  • -1: for revoked CHILD access

  • all other values are impossible for this webhook type

term_id

string

term id of PARENT subscription:

  • <term id>: for CHILD access revoked on renewal failure of recurring payment subscription, for CHILD access revoked on internal/external renewal failure of dynamic subscription, for CHILD access revoked on renewal grace period end of dynamic/recurring payment subscription, or for CHILD access revoked on immediate recurring payment/dynamic subscription cancellation, or for CHILD access expired on expiration of dynamic subscription after deferred cancellation, or for CHILD access expired on expiration of recurring payment subscription with turned off auto-renewal

  • <termFROM id>: for CHILD access to subscriptionFROM revoked on successful immediate/pending upgrade execution, or for CHILD access to subscriptionFROM revoked on immediate/pending upgrade execution with grace period start, or for CHILD access to subscriptionFROM revoked on immediate/pending upgrade execution failure, or for CHILD access to subscriptionFROM revoked on pending upgrade abortion

  • <termTO id>: for CHILD access revoked on upgrade grace period end of dynamic/recurring payment subscriptionTO

  • all other values are impossible for this webhook type

term_type

string

term type of PARENT subscription:

  • DYNAMIC: for CHILD access to dynamic subscription

  • PAYMENT: for CHILD access to recurring payment subscription

  • all other values are impossible for this webhook type

rid

string

resource id

parent_uid

string

PARENT end-user id

parent_subscription_id

string

PARENT subscription id

Examples

Example 1. Response to a shared_subscription_child_left event on a payment term
{
  "type": "shared_access_revoked",
  "version": 2,
  "typeTitle": "Shared access revoked",
  "event": "shared_subscription_child_left",
  "eventTitle": "Child left",
  "aid": "nAmj7xEtsu",
  "uid": "7a00fc40-4b9a-474f-80ef-3b2b5dbe7b98",
  "user_email": "testUserChild@io.io",
  "access_id": "dJIalfl3D5ke",
  "expires": -1,
  "term_id": "TM6K8R7QDP5J",
  "term_type": "PAYMENT",
  "rid": "RWMVGQN",
  "parent_uid": "ec8ea432-64b5-44fe-8010-1895f8bc2917",
  "parent_subscription_id": "RCTLDQ6MW4YM"
}
Example 2. Response to a shared_subscription_child_access_revoked event on a dynamic term
{
  "type": "shared_access_revoked",
  "version": 2,
  "typeTitle": "Shared access revoked",
  "event": "shared_subscription_child_access_revoked",
  "eventTitle": "Child access revoked",
  "aid": "nAmj7xEtsu",
  "uid": "110d6f29-a91c-4869-a9a8-d0610ed7358a",
  "user_email": "testUserChild@io.io",
  "access_id": "Nemz4Vs3P2It",
  "expires": -1,
  "term_id": "TMIKFHI0MM3C",
  "term_type": "DYNAMIC",
  "rid": "RONJAEU",
  "parent_uid": "387b2711-285d-4fd9-b101-b750115f4e6e",
  "parent_subscription_id": "RCG3DJ2O6CHO"
}

Vouchers

These events indicate users have engaged with vouchers or gift offers.

Type

Event

Triggered by

Notes

voucher_purchased

voucher_purchase

User

Sent when a user converts on a gift offer and purchases a voucher.

voucher_delivered

voucher_delivery

Piano

Sent when the gift is successfully delivered to the recipient after the voucher has been purchased.

voucher_redeemed

to_giftee_voucher_redeemed

User

Sent when gift recipient redeems their gift and begins their period of access.

access_granted

free_access_granted

Piano

Sent when access to the resource is triggered after the gift is redeemed.

voucher_revoked

voucher_revoked

You

Sent when a gift voucher's access has been revoked.

Examples

Example 1. Response to a voucher_purchased event

{
"version": 2,
 "type": "voucher_purchased",
 "event": "voucher_purchase",
 "aid": "eBGQWilSFK",
 "voucher_id": "VPS4VGpzhavq",
 "term_id": "TMDK47VMOY35",
 "voucher_state": 5,
 "voucher_send_date_timestamp": 1571248201,
 "voucher_recipient_name": "Example Giftee",
 "voucher_recipient_email": "<a class="c-link" href="mailto:giftee@gmail.com" target="_blank" rel="noopener noreferrer">giftee@gmail.com</a>",
 "voucher_message": "here is your gift",
 "voucher_code": "2O0KYE5",
 "voucher_expires_timestamp": 1602870614,
 "voucher_issue_term_conversion_id": "TCJJFBQO4L6D",
 "voucher_redeem_term_conversion_id": "TCFV21GB7122",
 "address_id": "UAV9XL30TSMY"
}
Example 2. Response to a voucher_delivered event

{
 "version": 2,
 "type": "voucher_delivered",
 "event": "voucher_delivery",
 "aid": "eBGQWilSFK",
 "voucher_id": "VPS4VGpzhavq",
 "term_id": "TMDK47VMOY35",
 "voucher_state": 5,
 "voucher_send_date_timestamp": 1571248201,
 "voucher_recipient_name": "Example Giftee",
 "voucher_recipient_email": "<a class="c-link" href="mailto:giftee@gmail.com" target="_blank" rel="noopener noreferrer">giftee@gmail.com</a>",
 "voucher_message": "here is your gift",
 "voucher_code": "2O0KYE5",
 "voucher_expires_timestamp": 1602870614,
 "voucher_issue_term_conversion_id": "TCJJFBQO4L6D",
 "voucher_redeem_term_conversion_id": "TCFV21GB7122",
 "address_id": "UAV9XL30TSMY"
}
Example 3. Response to a voucher_redeemed event


{
 "version": 2,
 "type": "voucher_redeemed",
 "event": "to_giftee_voucher_redeemed",
 "aid": "eBGQWilSFK",
 "voucher_id": "VPS4VGpzhavq",
 "term_id": "TMDK47VMOY35",
 "voucher_state": 5,
 "voucher_send_date_timestamp": 1571248201,
 "voucher_recipient_name": "Example Giftee",
 "voucher_recipient_email": "<a class="c-link" href="mailto:giftee@gmail.com" target="_blank" rel="noopener noreferrer">giftee@gmail.com</a>",
 "voucher_message": "here is your gift",
 "voucher_code": "2O0KYE5",
 "voucher_expires_timestamp": 1602870614,
 "voucher_issue_term_conversion_id": "TCJJFBQO4L6D",
 "voucher_redeem_term_conversion_id": "TCFV21GB7122",
 "address_id": "UAV9XL30TSMY"
}
Example 4. Response to a voucher_revoked event

{
 "version": 2,
 "type": "voucher_revoked",
 "event": "voucher_revoked",
 "aid": "eBGQWilSFK",
 "voucher_id": "VPS4VGpzhavq",
 "term_id": "TMDK47VMOY35",
 "voucher_state": 5,
 "voucher_send_date_timestamp": 1571248201,
 "voucher_recipient_name": "Example Giftee",
 "voucher_recipient_email": "<a class="c-link" href="mailto:giftee@gmail.com" target="_blank" rel="noopener noreferrer">giftee@gmail.com</a>",
 "voucher_message": "here is your gift",
 "voucher_code": "2O0KYE5",
 "voucher_expires_timestamp": 1602870614,
 "voucher_issue_term_conversion_id": "TCJJFBQO4L6D",
 "voucher_redeem_term_conversion_id": "TCFV21GB7122",
 "address_id": "UAV9XL30TSMY"
}

Site license

These are all events that fire in connection with site licenses.

All notifications include the parameters version (2), aid, type, typeTitle, event, and eventTitle.

Type

Event

Triggered by

Notes

licensee_created

licensee_created

You

We send this webhook when a new Site license is created.

licensee_updated

licensee_updated

You

We send this webhook when an existing Site license is updated.

contract_created

 contract_created

You

This webhook is sent when an email domain or specific email address contract is created.

contract_updated

contract_updated

You

This webhook is sent when an email domain or specific email address contract is updated.

contract_deleted

contract_deleted

You

This webhook is sent when an email domain or specific email address contract is deleted.

contract_user_created

contract_user_created

You

We send this webhook when a new user is added to a contract.

contract_redeemed

licensee_contract_redeemed

User

We send this webhook when the end-user redeems a site license contract.

contract_renewed

licensee_contract_auto_renewed

Piano

We send this webhook when the end user's site license contract is renewed.

contract_user_

access_revoked

licensee_contract_subscription_canceled

You

We send this webhook when the end user's site license contract access is revoked.

contract_user_

access_expired

licensee_contract_access_expired

Piano

We send this webhook when the end user's site license contract access expires.

licensee_invite_

to_contract

 licensee_invite_to_contract

 You

We send this webhook when the end-user is invited to a site license contract.

Examples

Example 1. Response to a licensee_created event
{
    "version": 2,
    "type": "licensee_created",
    "typeTitle": "Licensee created",
    "event": "licensee_created",
    "eventTitle": "Licensee created",
    "aid": "XTSRGNiPaH",
    "licensee_id": "LCS1FYAN2WT74"
}
Example 2. Response to a contract_created event
{
    "version": 2,
    "type": "contract_created",
    "typeTitle": "Contract created",
    "event": "contract_created",
    "eventTitle": "Contract created",
    "aid": "XTSRGNiPaH",
    "contract_id": "TMYIODEP48W1"
}
Example 3. Response to a contract_user_created event
{
    "version": 2,
    "type": "contract_user_created",
    "typeTitle": "Contract user created",
    "event": "contract_user_created",
    "eventTitle": "Contract user created",
    "aid": "XTSRGNiPaH",
    "contract_id": "TMPZR0WZV5BN",
    "user_email": "test@example.com"
}
Example 4. Response to a contract_redeemed event
{
    "Version": 2,
    "type": "contract_redeemed",
    "typeTitle": "Contract redeemed",
    "event": "licensee_contract_redeemed",
    "eventTitle": "Contract redeemed",
    "aid": "XTSRGNiPaH",
    "contract_id": "TMPZR0WZV5BN",
    "conversion_id": "TC4IGE500S9T",
    "uid": "PNIWrbGg3qui132",
    "user_email": "test@example.com"
}
Example 5. Response to a contract_user_access_revoked event
{
    "Version": 2,
    "type": "contract_user_access_revoked",
    "typeTitle": "Contract user access revoked",
    "event": "licensee_contract_subscription_canceled",
    "eventTitle": "Contract subscription canceled",
    "aid": "XTSRGNiPaH",
    "contract_id": "TMPZR0WZV5BN",
    "uid": "PNIWrbGg3qui132",
    "user_email": "test@example.com"
}
Example 6. Response to a licensee_invite_to_contract event
{
    "Version": 2,
    "type": "licensee_invite_to_contract",
    "typeTitle": "User invited to contract",
    "Event": "licensee_invite_to_contract",
    "eventTitle": "Users invited to contract",
    "aid": "XTSRGNiPaH",
    "contract_id": "TMPZR0WZV5BN",
    "user_email": "test@example.com"
}

User data

These events indicate user data has been added, updated, or deleted:

Type

Event

Triggered by

Notes

user_created

user_created

You or User

Sent when a user is created through registration or by the publisher dashboard. User creation events include user registration, passwordless registration (single and non-single step), social registration. On your side, events include creating new users via the 'Add new user' button, and bulk creation of users through email or import.

user_updated

user_updated

You or User

Sent when an end user, you, or file import updates the first name, last name, or email fields in the My Account page.

user_updated

piano_id_user_custom_fields_updated

You or User

 Sent when you or the end user updates a custom field. Note that this does not include consent field updates.

user_updated

 piano_id_user_password_updated

User

Sent when the user updates their password through My Account or they reset their password through the email link. Note that a publisher user can trigger the reset password action, but only an end user can complete it.

user_disabled

user_disabled

You or User

Sent when you or the user disable their accounts or their account is disabled via the publisher dashboard.

user_email_confirmed

piano_id_user_email_confirmed

User

Sent when the user confirms their email through double opt-in.

Examples

Example 1. Response to a user_created event

When a user is created, the their identifier (UID) is sent in the webhook body.

{

    "type": "user_created",
    "event": "user_created",
    "uid": "43097265",
    "aid": "87jJKj3jf3",
    "timestamp": "1575621625"
}
Example 2. Response to a user_updatedevent

For updated user information, the actual information input into the user profile is not displayed in the webhook body. For custom field updates, the name of the custom field updates is included in the webhook. The user profile update looks like this:

{

    "type": "user_updated",
    "event": "user_updated",
    "uid": "43097265",
    "aid": "87jJKj3jf3",
    "timestamp": "1575543633"
}

The custom field update looks like this:

{

    "type": "user_updated",
    "event": "piano_id_user_custom_fields_updated",
    "uid": "43097265",
    "aid": "87jJKj3jf3",
    "timestamp":"1575544166",
    "Updated_custom_fields":"date_id,num_id,text_id"
}

User address update

These are all of the events that result in a user address update:

Type

Event

Triggered by

Notes

address_updated

address_updated

You or User

We send this webhook when the end-user updates their delivery address associated with a subscription or a voucher in My Account, or when the delivery address associated with one or several subscriptions or vouchers is updated in publisher dashboard.

user_address_updated

user_address_updated

User

Deprecated. Please use address_updated instead. We send this webhook when end-user updates their delivery address in My Account

Examples

Example 1. Response to an address_updated event

{
    "type": "address_updated",
 "event": "address_updated",
 "aid": "jIwpUvdZM7",
 "uid": "HCT7oB6uSi",
 "address_id": "UAV9XL30TSMY",
 "subscription_id": ["RCOWL8YOHU18","RCOWL8YOHU19","RCOWL8YOHU20"],
 "voucher_id": ["VPS4VGpzhavq","VPS4VGpzhavr"]
}
Example 2. Response to a user_address_updated event. DEPRECATED.

{
    "type": "user_address_updated",
    "event": "user_address_updated",
    "aid": "jIwpUvdZM7",
    "uid": "HCT7oB6uSi",
    "term_id": "TM0B60EUU3UR",
    "subId": "RCOWL8YOHU18",
    "access_id": "48c1ShRnfvb8",
    "psc_subscriber_number": "1"
}

User payment method

The user_payment_method webhook type and events are disabled for all applications at the time of release, and may be enabled as needed by interested client users.

These are all events related to management of user payment methods.

Type

Event

Triggered by

Notes

user_payment-method

user_payment-method_new

User

We send this webhook when a user creates a new payment method.

user_payment-method

user_payment-method_update

User

We send this webhook when a user updates the existing payment method or changes the payment method associated with a subscription.

Example

{
  "version": 2,
  "type": "user_payment_method",
  "event": "(user_payment_method_new|user_payment_method_update)",
  "user_payment_info_id": "PME5WHTVT394",
  "user_subscriptions": ["RC31FDSDA339","RC31FDSDA329"],
  "uid": "43097265",
  "aid": "87jJKj3jf3"
}

Payments

These are payment-related webhooks available in Piano:

Type

Event

Triggered by

Notes

payment_completed

payment_completed

Piano

Sent when the user payment status has been changed to Completed.

payment_failed

payment_failed

Piano

Sent when the user payment fails, is canceled or aborted.

payment_initiated

payment_initiated

Piano

Sent when the user payment has been created in the Initiated status.

payment_pending

payment_pending

Piano

Sent when the user payment status has been changed to Pending.

payment_refund

purchase_refund

You or User

Sent when a full or partial refund has been issued.

Contents of the webhook

Field

Required

Type

Value

type

Required

string

webhook type:

  • payment_completed

  • payment_failed

  • payment_initiated

  • payment_pending

typeTitle

Required

string

webhook type title:

  • Payment completed

  • Payment failed

  • Payment initiated

  • Payment pending

event

Required

string

Webhook event:

  • payment_completed

  • payment_failed

  • payment_initiated

  • payment_pending

eventTitle

Required

string

webhook event title:

  • Payment completed

  • Payment failed

  • Payment initiated

  • Payment pending

triggeredBy

Required

string

The type of payment trigger. Possible values:

  • new_purchase:

    • purchase in the checkout with new payment method

    • purchase in the checkout with a stored payment method

    • purchase in the ATW with new payment method

    • purchase in the ATW with a stored payment method

  • renewal:

    • auto-renewal

    • manual renewal from the checkout

    • manual renewal from the My Account

    • manual renewal from the Publisher dashboard

    • any upgrade from the checkout

    • any upgrade from the My Account

    • any upgrade from the Publisher dashboard

  • early_billing:

    • renewal with early billing

version

Required

number

2

userPaymentId

Required

string

The user-payment ID in Piano.

status

Required

string

The user payment status.

statusValue

Required

string

The user payment status value.

amount

Optional

number

The amount from userPayment that has been actually charged.

userPaymentInfoId

Optional

string

The UPI ID in Piano.

externalPaymentId

Optional

string

The external UPI token.

xternalCustomerId

Optional

string

The external customer Id = payment_method_token (for imports)

aId

Required

string

The Piano application ID where the payment has been initiated.

uId

Required

string

The internal user ID in Piano.

termId

Required

string

The Piano term ID that has been purchased.

resourseId

Required

string

The Piano resource ID that is represented with the purchased term.

subscriptionId

Optional

string

The Piano subscription ID that has been created as a result of the purchase or the payment has been made. The parameter could be specified for MITs only.

accessId

Optional

string

The Piano access ID that has been created. The parameter could be specified for MITs only.

billingPeriodDateFrom

Optional

string

The start date of the subscription billing period that is paid with current user payment. The parameter could be specified for MITs only.

billingPeriodDateTo

Optional

string

The end date of the subscription billing period that is paid with the current user payment. The parameter could be specified for MITs only.

merchantID

Optional

string

Merchant ID from External provider configuration.

paymentMethodKey

Optional

string

The value that represents the payment method that should be displayed in the External payment page after the end-user is redirected from Piano. Could be used in cases when there are multiple external payment method configurations for a single merchant.

sourceInt

Required

number

Internal Piano identifier of the payment method.

Examples

Example 1. Response to a payment_completed event
{
	"type": "payment_completed",
	"typeTitle": "Payment completed",
	"event": "payment_completed",
	"eventTitle": "Payment completed",
	"triggeredBy": "new_purchase",
	"version": 2,
	"userPaymentId": "UP589XOSLJWKHT",
	"status": 0,
	"statusValue": "completed",
	"amount": 10,
	"userPaymentInfoId": "UPIUUI256887",
	"extPaymentId": OOIUYTVJJG,
	"extCustomerId": JGGFTYNJLO,
	"termId": "TMOUVRK06GPG",
    "aid": "AJJHYYFLPPUV",
    "uid": "UFFTDH6507J",
    "resourceId": "RJHHYYTTY",
    "subscriptionId": SUUNNHTRWR66,
    "accessId": "AKKI6F1PPMMJ",
    "billingPeriodDateFrom": 08012024,
    "billingPeriodDateTo": 08312024,
    "subscriptionPeriodCounter": 3,
    "merchantId": null,
    "paymentMethodKey": null,
    "sourceInt": 71
}
Example 2. Response to a payment_failed event
{
	"type": "payment_failed",
	"typeTitle": "Payment failed",
	"event": "payment_failed",
	"eventTitle": "Payment failed",
	"triggeredBy": "new_purchase",
	"version": 2,
	"userPaymentId": "UP589XOSLJWKHT",
	"status": 4,
	"statusValue": "canceled",
	"amount": 10,
	"userPaymentInfoId": "UPIUUU251557866",
	"extPaymentId": "UYTRGHJNK",
	"extCustomerId": "IUYRGHJHJN",
	"termId": "TMOUVRK06GPG",
    "aid": "AJJHYYFLPPUV",
    "uid": "UFFTDH6507J",
    "resourseId": "RJHHYYTTY",
    "subscriptionId": SUUNNHTRWR66,
    "accessId": "AKKI6F1PPMMJ",
    "billingPeriodDateFrom": 08012024,
    "billingPeriodDateTo": 08312024,
    "errorCode": "",
    "errorMessage": "",
    "merchantId": null,
    "paymentMethodKey": null,
    "sourceInt": 71
}
Example 3. Response to a payment_initiated event
{
	"type": "payment_initiated",
	"typeTitle": "Payment initiated",
	"event": "payment_initiated",
	"eventTitle": "Payment initiated",
	"triggeredBy": "new_purchase",
	"version": 2,
	"userPaymentId": "UP589XOSLJWKHT",
	"status": 7,
	"statusValue": "initiated",
	"amount": 10,
	"userPaymentInfoId": null,
	"extPaymentId": "HGGHUHLIJ",
	"extCustomerId": "YREWBJKLL",
	"termId": "TMOUVRK06GPG",
    "aid": "AJJHYYFLPPUV",
    "uid": "UFFTDH6507J",
    "resourseId": "RJHHYYTTY",
    "subscriptionId": null,
    "accessId": null,
    "billingPeriodDateFrom": null,
    "billingPeriodDateTo": null,
    "merchantID":"gjghhidl",
    "paymentMethodKey": "card",
    "sourceInt": 71
}
Example 4. Response to a payment_pending event
{
	"type": "payment_pending",
	"typeTitle": "Payment pending",
	"event": "payment_pending",
	"eventTitle": "Payment pending",
	"triggeredBy": "new_purchase",
	"version": 2,
	"userPaymentId": "UP589XOSLJWKHT",
	"status": 5,
	"statusValue": "pending",
	"amount": 10,
	"userpaymentInfoID": "UPIIIII5135",
	"extPaymentId": "UYTRTYYBBHY", 
	"extCustomerId": "OIUTRYYNJGF",
	"termId": "TMOUVRK06GPG",
    "aid": "AJJHYYFLPPUV",
    "uid": "UFFTDH6507J",
    "resourseId": "RJHHYYTTY",
    "subscriptionId": SUUNNHTRWR66,
    "accessId": "AKKI6F1PPMMJ",
    "billingPeriodDateFrom": 08012024,
    "billingPeriodDateTo": 08312024,
    "subscriptionPeriodCounter": 3,
    "merchantId": null,
    "paymentMethodKey": null,
    "sourceInt": 71
}
Example 5. Response to a payment_refund event
{
  "type": "payment_refund",
  "version": 2,
  "typeTitle": "Payment refund",
  "event": "purchase_refund",
  "eventTitle": "Payment refunded",
  "aid": "<AID>",
  "uid": "PNIVOlt0Tqk1ujg",
  "payment_id": "UPYKHS7YT66S",
  "amount": 10,
  "subscription_id": "RCJ6IIP4V658",
  "access_id": "oN0vFhcAcdoG"
}

Auto-renew in My Account (deprecated)

This event type is completely deprecated. Please use subscription_updated instead.

Type

Event

Triggered by

Notes

subscription_auto_renew_changed

subscription_auto_renew_changed_by_end_user

User

We send this webhook when the end-user interacts with the Auto-renew toggle in My Account.

Deprecated. Instead, please use the subscription_auto_renew_disabled and subscription_auto_renew_enabled events of the subscription_updated webhook type.

Example

{
    "version": 2,
    "type": "subscription_auto_renew_changed",
    "event": "subscription_auto_renew_changed_by_end_user",
    "aid": "vd2rNmtWqy",
    "uid": "mQrUXVrjyR",
    "subscription_id": "RCA2VW9I8S9P",
    "term_id": "TML7FFHCWB76",
    "auto_renew": "enabled"
}

Shared subscription (deprecated)

This event type is completely deprecated. Please use the shared_access_granted, shared_access_revoked, or shared_access_modified webhook type instead. You can also obtain the child accesses of a shared subscription using the UserSubscriptionAccount object, which is available in the shared_accounts field of the subscription_updated, subscription_renewal and subscription_ended webhook types.

Type

Event

Triggered by

Notes

shared_subscription_
child

shared_subscription_child

User

Sent when a child user redeems their shared subscription access via My Account.

Deprecated. Instead, please use the shared_subscription_child_access_auto_redeemed and shared_subscription_child_access_manually_redeemed events of the shared_access_granted webhook type.

Example

{
    "version": 2,
    "type": "shared_subscription_child",
    "typeTitle": "Shared subscription child access granted",
    "event": "shared_subscription_child",
    "eventTitle": "Shared subscription child",
    "aid": "XTSRGNiPaH",
    "expires": -1,
    "email": "demo@piano.io",
    "access_id": "aR3eXhufAeGN",
    "term_id": "TMS6NTTUXICY",
    "rid": "RD4NTHK",
    "uid": "PNIDDCJAEquotvw",
    "parent_uid": "PNIio9tntquots0",
    "parent_subscription_id": "RCHUXPZQNZWK"
}

Last updated: