# Upzelo

The complete reference for Upzelo.

## Where do I start?

**Looking to integrate Upzelo with your web app?**&#x20;

Head to our comprehensive guide: [Installing Upzelo](/developer-guide/installing-upzelo)

**Looking for information on how the platform works and its features?**&#x20;

Check out our [support centre](https://support.upzelo.com).

## Connecting your payment provider

Upzelo integrates with a wide variety of payment providers to make life easier when updating subscriptions during cancellation flows, things we take care of include **pausing subscriptions**, **changing subscription plans**, **applying discounts,** and **cancelling subscriptions either immediately, or at the end of the billing period.** Use the links below to learn about what actions we can do for you with our payment provider guides:

* [Stripe](/integrations/payment-providers/stripe)
* [Recurly](/integrations/payment-providers/recurly)
* [Chargebee](/integrations/payment-providers/chargebee)
* [Recharge](/integrations/payment-providers/recharge)
* [Woocommerce](/integrations/payment-providers/woocommerce)
* [QPilot](/integrations/payment-providers/qpilot)
* [API](/integrations/payment-providers/api)


# Installing Upzelo

3 Steps to get started quickly.

## 1. Insert the Upzelo JS Snippet

The following code will add the Upzelo client-side script and make itself available in the global JS namespace as `window.upzelo`. Place the following snippet into your `<head>` element.

```html
<script
  id="upzpdl"
  src="https://assets.upzelo.com/upzelo.min.js"
  appId="Upzelo App ID"
></script>
```

{% hint style="info" %}
You can find your App ID [here](https://upzelo.com/app/developer/api-keys)
{% endhint %}

## 2. Server-side authentication

{% hint style="warning" %}
This is only required if you wish for Upzelo to take action on your behalf with your payment provider.
{% endhint %}

Server-side authentication is in place to make sure that any requests Upzelo makes to your payment provider on your behalf are authorised and legitimate. This is achieved by you generating an HMAC hash (SHA256 algorithm) with the `customerId` and your `retentionAPI` key.

{% hint style="info" %}
You can find your retentionAPI key [here](https://upzelo.com/app/developer/api-keys)
{% endhint %}

When Upzelo makes a request, it will compare the HMAC hash sent with one that is generated on our servers to ensure that the request is legitimate. Below are some examples of how this hash can be generated in different backend languages.

{% tabs %}
{% tab title="PHP" %}

```php
<?php

declare(strict_types=1);

$retentionApiKey = 'upz_1234'; // Replace with retentionApi key.
$customerId = 'cus_1234'; // Replace with a real customer ID

echo hash_hmac('sha256', $customerId, $retentionApiKey);
// bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
)

func main() {
	// Set the retentionApi Key
	retentionApiKey := "upz_1234"
	// Set the customerId
	customerId := "cus_1234"

	// Generate an HMAC hash.
	hash := hmac.New(sha256.New, []byte(retentionApiKey))
	hash.Write([]byte(customerId))
	hmac := hex.EncodeToString(hash.Sum(nil))

	fmt.Println(hmac)
	// bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8
}
```

{% endtab %}

{% tab title="Python" %}

```python
import hmac
import hashlib

retention_api_key = "upz_1234"
customer_id = "cus_1234"
hmac_hash = hmac.new(
    retention_api_key.encode(),
    customer_id.encode(),
    digestmod=hashlib.sha256
).hexdigest()

print("{}".format(hmac_hash))
# bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'openssl'

retentionApiKey = "upz_1234"
customerId = "cus_1234"

hmacHash = OpenSSL::HMAC.hexdigest(
    OpenSSL::Digest.new('sha256'),
    retentionApiKey,
    customerId
)

print hmacHash
# bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8
```

{% endtab %}

{% tab title="Node" %}

```javascript
const crypto = require("crypto");

const retentionApiKey = 'upz_1234';
const customerId = 'cus_1234';

const hmacHash = crypto.createHmac(
    'sha256',
    retentionApiKey
).update(customerId).digest('hex');

console.log(hmacHash);
// bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8
```

{% endtab %}
{% endtabs %}

## 3. Link your cancel button

Once you have generated an HMAC hash and passed it along to your front end, you can initialise Upzelo and define how you'd like it to be displayed. If you are opting to not have Upzelo take action on your behalf, you may omit the `hash` and `type` parameters.

One typical way of implementing Upzelo would be to attach an event listener to a button.

```javascript
const cancelButton = document.getElementById('cancel-button');

cancelButton.addEventListener('click', () => {
    // Upzelo Config object.
    const config = {
        // The customer's ID from the subscription platform
        customerId: 'cus_1234',
        // The customer's subscription ID from the subscription platform
        subscriptionId: 'sub_1234',
        // The HMAC hash generated in step 2
        hash: 'bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8',
        // The type of flow to serve
        type: 'full', 
        // The mode that we are working with.
        mode: 'live',
    };
    window.upzelo.open(config);
});
```


# Advanced configuration

## Initialising Upzelo

There are a couple of ways of using Upzelo, you can opt to not manually set up click event listeners as Upzelo will do this by default on either a `button` or `a` with the ID of `cancel`. If opting to use this method (not recommended) You will need to add a second script tag to initialize Upzelo.

```javascript
// Upzelo config object
const config = {
    customerId: 'cus_1234',
    subscriptionId: 'sub_1234',
};

window.upzelo.init(config);
```

By doing this, Upzelo will be triggered and display the Flow that has been assigned to the customer.

## Usage with SPA

Integrating Upzelo with your SPA (single-page application) is simple.

Include the script tag from the installation guide in your main template file, then inside your components, use the `window.upzelo.open` function with an Upzelo Configuration Object to launch Upzelo.

## Content Security Policy

If you're running a CSP inside your application, then you'll need to allow Upzelo customer flows to serve images, fonts, and scripts. You'll also need to allow connections back to our servers. Please apply the following directives to your configuration:

* `image-src` [`assets.upzelo.com`](http://assets.upzelo.com/)
* `font-src` [`assets.upzelo.com`](http://assets.upzelo.com/)
* `script-src` [`assets.upzelo.com`](http://assets.upzelo.com/)
* `connect-src` [`upzelo.com`](http://upzelo.com/) [`events.upzelo.io`](http://events.upzelo.io/)

Optionally, you may decide to add [`assets.upzelo.com`](http://assets.upzelo.com/) to a `default-src`, to cover the 3 types in one.


# Upzelo Configuration Object

Parameters available for configuring Upzelo

Upzelo requires a configuration object to be passed into it to initialise.&#x20;

It can be passed into `window.upzelo.init` and/or `window.upzelo.open`.

{% hint style="info" %}
Parameters in <mark style="color:red;">red</mark> are required. <mark style="color:yellow;">Yellow</mark> is required conditionally.
{% endhint %}

## Configuration Parameters

<details>

<summary><mark style="color:red;">customerId</mark></summary>

**Type**: `String`.

The payment provider ID for the currently logged-in user.

```javascript
customerId: 'cus_1234',
```

</details>

<details>

<summary><mark style="color:red;">subscriptionId</mark></summary>

**Type**: `String`

The payment provider ID of the subscription that is to be modified or actioned against.

```javascript
subscriptionId: 'sub_1234',
```

</details>

<details>

<summary><mark style="color:yellow;">hash</mark></summary>

**Type**: `String`

**Required**: If `mode` = `full`

**Usage**: This is for providing the server-side hash

```javascript
hash: 'bd9d2eca979333103b3d93a80e8efcbd0f8421813fdb9feefffde2206b4115e8',
```

</details>

<details>

<summary>addressId (Recharge Only)</summary>

**Type**: `String`

**Required**: No

**Usage**: **This is only used for Recharge**. This is used to be able to apply offers or cancel all subscriptions under a single address.

```javascript
addressId: '234897sdjknf',
```

</details>

<details>

<summary>mode</summary>

**Type**: `String`

**Options**: `live`, `test`

**Default**: `live`

**Usage**: Test mode will utilise the data available while using Upzelo's test mode. This means that it will use Flows, Audiences, and payment provider data that has been imported using your test key.

```javascript
mode: 'test',
```

</details>

<details>

<summary>type</summary>

**Type**: `String`

**Options**: `full`, `minimal`

**Default**: `full` if `hash` supplied, otherwise `minimal`

**Usage**: This determines if you want Upzelo to action things on your behalf with your payment provider. If set to minimal, offboarding requests will appear in the Requests section of the dashboard for you to action yourself.

```javascript
type: 'minimal',
```

</details>

<details>

<summary>selector</summary>

**Type**: `String`

**Default**: `button#cancel, a#cancel`

**Usage**: A CSS selector to select which elements on the page should launch Upzelo when clicked.

```javascript
selector: 'button#cancelButton, a.endSubscription
```

</details>

<details>

<summary>provider</summary>

Type: String

Usage: Only set this if you have been advised by Upzelo support to do so.

```javascript
provider: 'stripe',
```

</details>

## Callbacks

There are some available callbacks that you can use to further extend the functionality of Upzelo. They run alongside what Upzelo does and do not replace that functionality, therefore they are optional.

{% hint style="info" %}
Where a callback has the `responses` argument, it will be an array of Actions that the user saw (not all of the actions in the Flow), and whether an Action was accepted or not.

You should always check if it is defined before using it as there are a small number of cases where it might not be.
{% endhint %}

<details>

<summary>onCancel</summary>

**Type**: `Function`

**Default**: `null`

**Arguments**: `{ customerId, subscriptionId, responses }`

**Usage**: A function that runs at the end of a flow when the customer confirms that they wish to cancel.

```
onCancel: ({ customerId, subscriptionId, responses }) => {
    window.location.replace(`https://www.example.com/goodbye?customer=${customerId}`);
}
```

</details>

<details>

<summary>onSave</summary>

**Type**: `Function`

**Default**: `null`

**Arguments**: `{ customerId, subscriptionId, responses, couponId, offerType, externalCouponId, planId, externalPlanId, offerDuration, offerDurationType }`

Usage: A function that runs when a customer accepts an offer.

You can use `offerType` to change how you respond based on the offer type. Possible values are:

* `discount`
* `pause`
* `trial_extension`
* `free_period`
* `plan_change`

```javascript
onSave: ({ customerId, offerType }) => {
    console.log(customerId, offerType);
    alert("Thanks for staying with us. Your account has been updated");
},
```

</details>

<details>

<summary>onClose</summary>

**Type**: `Function`

**Default**: `null`

**Arguments**: `{ customerId }`

**Usage**: A function that runs when the user closes the modal via the `X` button, clicking outside of it, or pressing the `esc` key.

```
onClose: ({ customerId }) => {
    apiCall.logAbandonedSession(customerId);
},
```

</details>

<details>

<summary>onError</summary>

**Type**: `Function`

**Default**: `null`

**Arguments**: `{ customerId, error }`

**Usage**: If Upzelo throws an error message to the user, it is available through this callback

```javascript
onError: ({ error }) => {
    console.log(error);
},
```

</details>


# Test Mode

An environment for you to test the product without affecting real data

By default, Upzelo will connect in live mode. It is highly recommended that you first set up your account using test mode so that you can fully explore the system and integrate it into your dev/staging environment so as to not affect any live data unintentionally.

Test mode is completely isolated from live mode so there is no way that any operations can affect live data. It is recommended that you add your test mode API keys from your payment provider to Upzelo test mode. Some payment providers, unfortunately, do not offer a test mode, in these cases, it is best to use a separate account for testing.

{% hint style="info" %}
Test mode can be turned on from the sub-menu activated by clicking the cog icon at the bottom left of the Upzelo dashboard.
{% endhint %}

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2F00lhBdIrQOQNun5P87o6%2Fimage.png?alt=media&amp;token=2f31296c-b575-4ff0-a891-2d2c9c58ae6a" alt="Submenu with test mode toggle "><figcaption><p>Sub menu with test mode toggle</p></figcaption></figure>


# Customer ID and Subscription ID

Upzelo connects to your payment provider to take action on your behalf. Your customer Flows are completely configurable and can have different outputs such as:

* Pausing subscriptions
* Applying discounts
* Cancelling subscriptions
* Changing subscription plans

When initializing Upzelo, it's required that you send both a `customerId` and `subscriptionId`. The requirements exist because customers can have multiple subscriptions and we want you to have precise control over what we are taking action on.

{% hint style="info" %}
If you support multiple subscriptions, you can add event handlers to individual buttons for each subscription with the `subscriptionId` set in the [Upzelo configuration object](/developer-guide/advanced-configuration/upzelo-configuration-object)
{% endhint %}

Even though the system could function correctly using just a `subscriptionId`, we require the `customerId` too so we can verify that the subscription that is being actioned does belong to the customer.

{% hint style="danger" %}
In the event that a `subscriptionId` isn't passed into Upzelo, we will pick the most recent non-cancelled subscription to action. This is determined using the subscription created date.
{% endhint %}


# Processing Behaviour

Change how Upzelo works for you

You can customise the way that Upzelo works for your platform using the [Settings](https://upzelo.com/app/settings/upzelo) area.

## Automatic Processing

By default, this option is turned on. This means that when a customer completes a flow, Upzelo will automatically process the output of the customer flow.

For example, if a customer accepts an offer of 10% off for a month, Upzelo will apply that coupon to their subscription via our payment provider integrations.

However, this option can be turned off. By turning this option off, Upzelo will create [Requests](https://upzelo.com/app/requests) for you to manually action.

## Cancellation / Save Behaviour

The default behaviour is the only action cancellations or save events on the subscription ID that is provided.

For example: configuring Upzelo with a `subscriptionId` means that only that subscription will be affected.

However, this functionality can be changed to suit your needs. There is an alternative mode in which we will action all of the subscriptions that belong to a `customerId` or `addressId`

{% hint style="info" %}
`addressId` is only available for Recharge customers.
{% endhint %}

For example: configuring Upzelo with a `customerId` and `subscriptionId`, Upzelo will use the `subscriptionId` to determine which flow to present to the customer, but will action the outcome of the flow on ALL subscriptions that belong to that `customerId`


# Examples

A few examples on ways you might set up Upzelo

{% hint style="warning" %}
All examples on this page use the same Upzelo app ID, customerId, subscriptionId, and hash.
{% endhint %}

<details>

<summary>Single Cancellation Button</summary>

This example follows the example on the [Installing Upzelo](/developer-guide/installing-upzelo) page, it assumes that you use PHP as a back-end language.

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Single cancellation example</title>
        
        <script
            id="upzpdl"
            src="https://assets.upzelo.com/upzelo.min.js"
            appId="upz_1234"
        ></script>
    </head>
    <body>
        <main class="container">
            <h1>Cancel your subscription</h1>
            <p>To cancel your subscription, please click the button below.</p>
            <button
                id="cancel-subscription-button"
                class="btn btn-primary"
            >
                Cancel Subscription
            </button>
        </main>
        
        <script type="text/javascript">
            var button = document.getElementById('cancel-subscription-button');
            
            var config = {
                customerId: 'cus_1234',
                subscriptionId: 'sub_1234',
                mode: 'live',
                type: 'full',
                hash: '<?php echo hash_hmac('sha256', 'cus_1234', $retentionApiKey) ?>',
            };
            
            button.addEventListener('click', () => {
                window.upzelo.open(config);
            });
        </script>
    </body>
</html>
```

</details>

<details>

<summary>Single Cancellation Button (using init method)</summary>

This example is similar to the one above but doesn't use any custom event listeners to trigger Upzelo

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Single cancellation example</title>
        
        <script
            id="upzpdl"
            src="https://assets.upzelo.com/upzelo.min.js"
            appId="upz_1234"
        ></script>
    </head>
    <body>
        <main class="container">
            <h1>Cancel your subscription</h1>
            <p>To cancel your subscription, please click the button below.</p>
            <button
                id="cancel-subscription-button"
                class="btn btn-primary"
            >
                Cancel Subscription
            </button>
        </main>
        
        <script type="text/javascript">
            var config = {
                selector: '#cancel-subscription-button',
                customerId: 'cus_1234',
                subscriptionId: 'sub_1234',
                mode: 'live',
                type: 'full',
                hash: '<?php echo hash_hmac('sha256', 'cus_1234', $retentionApiKey) ?>',
            };
            
            window.upzelo.init(config);
        </script>
    </body>
</html>
```

</details>

<details>

<summary>Multiple Cancellation Buttons</summary>

This is an example of how to implement Upzelo with multiple subscriptions

```
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Single cancellation example</title>
        
        <script
            id="upzpdl"
            src="https://assets.upzelo.com/upzelo.min.js"
            appId="upz_1234"
        ></script>
    </head>
    <body>
        <main class="container">
            <h1>Subscription management</h1>
            <h2>Pro plan</h2>
            <button
                id="cancel-pro-button"
                class="btn btn-primary"
            >
                Cancel Subscription
            </button>

            <h2>Secondary Plan</h2>
            <button
                id="cancel-secondary-button"
                class="btn btn-primary"
            >
                Cancel Subscription
            </button>
        </main>
        
        <script type="text/javascript">
            var proButton = document.getElementById('cancel-pro-button');
            var secondaryButton = document.getElementById('cancel-secondary-button');
            
            var proConfig = {
                customerId: 'cus_1234',
                subscriptionId: 'sub_1234',
                mode: 'live',
                type: 'full',
                hash: '<?php echo hash_hmac('sha256', 'cus_1234', $retentionApiKey) ?>',
            };
            
            var secondaryConfig = {
                customerId: 'cus_1234',
                subscriptionId: 'sub_1235',
                mode: 'live',
                type: 'full',
                hash: '<?php echo hash_hmac('sha256', 'cus_1234', $retentionApiKey) ?>',
            };
            
            proButton.addEventListener('click', () => {
                window.upzelo.open(proConfig);
            });
            
            secondaryButton.addEventListener('click', () => {
                window.upzelo.open(secondaryConfig);
            });
        </script>
    </body>
</html>
```

</details>

<details>

<summary>Non Actioning Cancellation Button</summary>

This is an example of how to implement Upzelo in a way that will create `Requests` that will need to be manually actioned by you.

```
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Single cancellation example</title>
        
        <script
            id="upzpdl"
            src="https://assets.upzelo.com/upzelo.min.js"
            appId="upz_1234"
        ></script>
    </head>
    <body>
        <main class="container">
            <h1>Cancel your subscription</h1>
            <p>To cancel your subscription, please click the button below.</p>
            <button
                id="cancel-subscription-button"
                class="btn btn-primary"
            >
                Cancel Subscription
            </button>
        </main>
        
        <script type="text/javascript">
            var button = document.getElementById('cancel-subscription-button');
            
            var config = {
                customerId: 'cus_1234',
                subscriptionId: 'sub_1234',
                mode: 'live',
                type: 'minimal',
            };
            
            button.addEventListener('click', () => {
                window.upzelo.open(config);
            });
        </script>
    </body>
</html>
```

</details>


# Payment Providers

Upzelo connects with many different payment providers, below is a list of features available for each one.

The tables below will be updated as new features are added.

## Flow Actions

<table><thead><tr><th width="224">Feature</th><th width="84" data-type="checkbox">Stripe</th><th width="90" data-type="checkbox">Recurly</th><th width="119" data-type="checkbox">Chargebee</th><th data-type="checkbox">Recharge</th><th data-type="checkbox">Woocommerce</th><th data-type="checkbox">QPilot</th><th data-type="checkbox">API</th></tr></thead><tbody><tr><td>Subscription Discounts</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Subscription Pausing</td><td>true</td><td>true</td><td>true</td><td>true</td><td>false</td><td>true</td><td>true</td></tr><tr><td>Plan Changing</td><td>true</td><td>true</td><td>false</td><td>false</td><td>false</td><td>false</td><td>true</td></tr><tr><td>Deflections</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Trial Extension</td><td>true</td><td>false</td><td>false</td><td>false</td><td>false</td><td>false</td><td>false</td></tr></tbody></table>

## Audience Segmentation

<table><thead><tr><th width="221">Attribute</th><th data-type="checkbox">Stripe</th><th data-type="checkbox">Recurly</th><th data-type="checkbox">Chargebee</th><th data-type="checkbox">Recharge</th><th data-type="checkbox">Woocommerce</th><th data-type="checkbox">QPilot</th><th data-type="checkbox">API</th></tr></thead><tbody><tr><td>Subscription Status</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Subscription Plan</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Billing Interval</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Subscription Age</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Customer Location</td><td>true</td><td>false</td><td>false</td><td>false</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Subscription Metadata</td><td>true</td><td>false</td><td>false</td><td>false</td><td>false</td><td>false</td><td>true</td></tr><tr><td>Active Coupon</td><td>true</td><td>false</td><td>false</td><td>false</td><td>false</td><td>false</td><td>false</td></tr></tbody></table>


# Stripe

Integrate Stripe with Upzelo

## How to connect Stripe and Upzelo

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FaSRF5521GmR1r8HBig2u%2Fimage.png?alt=media&amp;token=92028d23-f58a-42d7-9bae-d8487ecf555e" alt=""><figcaption></figcaption></figure>

Start by clicking the `Connect` button underneath the Stripe card. The card will then transform into a form with fields for you to enter your Live mode and Test mode Secret/Restricted keys.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2F8tMYQVL27LU2Ijv5BA5j%2Fimage.png?alt=media&amp;token=ec2a079d-d4dc-4aa0-87a8-ca201705567a" alt=""><figcaption></figcaption></figure>

Follow the instructions on the form and confirm your keys work correctly by pressing `Check` before pressing `Save`.

After pressing `Save`, we will check that you have set up the key with the [correct permissions](#api-key-permissions). Once that check is complete, your data will begin to be imported into Upzelo.

## How is Stripe used with Upzelo?

### 1. Audience Segmentation

Upzelo imports data from your Stripe account so that it can be used to create audiences. This allows you to create Flows that can be tailored specifically to a segment of your customer base. This means that a new sign-up can receive a Flow different from a customer that you consider to be valued.

{% hint style="info" %}
Upzelo imports `Customers`, `Subscriptions`, `Coupons`, `Products` and `Prices` from Stripe.
{% endhint %}

**Segmentation Attributes**:

* Subscription Age
* Plan
* Billing Interval
* Subscription Metadata
* Subscription Status
* Customer Location
* Active Coupon

### 2.  Creating Discounts

The Actions section of Upzelo will create coupons inside of your Stripe account which can then be used inside of Flows.

{% hint style="warning" %}
Actions created in test mode are only available for test mode flows.
{% endhint %}

### 3. Updating Customer Subscriptions

When a customer is presented with a Flow, Upzelo takes care of all of the billing updates for you. Some of the Actions that you create are billing related and we will go through those in a bit more detail below.

### 4. Creating Webhooks

Upzelo automatically creates webhooks so that it is always up to date with your customer's subscriptions.

## How Upzelo works with Stripe

### 1. Subscription Pausing

Upzelo uses Stripe's built-in pause feature. How this works, is we update the subscriptions `pause_collection[behavior]` and set it to `mark_uncollectible`. We also set `pause_collection[resumes_at]` to now plus the time period specified in your Action (e.g. 2 months).

{% hint style="info" %}
We follow the best practices set out in the [Stripe documentation](https://stripe.com/docs/billing/subscriptions/pause)
{% endhint %}

### 2. Applying Discounts

You can create different types of discounts in the Actions section. When a customer accepts a discount (money off, percentage, or even a "free period"), we will apply the coupon to the subscription ID that has been provided.

### 3. Changing Plans

When a customer accepts an Action that is for changing Plans, we follow the best practices as set out in the Stripe documentation. Switching subscription plans is configurable in that you can choose if there should be prorations for the time used on their original plan.

### 4. Cancelling Subscriptions

Upzelo handles cancelling subscriptions for you. The behaviour of this can be configured so that the subscription either ends immediately or at the end of the current period. This is configurable on each Flow that you offer.

### 5. Extending Trials

Upzelo can also extend trials for you, this is achieved by updating the `trial_end` parameter on the subscription.

## API Key Permissions

When creating an API key on Stripe, certain permissions are required for Upzelo to function correctly.

| Scope                         | Permission |
| ----------------------------- | ---------- |
| Core -> Charges               | Read       |
| Core -> Customers             | Write      |
| Core -> Events                | Read       |
| Core -> Products              | Read       |
| All Billing Resources         | Write      |
| Webhooks -> Webhook Endpoints | Write      |


# Recurly

Integrate Recurly with Upzelo

## How to connect Recurly and Upzelo

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FaSRF5521GmR1r8HBig2u%2Fimage.png?alt=media&amp;token=92028d23-f58a-42d7-9bae-d8487ecf555e" alt=""><figcaption></figcaption></figure>

Start by clicking the `Connect` button underneath the Recurly card. The card will then transform into a form with fields for you to enter your Live mode and Test mode API keys.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FFw41AZsDgHWjYtWGAXtE%2Fimage.png?alt=media&amp;token=bc99f627-7843-44ce-8211-f25e71d9cb6c" alt=""><figcaption></figcaption></figure>

Follow the instructions on the form and confirm your keys work correctly by pressing `Check` before pressing `Save`.

After pressing `Save`, we will check that you have set up the key with the correct permissions. Once that check is complete, your data will begin to be imported into Upzelo.

## How is Recurly used with Upzelo?

### 1. Audience Segmentation

Upzelo imports data from your Recurly account so that it can be used to create audiences. This allows you to create Flows that can be tailored specifically to a segment of your customer base. This means that a new sign-up can receive a Flow different from a customer that you consider to be valued.

{% hint style="info" %}
Upzelo imports `Customers`, `Subscriptions`, `Coupons`, `Products` and `Prices` from Recurly.
{% endhint %}

**Segmentation Attributes**:

* Subscription Age
* Plan
* Billing Interval
* Subscription Status

### 2.  Creating Discounts

The Actions section of Upzelo will create coupons inside of your Recurly account which can then be used inside of Flows.

{% hint style="warning" %}
Actions created in test mode are only available for test mode flows.
{% endhint %}

### 3. Updating Customer Subscriptions

When a customer is presented with a Flow, Upzelo takes care of all of the billing updates for you. Some of the Actions that you create are billing related and we will go through those in a bit more detail below.

### 4. Creating Webhooks

Unfortunately, Recurly does not allow the automatic creation of webhooks via their API, so these will need to be set up manually.

In the Developer dashboard on Upzelo, there is a card that has a `Webhook URL`, depending on which mode you are currently in (test/live) this will change to display the correct URL to use for your webhooks.

Webhooks set up on Recurly need to be in XML format, with all notification types selected.

## How Upzelo works with Recurly

### 1. Subscription Pausing

Upzelo uses Recurly's built-in pause feature. How this works, is we update the subscriptions `remaining_pause_cycles` and set it to the amount of days selected in the action.

{% hint style="info" %}
We follow the best practices set out in the [Recurly documentation](https://docs.recurly.com/docs/pause-subscription)
{% endhint %}

### 2. Applying Discounts

You can create different types of discounts in the Actions section. When a customer accepts a discount (money off, percentage, or even a "free period"), we will apply the coupon to the subscription ID that has been provided.

### 3. Cancelling Subscriptions

Upzelo handles cancelling subscriptions for you. The behaviour of this can be configured so that the subscription either ends immediately or at the end of the current period. This is configurable on each Flow that you offer.


# Chargebee

Integrate Chargebee with Upzelo

## How to connect Chargebee and Upzelo

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FaSRF5521GmR1r8HBig2u%2Fimage.png?alt=media&amp;token=92028d23-f58a-42d7-9bae-d8487ecf555e" alt=""><figcaption></figcaption></figure>

Start by clicking the `Connect` button underneath the Chargebee card. The card will then transform into a form with fields for you to enter your Live mode and Test mode Site Names and API Keys.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2Fh0PaIZ6zRvK0bd7rDDLl%2Fimage.png?alt=media&amp;token=7a2f708c-0491-4fcd-b0e0-d57ad1e4816c" alt=""><figcaption></figcaption></figure>

Follow the instructions on the form and confirm your keys work correctly by pressing `Check` before pressing `Save`.

After pressing `Save`, we will check that you have set up the key with the correct permissions. Once that check is complete, your data will begin to be imported into Upzelo.

## How is Chargebee used with Upzelo?

### 1. Audience Segmentation

Upzelo imports data from your Chargebee account so that it can be used to create audiences. This allows you to create Flows that can be tailored specifically to a segment of your customer base. This means that a new sign-up can receive a Flow different from a customer that you consider to be valued.

{% hint style="info" %}
Upzelo imports `Customers`, `Subscriptions`, `Coupons`, `Products` and `Prices` from Chargebee.
{% endhint %}

**Segmentation Attributes**:

* Subscription Age
* Plan
* Billing Interval
* Subscription Status

### 2.  Creating Discounts

The Actions section of Upzelo will create coupons inside of your Chargebee account which can then be used inside of Flows.

{% hint style="warning" %}
Actions created in test mode are only available for test mode flows.
{% endhint %}

### 3. Updating Customer Subscriptions

When a customer is presented with a Flow, Upzelo takes care of all of the billing updates for you. Some of the Actions that you create are billing related and we will go through those in a bit more detail below.

### 4. Creating Webhooks

Chargebee doesn't allow the automatic creation of webhooks, these need to be set up manually.

Your webhook URL can be found on the Developer dashboard on Upzelo.

Create a webhook on Chargebee using the URL provided, under Events to Send, select `All Events` and toggle `Exclude card information from webhook call`, we never require card information belonging to your customers.

## How Upzelo works with Chargebee

### 1. Subscription Pausing

Upzelo uses Chargebee's built-in pause feature. How this works, is we update the subscriptions `pauseOption` and set it to `immediately`. We also set `resumeDate` to now plus the time period specified in your Action (e.g. 2 months).

{% hint style="info" %}
We follow the best practices set out in the [Chargebee documentation](https://apidocs.chargebee.com/docs/api/subscriptions?prod_cat_ver=2#pause_a_subscription)
{% endhint %}

### 2. Applying Discounts

You can create different types of discounts in the Actions section. When a customer accepts a discount (money off, percentage, or even a "free period"), we will apply the coupon to the subscription ID that has been provided.

### 3. Cancelling Subscriptions

Upzelo handles canceling subscriptions for you. The behavior of this can be configured so that the subscription either ends immediately or at the end of the current period. This is configurable on each Flow that you offer.

## API Key Permissions

When creating an API key on Chargebee, certain permissions are required for Upzelo to function correctly.

The API key needs to be a `Full-Access Key` and be a `Write Key` for Upzelo to function correctly


# Recharge

Integrate Recharge with Upzelo

## How to connect Recharge and Upzelo

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FaSRF5521GmR1r8HBig2u%2Fimage.png?alt=media&amp;token=92028d23-f58a-42d7-9bae-d8487ecf555e" alt=""><figcaption></figcaption></figure>

Start by clicking the `Connect` button underneath the Recharge card. The card will then transform into a form with fields for you to enter your Live mode and Test mode API keys.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2F57EhtYywdRyaxij8iwNm%2Fimage.png?alt=media&amp;token=872a6f27-2e80-49bd-b57c-0866cdcdcaaa" alt=""><figcaption></figcaption></figure>

Follow the instructions on the form and confirm your keys work correctly by pressing `Check` before pressing `Save`.

After pressing `Save`, we will check that you have set up the key with the correct permissions. Once that check is complete, your data will begin to be imported into Upzelo.

## How is Recharge used with Upzelo?

### 1. Audience Segmentation

Upzelo imports data from your Recharge account so that it can be used to create audiences. This allows you to create Flows that can be tailored specifically to a segment of your customer base. This means that a new sign-up can receive a Flow different from a customer that you consider to be valued.

{% hint style="info" %}
Upzelo imports `Customers`, `Subscriptions`, `Coupons`, `Products` and `Prices` from Recharge.
{% endhint %}

**Segmentation Attributes**:

* Subscription Age
* Plan
* Billing Interval
* Subscription Status

### 2.  Creating Discounts

The Actions section of Upzelo will create coupons inside of your Recharge account which can then be used inside of Flows.

{% hint style="warning" %}
Actions created in test mode are only available for test mode flows.
{% endhint %}

### 3. Updating Customer Subscriptions

When a customer is presented with a Flow, Upzelo takes care of all of the billing updates for you. Some of the Actions that you create are billing related and we will go through those in a bit more detail below.

### 4. Creating Webhooks

Upzelo automatically creates webhooks so that it is always up to date with your customer's subscriptions.

## How Upzelo works with Recharge

### 1. Subscription Pausing

Pausing works a little differently with Recharge, instead with this, we offer the ability to "skip" the next charge.

We do this by requesting the next upcoming charge, and then marking it as skipped.

### 2. Applying Discounts

You can create different types of discounts in the Actions section. When a customer accepts a discount (money off, percentage, or even a "free period"), we will apply the coupon to the subscription ID that has been provided.

### 3. Cancelling Subscriptions

Upzelo handles canceling subscriptions for you. The behavior of this can be configured so that the subscription either ends immediately or at the end of the current period. This is configurable on each Flow that you offer.

## API Key Permissions

When creating an API key on Recharge, certain permissions are required for Upzelo to function correctly.

| Scope             | Permission |
| ----------------- | ---------- |
| Orders            | Write      |
| Discounts         | Write      |
| Subscriptions     | Write      |
| Payments          | Write      |
| Customers         | Write      |
| Products          | Read       |
| Store Information | Read       |


# Woocommerce

Integrate Woocommerce with Upzelo

## How to connect Woocommerce and Upzelo

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FYi9riYkl43ci2KW5KA8V%2Fimage.png?alt=media&amp;token=7f173196-bfc0-4dab-87e0-a3a97082610f" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Our Woocommerce integration is currently in beta. Please provide us with any feedback via the Intercom live chat.
{% endhint %}

Start by clicking the `Connect` button underneath the Woocommerce card. The card will then transform into a form with fields for you to enter your Live mode and Test mode API keys and store URL.

The store URL is the same URL as your `wp-admin` dashboard, just without the `wp-admin` suffix.\
For example, if your wp-admin URL is `https://www.example-store.com/wp-admin/`, the URL you would input into the form would be `https://www.example-store.com`.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2F7qB7ayRLKAfUbBnSmoSH%2Fimage.png?alt=media&amp;token=beb7d76e-5507-4582-8006-bf0d7466a74a" alt=""><figcaption></figcaption></figure>

Follow the instructions on the form and confirm your keys work correctly by pressing `Check` before pressing `Save`.

After pressing `Save`, we will check that you have set up the key with the correct permissions. Once that check is complete, your data will begin to be imported into Upzelo.

## How is Woocommerce used with Upzelo?

### 1. Audience Segmentation

Upzelo imports data from your Woocommerce account so that it can be used to create audiences. This allows you to create Flows that can be tailored specifically to a segment of your customer base. This means that a new sign-up can receive a Flow different from a customer that you consider to be valued.

{% hint style="info" %}
Upzelo imports `Customers`, `Subscriptions`, `Coupons`, `Products` and `Prices` from Woocommerce.
{% endhint %}

**Segmentation Attributes**:

* Subscription Age
* Plan
* Billing Interval
* Subscription Status
* Customer Location

### 2.  Creating Discounts

The Actions section of Upzelo will create coupons inside of your Woocommerce account which can then be used inside of Flows.

{% hint style="warning" %}
Actions created in test mode are only available for test mode flows.
{% endhint %}

### 3. Updating Customer Subscriptions

When a customer is presented with a Flow, Upzelo takes care of all of the billing updates for you. Some of the Actions that you create are billing related and we will go through those in a bit more detail below.

### 4. Creating Webhooks

{% hint style="info" %}
We don't currently support webhooks with Woocommerce. We are working on this as we expand with the beta.
{% endhint %}

## How Upzelo works with Woocommerce

### 1. Applying Discounts

You can create different types of discounts in the Actions section. When a customer accepts a discount (money off, percentage, or even a "free period"), we will apply the coupon to the subscription ID that has been provided.

### 2. Cancelling Subscriptions

Upzelo handles canceling subscriptions for you. The behavior of this can be configured so that the subscription either ends immediately or at the end of the current period. This is configurable on each Flow that you offer.

## API Key Permissions

When creating an API key on Woocommerce, It is essential that the API key has read/write permissions.


# QPilot

Integrate QPilot with Upzelo

## How to connect QPilot and Upzelo

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FDHgWRxLhDsu1LbRftcDy%2Fimage.png?alt=media&amp;token=2ec82f92-4c14-4327-83a8-8d9449f05d4d" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Our QPilot integration is currently in beta. Please provide us with any feedback via the Intercom live chat.
{% endhint %}

Start by clicking the `Connect` button underneath the QPilot card. The card will then transform into a form with fields for you to enter your Live mode and Test mode API keys and Site Ids.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FjjkttbKuYMeflzxTkpc5%2Fimage.png?alt=media&amp;token=95865287-3938-421f-a800-ba601bbf4510" alt=""><figcaption></figcaption></figure>

Follow the instructions on the form and confirm your keys work correctly by pressing `Check` before pressing `Save`.

After pressing `Save`, we will check that you have set up the key with the correct permissions. Once that check is complete, your data will begin to be imported into Upzelo.

## How is QPilot used with Upzelo?

### 1. Audience Segmentation

Upzelo imports data from your QPilot account so that it can be used to create audiences. This allows you to create Flows that can be tailored specifically to a segment of your customer base. This means that a new sign-up can receive a Flow different from a customer that you consider to be valued.

{% hint style="info" %}
Upzelo imports `Customers`, Scheduled Orders, `Coupons`, and`Products`from QPilot.
{% endhint %}

**Segmentation Attributes**:

* Subscription Age
* Plan
* Billing Interval
* Subscription Status

### 2.  Creating Discounts

The Actions section of Upzelo will create coupons inside of your QPilot account which can then be used inside of Flows.

{% hint style="warning" %}
Actions created in test mode are only available for test mode flows.
{% endhint %}

### 3. Updating Customer Subscriptions

When a customer is presented with a Flow, Upzelo takes care of all of the billing updates for you. Some of the Actions that you create are billing related and we will go through those in a bit more detail below.

### 4. Creating Webhooks

Upzelo automatically creates webhooks so that it is always up to date with your customer's subscriptions.

You can check the status of these inside your QPilot account, under the Site Dashboard > Webhooks.\
\
If webhooks are missing, please contact us via live chat.

## How Upzelo works with QPilot

### 1. Applying Discounts

You can create different types of discounts in the Actions section. When a customer accepts a discount (money off, percentage, or even a "free period"), we will apply the coupon to the subscription ID that has been provided.

### 2. Cancelling Subscriptions

Upzelo handles cancelling subscriptions for you. The behaviour of this can be configured so that the subscription either ends immediately or at the end of the current period. This is configurable on each Flow that you offer.

### 3. Pausing Subscriptions

Upzelo offers adjustable length pause periods when creating actions. When a subscriber accepts a pause offer the Next Occurrence Date of the Scheduled Order is adjusted by adding the length of the pause offer to today's date. This will result in an adjusted order schedule.


# API

Integrate your custom solution with Upzelo

## How to connect to Upzelo using the API

Head over to the [Integrations](https://upzelo.com/app/integrations) page in the Setup menu on the bottom left of the dashboard, you will be presented with a list of Integrations that Upzelo offers.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2FaSRF5521GmR1r8HBig2u%2Fimage.png?alt=media&amp;token=92028d23-f58a-42d7-9bae-d8487ecf555e" alt=""><figcaption></figcaption></figure>

Start by clicking the `Connect` button underneath the API card. To enable write access with the API, click on `Activate API`.

<figure><img src="https://2477763041-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fny2KheLD0svN4wwa3pPL%2Fuploads%2Fs1YaXHRSFVxMd0NavJJg%2Fimage.png?alt=media&amp;token=8e6dd13d-4142-4b77-ab64-53ff0fe8d544" alt=""><figcaption></figcaption></figure>

After pressing `Save`, a button will appear that when clicked will take you to create your API keys.

## Creating an API Key

On the `API Keys` page of the Developer section, you will be presented with your `App ID`. This is used in the headers sent to the Upzelo API.

Get started by clicking `Create an API Key`. Enter a name for your API Key and select the appropriate permissions for the key.

Once you have created your API Key, head over to the [API Documentation](https://upzelo.com/api/docs) to get started implementing Upzelo with your system.


# Webhooks

Listen for Upzelo events so your integration can automatically trigger reactions

Upzelo uses webhooks to notify your application when an event happens on your Upzelo account. Webhooks are useful for you to take any action needed for asynchronous events like when a customer cancels their subscription or accepts a discount offer.

## How Upzelo uses webhooks

Webhooks enable Upzelo to push real-time notifications to your app. We send you a JSON payload to a URL that has been specified in your webhook configuration. You can then use these notifications to execute actions on your own platform.

### How to receive webhooks

1. Create a new webhook in the [Upzelo developer dashboard](https://www.upzelo.com/app/developer/webhooks)
2. Create an endpoint on your web app to listen for the webhooks
3. Handle the request by parsing the payload and returning a 200 response code.

## When are webhooks sent?

Webhooks are sent within seconds of an event happening on Upzelo.

Upzelo uses exponential backoffs when sending webhooks. What this means is that the time between retries will increase until we hit a maximum limit, or a `200` status code is returned. Below is a table outlining the times between attempts.

| Attempt Number | Delay (minutes) |
| -------------- | --------------- |
| 1              | Immediately     |
| 2              | 3               |
| 3              | 5               |
| 4              | 9               |
| 5              | 17              |
| 6              | 33              |
| 7              | 65              |

## What events are available?

* Flow Started - This is when a customer begins a flow via Upzelo.
* Flow Abandoned - This is when a flow is started, but not completed after 60 minutes.
* Subscription Pause - When a customer accepts a pause offer.
* Subscription Skip Charge - When a customer accepts a skip charge offer.
* Subscription Plan Change - When a customer accepts a plan change offer.
* Subscription Free Period - When a customer accepts a free period offer.
* Subscription Discount - When a customer accepts a discount offer.
* Subscription Cancelled - When a customer cancels their subscription.
* New Request - When a new request enters the system from a Flow

## Example event payloads

### Flow

{% tabs %}
{% tab title="Flow Started" %}

```json
{
    "data": {
        "type": "flow.started",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "flow": {
            "title": "High-value customers",
            "reason": "Matched audience"
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}

{% tab title="Flow Abandoned" %}

```json
{
    "data": {
        "type": "flow.abandoned",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "flow": {
            "title": "High-value customers",
            "reason": "Matched audience"
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}
{% endtabs %}

### Subscription

{% tabs %}
{% tab title="Pause" %}

```json
{
    "data": {
        "type": "subscription.pause",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "duration": 2,
        "duration_unit": "month",
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}

{% tab title="Skip Charge" %}

```json
{
    "data": {
        "type": "subscription.skip-charge",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
        }
    }
}
```

{% endtab %}

{% tab title="Plan Change" %}

```json
{
    "data": {
        "type": "subscription.plan-change",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "price": {
            "external_id": "price_1234"
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}

{% tab title="Free Period" %}

```json
{
    "data": {
        "type": "subscription.free-period",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "coupon": {
            "external_id": "coupon_1234",
            "duration_in_months": 1,
            "duration": "once",
            "amount_off": null,
            "percent_off": 20
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}

{% tab title="Discount" %}

```json
{
    "data": {
        "type": "subscription.discount",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "coupon": {
            "external_id": "coupon_1234",
            "duration_in_months": 1,
            "duration": "once",
            "amount_off": 1000, // Cent value
            "percent_off": null
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}

{% tab title="Cancel" %}

```json
{
    "data": {
        "type": "subscription.cancelled",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
    }
}
```

{% endtab %}
{% endtabs %}

### Requests

{% tabs %}
{% tab title="New Request" %}

```json
{
    "data": {
        "type": "request.created",
        "attempt": 1,
        "customer": {
            "external_id": "cus_1234",
            "name": "Richard Hendricks",
            "email": "richard@piedpiper.com",
            "description": "Created middle-out compression",
            "created": "2023-01-01 00:02:04",
            "phone": "07123456789",
            "additional_id": null,
            "upzelo_id": "upz_cus_1234",
            "metadata": null,
            "country": "GB",
            "state": "East Sussex"
        },
        "subscription": {
            "external_id": "sub_1234",
            "additional_id": null,
            "current_period_start": "2023-01-01 00:00:00",
            "current_period_end": "2023-01-31 23:59:59",
            "cancel_at_period_end": false,
            "status": "active",
            "start_date": "2020-01-01 00:00:00",
            "canceled_at": null,
            "upzelo_id": "upz_sub_1234"
        },
        "flow": {
            "title": "High-value customers",
            "reason": "Matched audience"
        },
        "app_id": "upz_app_1234",
        "test_mode": true,
        "request_type": "cancel"
    }
}
```

{% endtab %}
{% endtabs %}


