# Overview

what is subs ?

Subs is a decentralized easy to use recurring payment protocol enabling businesses to earn recurring revenue in web3. Business ( App providers ) create subscription applications and their payment system in the subs contract. Simultaneously, in the same contract, the subscribers can subscribe to these applications while keeping their funds in their wallets. The subscribers simply in one transaction give the right to the protocol through the regulators to trigger the payment according to the rules of the app providers (every month, every week, every day…).\
\
Examples of recurring payment can be Subscription, automated investing, peer to peer payments or many others.<br>

<figure><img src="https://lh5.googleusercontent.com/T7YYajKB3YEp_Wc654io9GcYnU6w8Xk-8G--RcYvgbbqVbOZkq2b4-r3KW7mZB_vrL4Ef3Mos-7pja03ywvRFg21GomG7NZeSdEMOJTmQgvIoE2ePfYvZRuQj1AGAIIPmLsPQlvkByP_KymYc7ITH74" alt=""><figcaption><p>Subs arch</p></figcaption></figure>

The automation of payments is decided by the protocol and all these actors ::&#x20;

* For **app providers ( businesses, creators...)**, they can easily create a complete subscription and automatic payment system by providing their own rules.
* For **subscribers**, they can subscribe and unsubscribe to an application created by the app providers according to the rules provided by them
* For **regulators**, they regulate the protocol by automating or disabling subscriber payments according to the app providers' rules to earn a reward higher than their transaction costs.\ <br>

Subs makes possible to create fully customizable subscription plans and subscribe directly on-chain. Our goal is to make it super accessible thanks tour SDK. Which means Subs Protocol is perfect for business that wants to make their first steps into Web3.


# Uses Cases

Subs potential use cases

Subs protocol is a system that allows for the creation and management of subscription-based services on a blockchain. These services can take various forms, including Subscription, automated investing, peer to peer payments or many others. Let's explore these use cases in more detail. <br>

**Subscriptions**: The most obvious use case is managing subscriptions. Businesses can easily create customized subscription services using the Subs protocol. This includes monthly, weekly, daily, or even more specific subscription frequencies based on users' needs.\
\
**Automated Investing**: Developers can use Subs protocol to create fully DCA protocol. That can allow a user to create an automated investment strategy that purchases digital assets at regular intervals, all while retaining full control over their funds.

**Peer-to-Peer Payments**: Subs also facilitates recurring peer-to-peer payments. This can be used in various contexts, such as sharing expenses among friends, paying rent or other bills, or even employment contracts based on regular payments.

**Content Services**: Content creators can use Subs to offer subscriptions to their exclusive content. Users can subscribe to channels, blogs, media streams, and even video games, with automated payments ensuring continuous access.

**Payments split**: Buy now, pay later

**Decentralized Savings and Loans**: Subs can be used to automate periodic contributions to liquidity pools or repay loans, providing advanced functionality for the decentralized economy.

**Charity and Donations**: Charitable organizations can use Subs to collect recurring donations transparently, providing donors with precise tracking of how their funds are utilized.

In summary, the Subs protocol opens up a wide range of possibilities in the realm of recurring payments and subscriptions on the blockchain, offering revolutionary potential across numerous sectors, from entertainment to decentralized finance.&#x20;


# Subscription

Main use case

Subscription is the first use case that the Subs team set up to enable businesses to generate recurring revenue. This model provides a detailed and customizable approach to recurring payments without coding :astonished:  .  Here's a typical example of what you can do with Subs.

<figure><img src="/files/dW2dlzYEiun7oSK05u5i" alt=""><figcaption><p>Subs example implementation</p></figcaption></figure>

The subscription flow enables a recurring payment agreement between a consumer and a service provider. This service provider could be a traditional web2/SaaS business or any creator, community,charity, or others.

### **Tailored Subscription Configuration**<br>

**Flexible Billing Periods**: Subs allows for the fine-tuning of billing cycles, permitting service providers to choose from customizable intervals such as days, weeks, months, or years. This adaptability caters to diverse subscription needs.

**Flexible Payments**: Subs allows service providers to have several types of payments in one subscription. They can add as many payments as they want ( eg. Standard Plan, Premium plan etc... like the example below) and as many tokens as they want in these payments ( usdt, dai, link, uni, or any ERC20 token).

**Complimentary Trial Periods**: Service providers have the option to offer complimentary trial periods, which can be adjusted to suit their strategy, with trial durations. This feature serves as an effective marketing tool to attract potential subscribers.

**Multi Tokens**: Service providers have the option to choose any ERC20 token they want, not only stable coins. This allows DApps to give their token one more use case.

**Flexible Period**: Service providers have the option of adding a day period that the consumer takes in addition if their payment is due and they don't have the funds.&#x20;

### **Supporting Components**

Subs provides supplementary components to streamline the subscription process:

* **Subscription Widget**: The subscription widget is a user-friendly React component tool that can be seamlessly integrated into a service provider's website or web application. This widget features a "Subscribe" button, handling all wallet interactions with consumers. It simplifies the approval process for spending and gasless subscription initiation, eliminating the need for service providers to delve into web3 programming or smart contract interactions. The widget offers extensive customization options, and default subscription settings can be defined when configuring subscription plans. [See more](/developer-docs/subs-widget)
* **Personal Pages on Subs**:  For users who don't have a website or application, or just no knowledge of code, we offer free hosting of their work directly on Subs. Integration can be done with Discord, Telegram or others, depending on the needs of the service provider. [See example](https://testnet.subsprotocol.com/#/0xDEd399C85d29b284ab92fA16915eFcD9dEEd77b9/bsct_4).
* &#x20;**API:**  We also provide an easy-to-use API for interacting with the Subs protocol. [See more](/developer-docs/api/get)

<br>


# Subs Apps

Whatever uses cases you want to use Subs for, the first thing to do is to [**create your Subs App**](/how-it-works/create-your-app) :rocket:&#x20;

In the subs protocol, anyone can create a recurring payment application for free, be it a subscription system or any other use case. To create an application the creators provides different properties such as: the name of his application and his payment system. They can accept any number of payments with any number of ERC-20 tokens in their app. \
\
Each application created has its own payments/plans systems, its own ownership system to manage it  that the creator can manage with the protocol. Each payment system linked to an application has different attributes such as the type of period (monthly, yearly, daily, weekly, …), the tokens it accepts as payment, the minimum time for which its user must approve its token in order for it to be taken every duration. All these payments per period (monthly, daily, ...) defined by the app creator are made by the regulators when this period is due. The regulators automate the payment of apps users. In case the user has no funds in his wallet, or any other reason for not paying his subscription, The app provider give him an additional time period. If this period is over, his subscription is deactivated by the regulators and it will be up to the user to restart his subscription.

After creating their application, creators have access to a large panel of components that they can just copy and paste onto their front-end application without coding. They can also let users subscribe directly on subs web app if they don't have web applications.

A user can subscribe to an application through these payments by paying the amount due with the tokens required by the payment. The user does not need to block these tokens in the protocol, he just needs to approve these tokens that will be taken according to each period defined by the application provider.

<br>


# Create Your App

Create your subscription system easily

#### First things first.

<figure><img src="/files/J5xQMnORJVL6mknIJK7Y" alt=""><figcaption></figcaption></figure>

Visit our page [here](https://app.subsprotocol.com)

<div align="center" data-full-width="false"><figure><img src="/files/S5Aesnaf3U1IWfLpJcJH" alt="" width="123"><figcaption><p>Before connection</p></figcaption></figure> <figure><img src="/files/xFsEnZgwOO29oHAkbFat" alt="" width="142"><figcaption><p>With a Wallet connected</p></figcaption></figure></div>

Then connect your favorite wallet to the application. We're using Wallet Connect, one of the best wallet aggregator. So no worries regarding the compatibility of your browser wallet.

<figure><img src="/files/cNMcxkAKPAYumji3O5dJ" alt="" width="140"><figcaption><p>Once connected click on Create App</p></figcaption></figure>

<figure><img src="/files/acWenwVfYi7SeczIPz1H" alt="" width="375"><figcaption></figcaption></figure>

Now the real deal, create your plan. It's super simple, you only need to fill this form.

1. Choose the blockchain you want to use. Right now we are only on EVM, but we'll be on other chain really soon.&#x20;
2. Name your <mark style="color:green;">**Application**</mark>, this will be the name of your product or service.
3. Same for the <mark style="color:blue;">**Payment/Plan**</mark>, you can do a Standard, Premium, Student formula for example.
4. Here, we give you the choice of how often we will charge your client.
5. For <mark style="color:red;">**Token**</mark>, you can either choose it from the list but also search by the address or the name in the search bar.
6. Enter the amount.
7. With this button you can add another <mark style="color:red;">**Token**</mark> for a <mark style="color:blue;">**Payment**</mark>&#x20;
8. And this button allows you to add a <mark style="color:blue;">**Payment**</mark> in your <mark style="color:green;">**Application**</mark>
9. Perfect ! You can create your <mark style="color:green;">**Application**</mark>.

#### Almost Done !&#x20;

<figure><img src="/files/58hC3dczncpdRmbCnhGS" alt=""><figcaption><p>From Recap</p></figcaption></figure>

Verify all the information one last time. One Click and your plan is live !

### Sit back and earn with subs

The only thing you need to do now is to choose [how you will earn your rewards with subs](/how-it-works/earn-with-subs). See you in the next section.


# Earn with Subs

Multiple ways to earn

There are many ways to earn recurring revenue with Subs after you've created your application. The simplest is "personal subs" which allows you to just have a page hosted on Subs and let your users subscribe, nothing more.

## Personal Page

The first thing you need to do is add your app information, and for that, go to [Subs](https://app.subsprotocol.com/#/app/apps), on your apps page click **manage** and complete your app details :&#x20;

<figure><img src="/files/scoaxhtNsZ0MmgSXPKIo" alt=""><figcaption></figcaption></figure>

After that, complete your profile :

<figure><img src="/files/gmwR5tlyENtKlnuShX62" alt=""><figcaption></figcaption></figure>

Boom, the magic of Subs :tada::tada::tada:

<figure><img src="/files/4atFb1VrUS5TGiauqrhN" alt=""><figcaption></figcaption></figure>

#### We keep it simple

<div><figure><img src="/files/log0CGr9ANDuKHjTAyyw" alt="" width="295"><figcaption></figcaption></figure> <figure><img src="/files/FnDVrV4WuL5dx9ZG8HIc" alt=""><figcaption></figcaption></figure></div>

For the end users, they just need to choose the plan and the token they want to use. And, Tadaa, a new subscriber :tada::tada::tada: . Take a look at this [example](https://testnet.subsprotocol.com/#/0x6432BF02a54975500EE3924Dfe504351E27b968B/mumbai_1).

## Subs Widget&#x20;

Another way to earn recurring revenue with Subs is with the Subs widget, which lets you integrate Subs directly into your existing application.

&#x20;      &#x20;

<figure><img src="https://cdn.gamma.app/zjdxhxryph5dzu7/872e7fe83bcc4480a4f623f2e1a84930/original/Capture-d-ecran-du-2023-09-19-10-41-12.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://cdn.gamma.app/zjdxhxryph5dzu7/e4bb8404307b4d618a0eff526d052cb4/original/Capture-d-ecran-du-2023-09-19-09-10-57.png" alt=""><figcaption></figcaption></figure>

Simply install our package JS on your already existing website, it's easy to setup.\
Go check [Subs Widget page](/developer-docs/subs-widget).&#x20;

## Telegram Monetization

There are a service build on top of Subs that allow you to monetize your group or channel telegram with your subs plans: Check our [telegram bot](/developer-docs/telegram)  .&#x20;

## Discord Monetization

There are others services build on top of Subs that allow you to monetize your discord servers  with your subs plans. Write [us](https://t.me/+esGoPJGnaXE2ODNk) to get access .

## REST API

Do you have a complex existing information system? No problem, our tailor-made API helps you to easily use Subs for recurring revenues.

Our API is incredible for 2 reason:

* Is gas-less, you can add payment to your App and also let your user subscribe for FREE.
* Choose your favorite node provider and you get all the data about your subscription app and customers

It's just here [Subs API](/developer-docs/api)

## Directly on-chain

We give you all you need to recreate a mini ABI of our smart-contract.

You can integrate Subs directly into your smart contract if needed, for example verify if a user is your subscriber :&#x20;

```solidity
(bool isMySubscriber,,,) = ISubs(subsAddress).isMySubscriber(appId, userAddress);
```

\
You can even make your own SDK out of it ! Posibilities are endless, there are several possibilities, so it's up to you

All you need: [Subs Contract](/developer-docs/apps-contracts)


# Chains

Subs chains

In the Subs ecosystem, each blockchain has its own codename. To interact with the Subs API, Discord bot, or Telegram bot, you'll need these codenames.

<table><thead><tr><th width="328" align="center">Chains</th><th align="center">Code Name</th></tr></thead><tbody><tr><td align="center">Polygon  Pos Amoy</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">amoy
</code></pre></td></tr><tr><td align="center">Binance Smart Chain Testnet</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">bsct
</code></pre></td></tr><tr><td align="center">Base Sepolia </td><td align="center"><pre class="language-typescript"><code class="lang-typescript">baset
</code></pre></td></tr><tr><td align="center">Stellar testnet</td><td align="center"><pre><code>stellart
</code></pre></td></tr><tr><td align="center"></td><td align="center"></td></tr><tr><td align="center">Polygon Pos Mainnet</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">polygon
</code></pre></td></tr><tr><td align="center">Binance Smart Chain </td><td align="center"><pre><code>bsc
</code></pre></td></tr><tr><td align="center">Base Mainnet</td><td align="center"><pre><code>base
</code></pre></td></tr><tr><td align="center">Stellar public</td><td align="center"><pre><code>stellar
</code></pre></td></tr></tbody></table>


# Testnets

Subs Testnets Adresses

<table><thead><tr><th width="328" align="center">Chains</th><th align="center">Addresses</th></tr></thead><tbody><tr><td align="center">Polygon  Amoy</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">0x7BfBb8ea2c5bFCbf26Fc5CB53Ffc961De0F9Eaa2
</code></pre></td></tr><tr><td align="center">Binance Smart Chain Testnet</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">0x04452A6183547A769a8cdcD4ab08Bc5ad9A5a1aB
</code></pre></td></tr><tr><td align="center">Base Sepolia</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">0x471Ff045265724322667c484D2ED132C6a68e94B
</code></pre></td></tr><tr><td align="center">Stellar testnet</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">CD5AA64WRULBQ6Y6NB4C2GJKBL46J2TIXGSV4HZGLH6EHYGBH7PSQU45
</code></pre></td></tr></tbody></table>

### And more to come soon


# Mainnets

Subs Mainnet Adresses

<table><thead><tr><th width="328" align="center">Chains</th><th align="center">Addresses</th></tr></thead><tbody><tr><td align="center">Polygon Pos Mainnet </td><td align="center"><pre class="language-typescript"><code class="lang-typescript">0xd0a1DB0cDe611f1467C8d4B59422d888A9B1AC0B
</code></pre></td></tr><tr><td align="center">Binance Smart Chain</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">0xd0a1DB0cDe611f1467C8d4B59422d888A9B1AC0B
</code></pre></td></tr><tr><td align="center">Base Mainnet</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">0xd0a1DB0cDe611f1467C8d4B59422d888A9B1AC0B
</code></pre></td></tr><tr><td align="center">Stellar</td><td align="center"><pre class="language-typescript"><code class="lang-typescript">CB4WXHLU5VGRFYZUZ5BP372VZRPQIDNF24MZOANMJLUJYZHOBQYPAE4X
</code></pre></td></tr></tbody></table>

### And more to come really soon


# Subs Widget

&#x20;Subs on your website has never been easier ! Thanks to our [**React JS Package**](https://www.npmjs.com/package/subs-widget).

First things first, install the package

```
yarn install subs-widget

or

npm install subs-widget
```

Now you just need to import and use our customizable button.

```tsx
import { Subs } from 'subs-widget';

const handleResponse = (response : {success:boolean, message: string}) => {
   console.log("This is what happened" , response);    
}

return(
<Subs address={"0x8e468E7Cbf7E7E056A7591C796F2dd4C5C255591"} 
        appId="4" 
        chain={"polygon"}
        mode='testnet'
        apiKey='x123123x'
        ? color='red'
        ? width={200}
        ? defaultPayment='30Days'
        ? choice={"payment", "token"}
        ? dataOnSubs={handleResponse} />
)
```

### How it works&#x20;

Just widget without default payment.

```jsx
<Subs address={"0x8e468E7Cbf7E7E056A7591C796F2dd4C5C255591"} 
        appId="4" 
        chain={"polygon"} 
        mode='testnet'
        dataOnSubs={handleResponse}
        apiKey='x123123x'
/>
```

<figure><img src="/files/cDHVxEktT3DMUdWUk81p" alt="" width="563"><figcaption><p>Subs with just appId and chain</p></figcaption></figure>

Widget with default payment.

```tsx

<Subs address={"0x8e468E7Cbf7E7E056A7591C796F2dd4C5C255591"} 
        appId="4" 
        chain={"polygon"} 
        mode='testnet'
        defaultPayment='30Days'
        dataOnSubs={handleResponse}
        apiKey='x123123x'
/>
```

<figure><img src="https://cdn.gamma.app/zjdxhxryph5dzu7/e4bb8404307b4d618a0eff526d052cb4/original/Capture-d-ecran-du-2023-09-19-09-10-57.png" alt=""><figcaption><p>Subs with default payment</p></figcaption></figure>

Widget with default payment and token choice.

```jsx
<Subs address={"0x8e468E7Cbf7E7E056A7591C796F2dd4C5C255591"} 
        appId="4" 
        chain={"polygon"}
        mode='testnet'
        defaultPayment='30Days'
        choice={{
              payment: "30Days",
              token: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
        }}
        dataOnSubs={handleResponse}
        apiKey='x123123x'
/>
```

&#x20;    &#x20;

<figure><img src="https://cdn.gamma.app/zjdxhxryph5dzu7/872e7fe83bcc4480a4f623f2e1a84930/original/Capture-d-ecran-du-2023-09-19-10-41-12.png" alt=""><figcaption><p>Subs with payment and token choice</p></figcaption></figure>

\
You can choose multiple ways to present your button.

<table><thead><tr><th width="200">Types</th><th width="175.33333333333331">Description</th><th>Description</th></tr></thead><tbody><tr><td>address <mark style="color:red;">*</mark></td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>Address of the owner of the App</td></tr><tr><td>appId <mark style="color:red;">*</mark></td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>App ID</td></tr><tr><td>chain <mark style="color:red;">*</mark></td><td><pre class="language-solidity" data-full-width="true"><code class="lang-solidity">string
</code></pre></td><td>Network of your subscription plan</td></tr><tr><td>apiKey <mark style="color:red;">*</mark></td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>Api Key of the AppID. You can find your Key whan managing our App.</td></tr><tr><td>mode <mark style="color:red;">*</mark></td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>Choose mainnet or testnet, depending on the blockchain you are using.</td></tr><tr><td>color </td><td><pre class="language-typescript"><code class="lang-typescript">string
</code></pre></td><td>You can customize the color of your button</td></tr><tr><td>width </td><td><pre class="language-typescript"><code class="lang-typescript">number
</code></pre></td><td>And the width of the component</td></tr><tr><td>defaultPayment</td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>Paeyment name, if you want to show a particular payment</td></tr><tr><td>choice </td><td><pre class="language-java"><code class="lang-java">Object
</code></pre></td><td>Payment name and token address, prechoose and only keep the Subscribe button</td></tr><tr><td>response</td><td><pre class="language-typescript"><code class="lang-typescript"> function
</code></pre></td><td>Informs you if a subscription is done successfully.</td></tr></tbody></table>

### Get your Api Key

After creating your App go on the My Apps section on the left side of the website.

Then click on Manage of the App you want to set up

<figure><img src="/files/OvjUWQPYhm0XjkUQXB2n" alt="" width="375"><figcaption></figcaption></figure>

Wait a few seconds, your Api Key will appear on you screen right here.

<figure><img src="/files/621cCyQHDG3s7MBzncjk" alt="" width="375"><figcaption></figcaption></figure>

### Popup

**If the Popup doesn't show up, some parts of your CSS may cause some issues.**

<figure><img src="/files/gy7gIQJrf3OEbfVyF6H9" alt="" width="338"><figcaption><p>First view of the PopUp</p></figcaption></figure>

First users need to select the period you want to subscribe and fill your email. We will notify your users after each debit and notify them if a debit fails.

<figure><img src="/files/AxkhAEf0Fu3aI38MvGIy" alt="" width="338"><figcaption><p>Approval Step</p></figcaption></figure>

Users will need to approve an amount of token before the subscription. We will later debit the amount with TransferFrom calls periodically.

<figure><img src="/files/RPI89izGTkvsdA4Lnz3d" alt="" width="338"><figcaption><p>Sign to subscribe</p></figcaption></figure>

When the approval is done, all you need to do is sign to trigger the subscription process.&#x20;

<figure><img src="/files/CyW23YDLfnf92llToRU6" alt="" width="338"><figcaption><p>Error massage</p></figcaption></figure>

If the user dosen't have enough funds in his wallet, the first debit won't work.\
**And no one will be charged for this action.**

<figure><img src="/files/RCZqMKAl28aZZhnR3FoU" alt="" width="338"><figcaption><p>Success</p></figcaption></figure>

Congratulation ! \
If the transaction is a success, users will be charge from now on. It is possible to get the result thanks to dataOnSubs, the function will return the status of the operation and a message if an error happens.


# Api


# Get

Subs API Get methods

## API up ?

<mark style="color:blue;">`GET`</mark> `https://api.subsprotocol.com/creator/status`

This call is a good way to see if pur API is up and operational.

#### Path Parameters

| Name                                    | Type   | Description |
| --------------------------------------- | ------ | ----------- |
| appId<mark style="color:red;">\*</mark> | String | App ID      |
| chain<mark style="color:red;">\*</mark> | String | Chain Name  |

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | API Key     |

{% tabs %}
{% tab title="200: OK All is working fine" %}

```json
{
    "status": "ok",
    "timestamp": 1694528528826
}
```

{% endtab %}
{% endtabs %}

## Get Payment IDs for an App

<mark style="color:blue;">`GET`</mark> `https://api.subsprotocol.com/creator/payments`

#### Path Parameters

| Name                                    | Type   | Description   |
| --------------------------------------- | ------ | ------------- |
| appId<mark style="color:red;">\*</mark> | String | App ID        |
| chain<mark style="color:red;">\*</mark> | String | Chain Name    |
| rpc<mark style="color:red;">\*</mark>   | String | Node Provider |

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | API Key     |

{% tabs %}
{% tab title="200: OK " %}

```json
[
    {
        "paymentId": "0xdd346f6491955977a0f2ffdadd3efe4173e7ffd0404aaf4bb452ca5a78106dce",
        "payment": {
            "name": "5500 with 10 months",
            "owner": "0xc11CB8898B06AE1Ec901Bd8624E4D3F93a78a584",
            "fee": 0,
            "paymentType": 0,
            "paymentTokens": [
                {
                    "token": "0xA02f6adc7926efeBBd59Fd43A84f4E0c0c91e832",
                    "price": "550000000000000000000",
                    "firstAmount": "825000000000000000000"
                },
                {
                    "token": "0x0FA8781a83E46826621b3BC094Ea2A0212e71B23",
                    "price": "550000000000000000000",
                    "firstAmount": "825000000000000000000"
                },
                {
                    "token": "0xd393b1E02dA9831Ff419e22eA105aAe4c47E1253",
                    "price": "550000000000000000000",
                    "firstAmount": "825000000000000000000"
                }
            ],
            "trialPeriod": 0,
            "periodType": "MONTH",
            "limitPeriod": 10,
            "loadingTime": 3
        }
]
```

{% endtab %}
{% endtabs %}

## Check user subscription for an App

<mark style="color:blue;">`GET`</mark> `https://api.subsprotocol.com/creator/isMyUser`

#### Path Parameters

| Name                                    | Type   | Description   |
| --------------------------------------- | ------ | ------------- |
| appId<mark style="color:red;">\*</mark> | String | App ID        |
| chain<mark style="color:red;">\*</mark> | String | Chain Name    |
| user<mark style="color:red;">\*</mark>  | String | User Address  |
| rpc<mark style="color:red;">\*</mark>   | String | Node Provider |

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | API Key     |

{% tabs %}
{% tab title="200: OK " %}
{% code lineNumbers="true" fullWidth="false" %}

```json
{
    "isSubscribed": false,
    "isTrial": false,
    "paymentId": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "subId": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## All subscribers for a specific App

<mark style="color:blue;">`GET`</mark> `https://api.subsprotocol.com/creator/subs`

#### Path Parameters

| Name                                    | Type   | Description   |
| --------------------------------------- | ------ | ------------- |
| appId<mark style="color:red;">\*</mark> | String | App ID        |
| chain<mark style="color:red;">\*</mark> | String | Chain Name    |
| rpc<mark style="color:red;">\*</mark>   | String | Node Provider |

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | Api Key     |

{% tabs %}
{% tab title="200: OK " %}

```json
[
    {
        "subsId": "0xdb09f6a1baeacf8e0d63953fcf09536bce633e5bda1d57c60bb392351439a211",
        "payeeAddress": "0xD3C509e32983ffA469d48863CBBB275BD885E891",
        "tokenAddress": "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
        "PaymentName": "Premium",
        "finalPay": 200000000000000,
        "appId": 2,
        "paymentId": "0x2182d817093e51c19d2776aa2eee9b2c72d8a529a3d9a63a321c1634f569d984",
        "periodType": 5,
        "periodMultiplier": 2592000,
        "timePeriod": {
            "nTimePaid": 1,
            "limitPeriod": 36
        },
        "startTime": 1696281619,
        "activeTrial": false,
        "active": true,
        "nextPaymentTime": 1698873619,
        "renewTime": 1789593619
    }
]
```

{% endtab %}
{% endtabs %}

## Subscribers of a specific payment of an App

<mark style="color:blue;">`GET`</mark> `https://api.subsprotocol.com/creator/subsOfPayment`

#### Path Parameters

| Name                                        | Type   | Description   |
| ------------------------------------------- | ------ | ------------- |
| appId<mark style="color:red;">\*</mark>     | String | App ID        |
| chain<mark style="color:red;">\*</mark>     | String | Chain Name    |
| rpc<mark style="color:red;">\*</mark>       | String | Node Provider |
| paymentID<mark style="color:red;">\*</mark> | String | Payment ID    |

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | API Key     |

{% tabs %}
{% tab title="200: OK " %}

```json
[
    {
        "subsId": "0xdb09f6a1baeacf8e0d63953fcf09536bce633e5bda1d57c60bb392351439a211",
        "payeeAddress": "0xD3C509e32983ffA469d48863CBBB275BD885E891",
        "tokenAddress": "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
        "PaymentName": "Premium",
        "finalPay": 200000000000000,
        "appId": 2,
        "paymentId": "0x2182d817093e51c19d2776aa2eee9b2c72d8a529a3d9a63a321c1634f569d984",
        "periodType": 5,
        "periodMultiplier": 2592000,
        "timePeriod": {
            "nTimePaid": 1,
            "limitPeriod": 36
        },
        "startTime": 1696281619,
        "activeTrial": false,
        "active": true,
        "nextPaymentTime": 1698873619,
        "renewTime": 1789593619
    }
]
```

{% endtab %}
{% endtabs %}

## All the subscriptions for a specific User

<mark style="color:blue;">`GET`</mark> `https://api.subsprotocol.com/creator/userSubs`

#### Path Parameters

| Name                                    | Type   | Description   |
| --------------------------------------- | ------ | ------------- |
| chain<mark style="color:red;">\*</mark> | String | Chain Name    |
| rpc<mark style="color:red;">\*</mark>   | String | Node Provider |
| user<mark style="color:red;">\*</mark>  | String | User Address  |

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | API Key     |

{% tabs %}
{% tab title="200: OK " %}

```json
[
    {
        "subsId": "0x9062f838b0d875f3d892694883f209878037ffe6e81019821286e0c06d1ca92d",
        "appId": "2",
        "paymentId": "0x2182d817093e51c19d2776aa2eee9b2c72d8a529a3d9a63a321c1634f569d984",
        "token": "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
        "owner": "0xD3C509e32983ffA469d48863CBBB275BD885E891",
        "status": "active"
    }
]
```

{% endtab %}
{% endtabs %}


# Post

Subs API Post methods

The POST methods are completely free to use. Subs take care of the transaction fees. Your customers can now subscribe almost for free. They still need to pay the approval call.&#x20;

{% hint style="info" %}
Please, note that you need super access to call these methods. If you don't have it yet, write to [us](https://t.me/+esGoPJGnaXE2ODNk) to get it.
{% endhint %}

For the first call the signature must come from the subscriber wallet

## Gasless Subscription

<mark style="color:green;">`POST`</mark> `https://api.subsprotocol.com/creator/subscribe`

#### Request Body

| Name                                                | Type   | Description                                     |
| --------------------------------------------------- | ------ | ----------------------------------------------- |
| appId<mark style="color:red;">\*</mark>             | String | App ID                                          |
| chain<mark style="color:red;">\*</mark>             | String | Chain Name                                      |
| user<mark style="color:red;">\*</mark>              | String | User Address                                    |
| token<mark style="color:red;">\*</mark>             | String | Token Address                                   |
| paymentId<mark style="color:red;">\*</mark>         | String | Payment ID                                      |
| sig<mark style="color:red;">\*</mark>               | String | Signature of appId, paymentId, token and nonce. |
| userChoosenPeriod<mark style="color:red;">\*</mark> | String | Choosen duration of subscriptions               |

<br>

## Gasless add Payment to an App

Here the signature must come from the creator of the application.

```typescript
// Payment types

enum PeriodType {
    // 0: One Time Payment (No Subscription)
    ONETIME,
    // 1: Minutes Subscription
    MINUTES,
    // 2: Hours Subscription
    HOURS,
    // 3: Days Subscription
    DAYS,
    // 4: Week Subscription
    WEEK,
    // 5: Month subscriptions
    MONTH,
    // 6: Year subscriptions
    YEAR
}

interface PaymentToken {
  token: string; // Identifier of the token, usually an Ethereum erc-20 address
  price: string; // Price (with decimals) associated with this token, expressed as a string to avoid precision issues with large numbers
  firstAmount: string; // Initial amount ( ideally for payment split, if you want the first payment to be différent than the subscription amount), also expressed as a string for the same precision reasons
}

interface Payment {
  name: string; // Name, encoded in hexadecimal
  owner: string; // Ethereum address of the owner of the payment
  fee: number; // Associated fee ( add fee if you're not the owner of the payment and you wanna take the fees from this payment, can be used for affiliation) 50 = 5%
  paymentType: number; // Type of payment, represented by a number ( 0 = erc-20 payment )
  paymentTokens: PaymentToken[]; // List of possible payment tokens for this payment
  trialPeriod: number; // Duration of the trial period, expressed in number of days
  periodType: number; // Type of period, likely an enum indicating units like days, months, etc.
  limitPeriod: number; // minimum time for user to approve before subscription
  loadingTime: number; // The time, Subs system have to wait before considering subscription as expired ( In days )
}

```

<mark style="color:green;">`POST`</mark> `https://api.subsprotocol.com/creator/addPayment`

#### Headers

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| x-api-key<mark style="color:red;">\*</mark> | String | API Key     |

#### Request Body

| Name                                        | Type       | Description                              |
| ------------------------------------------- | ---------- | ---------------------------------------- |
| appId<mark style="color:red;">\*</mark>     | String     | App ID                                   |
| chain<mark style="color:red;">\*</mark>     | String     | Chain Name                               |
| appOwner<mark style="color:red;">\*</mark>  | String     | AppOwner address                         |
| version<mark style="color:red;">\*</mark>   | String     | Depends of the chain: testnet or mainnet |
| payments <mark style="color:red;">\*</mark> | Payment\[] | List of Payments                         |
| sig<mark style="color:red;">\*</mark>       | String     | Signature of the appId and payments      |

{% tabs %}
{% tab title="200: OK All fine" %}

```
{
    "success": "true",
    "message": "Payment successfully added"
}
```

{% endtab %}

{% tab title="400: Bad Request Wrong payments" %}

```
{
    "success": "false",
    "error": "Contract Execution Error",
    "message": "åm*®StudentStudent"
}

```

{% endtab %}
{% endtabs %}

Here you have a template for your addPayment request.\
\
Watch up the name is a string converted in Bytes32\
You can try to convert here for your tests.  <https://www.devoven.com/string-to-bytes32>

<table><thead><tr><th width="189">Variables</th><th width="175.33333333333331">Types</th><th>Description</th></tr></thead><tbody><tr><td>name</td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>Name of your app in Hexadecimal</td></tr><tr><td>owner</td><td><pre class="language-solidity"><code class="lang-solidity">string
</code></pre></td><td>Address of the beneficiary of the fees for this payment</td></tr><tr><td>fee</td><td><pre class="language-solidity" data-full-width="true"><code class="lang-solidity">uint
</code></pre></td><td>Percent given to the owner of this payment</td></tr><tr><td>paymentType</td><td><pre class="language-solidity"><code class="lang-solidity">uint
</code></pre></td><td>MUST be 0 for ERC20 token                            We will SOON add ERC721 token</td></tr><tr><td>periodType</td><td><pre class="language-solidity"><code class="lang-solidity">uint
</code></pre></td><td><p>- 0 for One Time Payement                       </p><p>- 1 for Minute Payment</p><p>- 2 for Hour Payment                             </p><p>- 3 for Day Payment                            </p><p>- 4 for Week Payment                             </p><p>- 5 for Month Payment                             </p><p>- 6 for Year Payment</p></td></tr><tr><td>trialPeriod</td><td><pre class="language-solidity"><code class="lang-solidity">uint
</code></pre></td><td>Number of periodType given for free to the customer</td></tr><tr><td>limitPeriod</td><td><pre class="language-solidity"><code class="lang-solidity">uint
</code></pre></td><td>Number of debit, but also used for the approval needed to subscribe</td></tr><tr><td>loadingTime</td><td><pre class="language-solidity"><code class="lang-solidity">uint
</code></pre></td><td>Number of extra Days customers have if the debt didn't worked</td></tr></tbody></table>

Here is how you can make you own signature.

```javascript
const { ethers } = require("ethers");

// Example input data
const data = {
    appId: "41",
    chain: "Binance Smart Chain Testnet",
    appOwner: "0x7bFD3D3E0c1cD1e8a92eFd8de2E5769D9a39497B",
    version: "testnet" or "mainnet",
    payments: [
        {
            name: "0x53747564656e7400000000000000000000000000000000000000000000000000",
            owner: "0x7bFD3D3E0c1cD1e8a92eFd8de2E5769D9a39497B",
            fee: 2,
            paymentType: 0,
            paymentTokens: [
                {
                    token: "0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1",
                    price: "20000000",
                    firstAmount: "25000000",
                }
            ],
            trialPeriod: 0,
            periodType: 1,
            limitPeriod: 3,
            loadingTime: 5
        }
    ]
};

// Signer's private key (replace with the actual private key)
const privateKey = "0x....";

function computeHash(appId, payments) {
    const paymentNames = payments.map(payment => payment.name); // Extract payment names

    // Mimic abi.encodePacked(_appId, paymentNames)
    const encoded = ethers.utils.solidityPack(
        ["uint256", "bytes32[]"],
        [ethers.BigNumber.from(appId), paymentNames]
    );
    // Compute keccak256 hash
    return ethers.utils.keccak256(encoded);
}



// Step 2: Sign the hash
async function signHash() {
    // Create a signer from the private key
    const wallet = new ethers.Wallet(privateKey);

    // Compute the message hash
    const messageHash = computeHash(data.appId, data.payments); 
    
    // Sign the hash
    let signature = await wallet.signMessage(ethers.utils.arrayify(messageHash));
    console.log("Computed Hash:", messageHash);
    console.log("Signature:", signature);
}

// Call the function
signHash().catch(err => console.error(err));
```


# Webhook

Setting Up Subs Webhooks with Moralis or just listen

Webhooks offer a powerful way to automate reactions to specific events on the blockchain, enhancing the functionality and interactivity of applications. In the context of Subs, webhooks can be utilized to monitor subscription events and any custom actions that are pivotal to subscription management and analytics.

<figure><img src="/files/bdi8rgSKgFWSqv1LPdF1" alt=""><figcaption><p>Blockchain webhook system</p></figcaption></figure>

### What are Webhooks ?

Webhooks, in essence, are automated messages sent from apps when something happens. They have URLs, making them web-accessible for receiving data immediately. Unlike typical APIs where you need to poll for data frequently, webhooks deliver data as it happens, ensuring real-time updates.

### Why Use Webhooks with Subs ?

Integrating webhooks into your Subs-powered application allows for real-time monitoring and handling of subscription lifecycle [events](https://app.gitbook.com/o/2LDgtDSXVsqfC1CZiwUe/s/Mi4ivT4S6SjuAElL2Iuo/~/changes/74/developer-docs/webhook/events), payment confirmations, and any custom blockchain events that you define within your subscription logic. This enables automated workflows, such as:

* **Notifications:** Alerting users or administrators about subscription renewals, cancellations, or payment issues.
* **Analytics:** Gathering data on user interactions and subscription trends for better business insights.
* **Compliance:** Automatically tracking and reporting for regulatory compliance and auditing.
* **Integration:** Seamlessly connecting your Subs data with other tools and services for enhanced functionality.

### Set Up Subs Webhooks with Subs Front

Just click on "Require users email address" and add your webhook url.&#x20;

<figure><img src="/files/k0gDuujWGN5ol6RJg73Y" alt=""><figcaption><p>Subs webhook config</p></figcaption></figure>

That's all. After each subscription, Subs will send you all the data relating to that subscription :tada::tada::tada:

{% hint style="info" %}
Here is all type of [events](https://app.gitbook.com/o/2LDgtDSXVsqfC1CZiwUe/s/Mi4ivT4S6SjuAElL2Iuo/~/changes/74/developer-docs/webhook/events) data Subs will sent after user subscription, cancellation or other actions.&#x20;
{% endhint %}

### Set Up your own Subs Webhooks with Moralis’ Web3 Streams API

The following sections will illustrate how to set up Subs webhooks using Moralis’ Streams API.

<figure><img src="/files/IKI8zJOrmYO3iryXk2Ci" alt=""><figcaption><p>Moralis</p></figcaption></figure>

You have two options for building your stream and receiving Subs webhooks on supported networks:

* **Programmatically** – The first alternative is to set up streams programmatically through the use of Moralis’ SDK or API - see an example [here](https://moralis.io/web3-webhooks-the-ultimate-guide-to-blockchain-webhooks/)&#x20;
* **Via Moralis’ Admin Panel** – The second alternative is to create streams using Moralis’ web UI. \
  \
  In this tutorial we will only use the second option

#### **Via Moralis’ Admin Panel**

\
Before start creating your stream, login on Moralis [here](https://admin.moralis.io/login)

&#x20;After login, create your stream : <br>

<figure><img src="/files/bAQbx1XCp42qC0dMpUia" alt=""><figcaption><p>Moralis stream page</p></figcaption></figure>

After click on create stream, at the bottom of the page, you will have this view

<figure><img src="/files/KDcKitXHES7DIh7ITHUD" alt=""><figcaption></figcaption></figure>

#### 1 - **Events**

Here, you'll need to choose what subs event you want to listen as webhook, most of the time it will be for new subscription on your app, but maybe also others. You can see all Subs events abis [here](/developer-docs/subscription-contracts#events-abi).\
\
In this example we'll use the NewSubscription event, so copy and paste it in custom onglet.\
After that, click on NewSubscription and add your filter with your app ID. You can find your app ID on your app page here for [testnet](https://testnet.subsprotocol.com/#/app/apps) or [mainnet](https://app.subsprotocol.com/#/app/apps).  <br>

{% hint style="info" %}
We recommend you to create two apps on subs before testing your stream because sometimes the filter can have problems and your stream can end up listening to all the apps on Subs :worried:. If you ever encounter this problem, edit your stream and at the bottom of the page, click on Swith to legacy, reconfigure your app in legacy mode, it should work normally.
{% endhint %}

<figure><img src="/files/RnK5i87EPvLkAH5y1Jtg" alt=""><figcaption><p>Config Moralis with Subs event</p></figcaption></figure>

#### 2 - Add Stream tag

Tag is just a way for you to identify your stream. After adding your tag, click continue.

<figure><img src="/files/q2HvJ5oKzkF5PEsHSnSI" alt=""><figcaption><p>Add stream tag</p></figcaption></figure>

#### 3 - Add Subs Contract address

Here you will need to add Subs contract address, you can find Subs testnet contract addresses [here](/deployments/chains)[ ](/deployments/testnets)and for mainnet [here](/deployments/mainnets) . Be sure to take your supported chain contract address. After copy and paste it, click to continue.

<figure><img src="/files/EClQn3nYLyVdRBNzIwIM" alt=""><figcaption><p>Paste Subs CA</p></figcaption></figure>

#### &#x20;4 - Choose chain

Choose the chains you have your subs apps on and continue

<figure><img src="/files/w8dR7j0wZ4O3Fz0iqXrn" alt=""><figcaption><p>Choose chain</p></figcaption></figure>

#### 5 - Test your stream&#x20;

Click on **Live blocks** and **Launch Live Blocks** , after that, subscribe to your app on Subs page to see if your stream work, if yes, you will have a response in the live playground if not, the playground will be empty. Don't forget to test your filter by testing a not filtered app and your filtered app.

<figure><img src="/files/n0v9yO3xcV0r8lZMfqHP" alt=""><figcaption><p>Test the stream</p></figcaption></figure>

#### 6 - Deploy your stream

Recommend you to test it fast with [webhook-site](https://webhook.site/#!/view/cff5a147-5bf0-406e-b4a6-3f5555ffd7bc). Copy and paste your unique url. Click verify and after deploy your stream. After testing with webhook-site, you can edit the stream to change the webhook and work with yours.

<figure><img src="/files/9rKOryQtz4dVITeeZoPP" alt=""><figcaption><p>Verify and deploy</p></figcaption></figure>

{% hint style="info" %}
Also notice that Moralis will send you two notifs per block, read more [here](https://docs.moralis.io/streams-api/evm/webhooks-transactions#two-webhooks-for-each-block)&#x20;
{% endhint %}

That's all, you've just set up your subs webhook  with moralis :tada::tada::tada:

### Just listen&#x20;

Maybe you want to have your own in-house solution and not depend on a third-party service. You can just listen to the subs contract to see what's going on and make action.\
Here is an sample code to listen and make action when user subscribe to your app  with ethersjs.

* Add your chain rpc url&#x20;
* Add subs contract address
* Add the app ID for filter your app

<pre class="language-javascript"><code class="lang-javascript">import { ethers } from 'ethers';
// Event ABI
<strong>let eventABI = [
</strong>    {
        "name": "NewSubscription",
        "type": "event",
        "anonymous": false,
        "inputs": [
            {
                "type": "address",
                "name": "subscriber",
                "indexed": false
            },
            {
                "type": "uint256",
                "name": "appId",
                "indexed": true
            },
            {
                "type": "bytes32",
                "name": "subscriptionId",
                "indexed": false
            }
        ]
    }
];
// Build subs contract with ethersjs
const provider = new ethers.JsonRpcProvider("YOUR_CHAIN_RPC_URL");
const contract = new ethers.Contract(
    "SUBS_CONTRACT_ADDRESS",
    eventABI,
    provider
);
 // Add your filter to listen only your app
const filter = contract.filters.NewSubscription(null, YOUR_APP_ID, null)
// Listen
console.log("Listening for NewSubscription events...");
contract.on(filter, async (event, appId, subscriptionId, subscriber) => {
    let datas = {
        subscriber: event.args[0],
        appId: event.args[1],
        subscriptionId: event.args[2],
    };
    console.log("We got it", datas);
    // Your action

});
</code></pre>

Thanks for your reading, see you :tada::tada::tada:


# Events

Subs webhook event types

Here is an overview of the types of events we send. Note that additional events may be introduced in the future, so your code should be designed to handle new types as they are added.

## checkout.session.completed

This is the example of data Subs sent after a successfull first payment&#x20;

```json
{
  "id": "0x193d230ada8be19827ecccbf870bd050da38885e5cc90a0193f931c6e528a8b4",
  "object": "event",
  "created": 1712051799722,
  "type": "checkout.session.completed",
  "data": {
    "object": {
      "id": "0x193d230ada8be19827ecccbf870bd050da38885e5cc90a0193f931c6e528a8b4",
      "object": "subscription",
      "application": "44",
      "cancel_at": null,
      "cancel_at_period_end": false,
      "canceled_at": null,
      "collection_method": "charge_automatically",
      "chain": "mumbai",
      "created": 1712051799722,
      "token_address": "0x0FA8781a83E46826621b3BC094Ea2A0212e71B23",
      "currency": "USDC",
      "currency_symbol": "USDC",
      "amount_total": 50,
      "amount": 0.5,
      "metadata": {
        "user_email": "user@gmail.com"
      },
      "customer_details": {
        "email": "customer@gmail.com"
      },
      "payment_name": "Standard",
      "payment_id": "0xad00516daf197721f85a4a89afff48066a1778f3c20ae86f8c043e1acf4972ed",
      "period": "Monthly"
    }
  }
}
```

## customer.subscription.updated&#x20;

This is the example of data Subs sent after user cancel his subscripiton. Please, note that the subscription  will not be stopped directly on the blockchain `chain`. It will be definitively stopped on the date `cancel_at`(the end of the current subscription period).&#x20;

```json
 {
  "id": "0x193d230ada8be19827ecccbf870bd050da38885e5cc90a0193f931c6e528a8b4",
  "object": "event",
  "created": 1718211273292,
  "type": "customer.subscription.updated",
  "data": {
    "object": {
      "id": "0x193d230ada8be19827ecccbf870bd050da38885e5cc90a0193f931c6e528a8b4",
      "object": "subscription",
      "application": 4,
      "cancel_at": "123415424542435",
      "cancel_at_period_end": true,
      "canceled_at": 1718211273292,
      "collection_method": "charge_automatically",
      "chain": "bsct",
      "created": 1718211273292,
      "token_address": "0x93F1db0fa9E6997068E5dFF43F6de6E8C51711B7",
      "currency": "USDT",
      "currency_symbol": "USDT",
      "customer": "0x93F1db0fa9E6997068E5dFF43F6de6E8C51711B7",
      "amount_total": 500,
      "amount": 5,
      "metadata": {
        "user_email": "user@gmail.com"
      },
      "customer_details": {
        "email": "customer@gmail.com"
      },
      "payment_name": "Premium",
      "period": "Monthly",
      "user_address": "0x93F1db0fa9E6997068E5dFF43F6de6E8C51711B7"
    }
  }
}
```

## customer.subscription.deleted&#x20;

This is the example of data Subs sent after user definite cancel. The subscription  will be directly stopped on the blockchain `chain`.&#x20;

```json
{
  "id": "0x193d230ada8be19827ecccbf870bd050da38885e5cc90a0193f931c6e528a8b4",
  "object": "event",
  "created": 1718211577616,
  "type": "customer.subscription.deleted",
  "data": {
    "object": {
      "id": "0x193d230ada8be19827ecccbf870bd050da38885e5cc90a0193f931c6e528a8b4",
      "object": "subscription",
      "application": 4,
      "cancel_at": null,
      "cancel_at_period_end": false,
      "canceled_at": 1718211577616,
      "collection_method": "charge_automatically",
      "chain": "bsct",
      "created": 1718211577616,
      "token_address": "0x93F1db0fa9E6997068E5dFF43F6de6E8C51711B7",
      "currency": "USDT",
      "currency_symbol": "USDT",
      "customer": "0x93F1db0fa9E6997068E5dFF43F6de6E8C51711B7",
      "amount_total": 500,
      "amount": 5,
      "metadata": {
        "user_email": "user@gmail.com"
      },
      "customer_details": {
        "email": "customer@gmail.com"
      },
      "payment_name": "Premium",
      "period": "Monthly",
      "user_address": "0x93F1db0fa9E6997068E5dFF43F6de6E8C51711B7"
    }
  }
}
```


# Telegram

We provide a Telegram bot to manage your subscriptions plans and your community.

Take a look at <https://t.me/subsprobot>


# Discord Bot

We also provide a Discord bot to manage your community.

Thanks to our Discrod Bot you can set up a bot that will make sure your users are paying your Subscription plan in order to have access to a role. You can then grant the privileges that you want for every single role. And if a user Subcription stop the Bot will remove his role automatically.

### The set of /commands for the Server Admin&#x20;

#### Invite the bot on your server

The link for the bot:

[Click here to invite Subs Bot](https://discord.com/api/oauth2/authorize?client_id=1112042095885160469\&permissions=8\&scope=bot%20applications.commands)

#### Synchronize your bot with a Subs Application & Payment

To link your bot to your Subs Application your can use:

```
/link_role_app role: 'defaultRole' app_id: '5' payment_name: 'premium' chain: 'bsc'
```

#### Look at the already linked applications & payments

You can check the status of each links with this simple command:

```
/list_app
```

### The set of /commands for the User

#### Link a Discord User ID with a wallet

In order to promote or kick a user accordingly of if he pays a Subs Subcsription they first need to connect their wallet to Subs Discord Bot. They can process by typing this command:

```
/embed_link_wallet
```

The Bot will send a private message to the user with a link to an ephemeral page that will last 15 minutes.

They simply need to sign a message. And we take care of the rest.

Sit back and relax the Bot is set and running.&#x20;

### Want to customise the Bot

Remember you can change access and roles for the Bot.

For example the 3 previous commands are by default for the admin but you can change them if you want.

#### Make a command public

If you want to make a command public follow these simple steps.

Go to your Servers Settings:

<figure><img src="/files/eADnYT8vhFZppANgt58y" alt="" width="151"><figcaption><p>Right click on your server icon</p></figcaption></figure>

Then on the Integrations section:

<figure><img src="/files/P5s9YvOpR268naLY2V1t" alt="" width="563"><figcaption><p>Select Integrations</p></figcaption></figure>

Click on SubsBot, you will find 3 commands:

<figure><img src="/files/hQFVgUVgDd2BKq13gGyv" alt="" width="563"><figcaption><p>Here is the list of commands used with SubsBot</p></figcaption></figure>

By clicking on of of them, you can customize where this command can be used and by whom.<br>

<figure><img src="/files/fraT9eUJ3z5spoJJcXxw" alt="" width="563"><figcaption><p>You can grant the permissions to a specific role</p></figcaption></figure>

And that's it, your fully customized SubsBot !


# Subs SDK

Crypto subscription sdk

{% hint style="info" %}
The SDK is available for Stellar Mainnet and Testnet. [Install it ](https://www.npmjs.com/package/subs-sdk) !
{% endhint %}

#### What is Subs SDK?

The **Subs SDK** is a lightweight JavaScript/TypeScript library that makes it easy to create and manage decentralized crypto subscription plans. With just a few lines of code, developers can set up subscription plans, generate checkout links.

Whether you're building a SaaS platform, content service, or any recurring revenue model, Subs SDK lets you go live quickly with fully on-chain payments and plan management.

***


# Write

Subs sdk write methods

## Create Plan

#### Initialize Subs Client

```typescript
import { SubsSDK, PaymentType, PeriodType, SubsPayment, Keypair } from 'subs-sdk';

// Initialize with wallet private key (keep this secure!)
const subsClient = new SubsSDK("YOUR_WALLET_PRIVATE_KEY", "testnet"); // "testnet" or "public"
```

### Payment Configuration

```typescript
// Get creator keypair
const creatorKeypair = Keypair.fromSecret("OWNER_SECRET_KEY");
const creatorAddress = creatorKeypair.publicKey();

// Configure payment type
const paymentType: PaymentType = {
  tag: "ERC20",      // Only ERC20 for the moment.
  values: undefined // For simple payment types
};

// Configure period type
const periodType: PeriodType = {
  tag: "DAYS", // Other options: ONETIME | MINUTES | HOURS | WEEK | MONTH | YEAR
  values: undefined
};
```

### Payment Plans Setup

```typescript
const payments: SubsPayment[] = [
  {
    name: paymentName,      // String
    owner: creatorAddress,  // String
    fee: BigInt(0),
    payment_type: paymentType,
    payment_tokens: [
      {
        token: 'CBIGUDYSW55TYQ47D3723KD3MUP6EABI5MVFTIMHE6CEUY55GCOW4YY5', // String
        price: BigInt(6 * 10 ** 18),  // 18 Is your token decimal
        first_amount: BigInt(0)       // You can customize the first amount.
      },
      {
        token: 'CAHVA6R5QJUTYRNG3GR7XPE63MRFWQH32CHBW6CANK3OKDR5TEOHN32V', // String
        price: BigInt(6000000000000000000), // Or leave 18 zeros for the decimals
        first_amount: BigInt(0)
      }
    ],
    trial_period: BigInt(0),
    period_type: periodType,
    limit_period: BigInt(3),
    loading_time: BigInt(3)
  },
  {
    name: paymentName,
    // ... similar structure with different prices, tokens, period_type, ...
  }
];
```

### Execute Creation

```typescript
await subsClient.createApp(
  nameApp,        // String
  payments,       // Configured payment plans array
  creatorAddress, // Owner's public address
);

```

### Returns App Url

```typescript
const result = await createApp("MyApp", payments, "G...ABC123");
console.log(result.url); 
// -> https://checkout.subsprotocol.com/#/testnet?owner=G...ABC123&chain=stellart&appId=...

```

### Payment Struct

#### **1. `name`**

* **Type**: `string`
* **Description**: Unique identifier for the payment plan (e.g., `Student`, `Premium`).
* **Rules**:
  * Must be unique across all your payment plans.

***

#### **2. `owner`**

* **Type**: `string` (Stellar public key)
* **Description**: Revenue beneficiary address.
* **Default**: Use your `creatorAddress` (if not specified).
* **Revenue Sharing**:
  * If `owner ≠ creatorAddress`, fees are split:
    * `owner` earns `fee%`
    * `creatorAddress` earns `100% - fee%`.

***

#### **3. `fee`**

* **Type**: `BigInt` (basis points: 10 = 1%)
* **Description**: Revenue share for `owner` (only if `owner ≠ creatorAddress`).
* **Example**:

```typescript
fee: BigInt(50), // owner gets 5%, creator gets 95%
```

***

#### **4. `payment_type`**

* **Type**: `PaymentType`
* **Options**:

```typescript
{ tag: "ERC20", values: undefined } // Currently only ERC20-like tokens
```

* **Future**: May support NFTs or other assets via `values`.

***

#### **5. `payment_tokens`**

* **Type**: `Array<Token>`
* **Structure**:

  ```typescript
  {
    token: string,   // Stellar Asset ID (e.g., 'CBIGUDYSW55TYQ...')
    price: BigInt,   // Don't forget you token decimals
    first_amount: BigInt // Initial discounted or additional charge
  }
  ```
* **Rules:**
  * If the `first_amount`  is set to 0 no change.
  * But you can customize the First payment more or less then the `price`&#x20;
  * Use valid Stellar Token Address otherwise the payment won't work.
* **Example**:

  ```typescript
  payment_tokens: [{
    token: 'CBIGUDYSW55TYQ4...MVFTIMHE6CEUY55GCOW4YY5', //Token address
    price: BigInt(6 * 10 ** 18), // 18 Is your token decimal
    first_amount: BigInt(0) // No initial discount
  }]
  ```

***

#### **6. `period_type`**

* **Type**: `PeriodType`
* **Options**:

  ```typescript
  { tag: "ONETIME" | "MINUTES" | "HOURS" | "DAYS" | "WEEK" | "MONTH" | "YEAR" }
  ```
* **Example**:

  ```typescript
  { tag: "DAYS", values: undefined }} // Daily subscriptions
  ```

***

#### **7. `trial_period`**

* **Type**: `BigInt`
* **Description**: Free trial duration (units depend on `period_type`):
  * `DAYS`, `WEEK`, `MONTH`, `YEAR` → Trial in **days**.
  * `HOURS` → Trial in **hours.**
  * `MINUTES`  → Trial in **minutes**.
* **Example**:

  ```typescript
  trial_period: BigInt(7) // 7-day trial for "DAYS" period_type
  ```

***

#### **8. `limit_period`**

* **Type**: `BigInt`
* **Description**: Number of billing cycles users must commit to.
* **Example**:

  ```typescript
  limit_period: BigInt(3) // 3 cycles (3 days for "DAYS" period_type)
  ```

***

#### **9. `loading_time`**

* **Type**: `BigInt`
* **Description**: Grace period (in **days**) for late payments before subscription deactivation.
* **Example**:

  ```typescript
  loading_time: BigInt(3) // 3-day grace period
  ```


# Read

#### Initialize Subs Client

```typescript
import { SubsSDK, PaymentType, PeriodType, SubsPayment, Keypair } from 'subs-sdk';

// Initialize with wallet private key (keep this secure!)
const subsClient = new SubsSDK("YOUR_WALLET_PRIVATE_KEY", "testnet"); // "testnet" or "mainnet"
```

### Get Payments IDs

```typescript
await subsClient.get_app_payments(
  appId,        // BigInt
);
```

It will return the list of Payments ID in side one particular App.

### Get User Subscriptions

```typescript
await subsClient.get_user_subscriptions(
  userAdress,        // String
);
```

It will return a list of Subscription IDs for one particular User.

### Get Subscription

```typescript
await subsClient.get_subscription(
  subsId,        // String
);
```

It will give you all the data concerning a particular Subscription.

### Get App Subscribers

```rust
await subsClient.get_app_subscribers(
  appId,        // BigInt
  paymentId,    // String
);
```

It will return a list of User subscribed to a particular Payment of an App.

### Get App Subscriptions

```rust
await subsClient.get_app_subscriptions(
  appId,        // BigInt
);
```

It will return a list of Subscription IDs for a particular App.

### Get Already Subscribed

```rust
await subsClient.get_already_subscribed(
  appId,        // BigInt
  user,         // String
);
```

It will return a boolean if the User is subscribed to an App.&#x20;

### Get Canceled Subscription

```rust
await subsClient.get_cancel_subscription(
  subs_id,      // String
);
```

It will give you a boolean if the User has canceled his Subscription.


# Apps Contracts

For providers

***Apps Contract*** is the main contract of subs apps that can be use for interaction with apps.

## **View Methods**

### getAppPayments

```solidity
function getAppPayments(uint256 _appId)
```

Returns `all app payments ids (bytes32).`

### getAppByOwner

```solidity
function getAppByOwner(address _owner)
```

Returns `all app ids by owner (uint256[]).`

## **Write Methods**

### createApp

```solidity
function createApp(
    bytes32 _name,
    Payment[] calldata _payments
)
```

Create new subs app

### deleteApp

```solidity
function deleteApp(uint _appId)
```

Delete subs app.

### addPayment

```solidity
function addPayment(uint256 _appId, Payment[] calldata _payments)
```

Add new payment to an existed app.

### deletePayment

```solidity
function deletePayment(uint256 _appId, bytes32 _paymentId)
```

Delete app Payment

### changeTokenPayment

```solidity
function changeTokenPayment(
        uint256 _appId,
        bytes32 _paymentId,
        address _oldToken,
        address _newToken,
        uint256 _newPrice,
        uint256 _firstAmount
)
```

change payment Token properties.

### modifyPayment

```solidity
function modifyPayment(
        uint256 _appId,
        bytes32 _oldPaymentId,
        bytes32 name
        address owner,
        uint256 fee,
        uint256 trialPeriod,
        uint256 loadingTime
    )
```

Change payment properties

### addTokenPaymentToMyApp

```solidity
function addTokenPaymentToMyApp(
        uint256 _appId,
        bytes32 _paymentId,
        address _newToken,
        uint256 _price,
        uint256 _firstAmount
)
```

Add new token to an existed payment

### removeTokenPaymentFromMyApp

```solidity
function removeTokenPaymentFromMyApp(
        uint256 _appId,
        bytes32 _paymentId,
        address _token
)
```

Remove existed token from a payment

### transferAppOwnership

```solidity
function transferAppOwnership(uint _appId, address _newOwner)
```

Transfer app ownership to new address

### renounceAppOwnership

```solidity
function renounceAppOwnership(uint _appId)
```

Renounce app ownership<br>


# Subscription Contracts

For providers users

***Subscription Contracts*** is the main contract that allow providers users to interact with the providers created app.

## **View Methods**

### isMySubscriber

```solidity
function isMySubscriber(
      uint256 _appId,
      address _user
)
```

Returns  user subscription information for check if a specific address is a user of specific app.&#x20;

Return values :

<table><thead><tr><th width="266">Types</th><th width="228.33333333333331">Description</th><th>Description</th></tr></thead><tbody><tr><td>isSubscriber</td><td><pre class="language-solidity"><code class="lang-solidity">bool
</code></pre></td><td>True if user is a current subscriber of the app, false if not.</td></tr><tr><td>isTrialSubscriber</td><td><pre class="language-solidity"><code class="lang-solidity">bool
</code></pre></td><td>True if user is a trial subscriber of the app, false if not</td></tr><tr><td>paymentId</td><td><pre class="language-solidity"><code class="lang-solidity">bytes32
</code></pre></td><td>The id of the payment that is used in the subscription</td></tr><tr><td>subscriptionId</td><td><pre class="language-solidity"><code class="lang-solidity">bytes32
</code></pre></td><td>The subscription id</td></tr></tbody></table>

### paymentDue

```solidity
function paymentDue(bytes32 _subscriptionId)
```

Returns `subscription status`

Return values :

<table><thead><tr><th>Name</th><th>Types</th><th>Description</th></tr></thead><tbody><tr><td>isDue</td><td><pre class="language-solidity"><code class="lang-solidity">bool
</code></pre></td><td>True, if it is the time for user to pay, false if not.</td></tr><tr><td>isOver</td><td><pre class="language-solidity"><code class="lang-solidity">bool
</code></pre></td><td>True if the user has not paid and the subscription must be stopped.</td></tr></tbody></table>

## **Write Methods**

### createSubscription

```solidity
function createSubscription(
        uint256 _appId,
        bytes32 _paymentId,
        address _token,
        uint256 _userChoosenPeriod
)
```

Subscribe to an app

### cancelSubscription

```solidity
function cancelSubscription(
        bytes32 _subscriptionId,
        uint256 _appId
)
```

Stop subscription

### processSubscription

```solidity
function processSubscription(bytes32 _subscriptionId)
```

Restart subscription if stopped.

### renewSubscription

```solidity
function renewSubscription(bytes32 _subscriptionId)
```

Renewal of the subscription if it has expired.

### migrateToNewPayment

```solidity
function migrateToNewPayment(
        bytes32 _subscriptionId,
        bytes32 _newPayment,
        address _token
)
```

Migrate existing subscripiton to a new payment

### refundSubscription

```solidity
function refundSubscription(bytes32 _subscriptionId)
```

Pay subscription all at once

## **Events & ABI**

<pre class="language-solidity"><code class="lang-solidity">event NewSubscription(
    address subscriber,
    uint256 indexed appId,
    bytes32 subscriptionId
)

event TrialSubscription(
    address subscriber,
    uint256 indexed appId,
    bytes32 subscriptionId
);

event SubscriptionCancelled(
    address subscriber,
    uint256 indexed appId,
    bytes32 subscriptionId
);

<strong>event SubscriptionProcessed(
</strong>    address subscriber,
    uint indexed appId,
    bytes32 subscriptionId
);

event RefundSubscription(
    address subscriber,
    uint256 indexed appId,
    bytes32 subscriptionId
);

event RenewSubscription(
    address subscriber,
    uint256 indexed appId,
    bytes32 subscriptionId
);
</code></pre>

```json
[
    {
        "name": "NewSubscription",
        "type": "event",
        "anonymous": false,
        "inputs": [
            {
                "type": "address",
                "name": "subscriber",
                "indexed": false
            },
            {
                "type": "uint256",
                "name": "appId",
                "indexed": true
            },
            {
                "type": "bytes32",
                "name": "subscriptionId",
                "indexed": false
            }
        ]
    }
]
```


