Monetize your apps

Apps monetization allows your monday app to accept payments from users directly through monday.com.

General Information

What is monday monetization?

The monday monetization framework allows your users to pay for your app without leaving the monday.com platform. For developers, it's a seamless way to accept payments without a third-party system.

If your app uses monday monetization, our platform will handle the entire payment and billing process, including VAT and currency conversions.

Once you've implemented monetization in your app, reach out to the apps review team so we can complete the final setup.

Requirements

You have to become a vendor to use the monetization feature. You can do this by submitting this form.

Your app also needs to support the following flows to use the monetization feature:

  • Check the status of the user's subscription when they use your app
  • Enable or disable features based on the user's subscription level
  • Prompt the user for payment using our SDK
  • Migrate any users from an external billing system to monday billing without double payment

Subscriptions

The monetization framework revolves around the concept of a subscription. Each subscription serves as a billing contract between the user and your app.

Every account can only have one subscription per app. Each subscription contains three parameters:

  • Plan ID: The unique identifier of the subscription tier
  • Renewal date: The date the current subscription ends and will renew
  • Is Trial: Whether or not the user is currently in a trial period

App and Subscription Life Cycle

Here is the typical app life cycle:

  1. App installation and trial: An admin installs the app and starts a trial. The trial will have a default plan tier that you define. For example, you may want all trial users to have the Pro plan.

  2. Trial end: The app will be disabled or revert to the free plan if your app supports one after 14 days.

  3. Payment: An admin pays for the app annually or monthly. monday will handle the payment page, billing, currency conversions, tax, etc. Your app will see the updated subscription object with the correct plan_id they purchased.

  4. Usage: You should enable the relevant features based on the subscription information.

Each step of the life cycle has different outcomes. Check out our diagram to see the various states that a user goes through. Pro tip: you can zoom in on the diagram if you download it!

27712771

Supporting existing and new customers

Our monetization builds on our new billing infrastructure that is gradually released. You will need to handle two groups of customers while this infra is released:

  • Supported accounts: Can pay for your app
  • Unsupported accounts: Will need to pay externally or use a free version of your app

You must decide how to handle unsupported accounts during this transition period. Your app should have logic to prevent double payment and migrate customers from one billing system to another. We have provided some relevant tips in the last section of this article!

Checking if an account supports monetization

You can check if an account supports monetization using the apps_monetization_status object in the GraphQL API.

API Reference

The monday apps framework has three interfaces to manage your app’s monetization:

  • monday SDK: To handle subscriptions in a frontend app
  • GraphQL API: To allow your backend to access subscription information and create mock subscriptions for testing
  • Webhooks: To send subscription information to your backend and custom actions

SDK methods

The following methods are available to frontend apps through the monday SDK.

Open plan selection

Execute method to open the plan selection page or billing tab so users can pay for your app or upgrade.

When the tab is open, users can make any updates to their subscription. They can subscribe, upgrade, downgrade, or cancel.

For example, users may want to use a feature not available on their plan. You can show them the billing tab to upgrade to the next tier.

If the isInPlanSelection parameter is true, the plan selection page will open. You should use this when you want the user to pay for the app first.

If the isInPlanSelection parameter is false, the app's billing section will open instead.

Code example:

monday.execute('openPlanSelection', {isInPlanSelection: true});

Session token

Every time your app loads, we will generate a session token signed with your app’s client secret. You can get this token with the method monday.get(‘sessionToken’).

Your frontend should use this as the primary access to the current subscription.

Find more information about this SDK method here.

Code Example:

monday.get('sessionToken')
.then((token) => { 
  // send token to backend
  // On backend, call jwt.verify(token.data, 'MY_CLIENT_SECRET') 
}

App Context

Your app’s context contains helpful information to manage your app’s state, such as the board it’s connected to, the current user, etc.

In the context payload, we will include the subscription information for the current account. You can access the context using the monday.get and monday.listen methods.

These are methods for convenience method – you should always verify the subscription details in the session token since it is signed.

Example context object:

{
  "boardViewId": 19324,
  "boardId": 3423243,
  "mode": "fullScreen", 
  "theme": "light",
  "subscription" : {
      "plan_id" : "basic_tier_5",
      "is_trial" : false,
      "renewal_date" : "2021-08-27T00:00:00+00:00"
  }
}

GraphQL Methods

app_subscription

A query to return the subscription object for the current app and account based on the token used. This method does not accept any arguments and returns an array.

If an account has a mock subscription and a real one, it will only return the mock subscription.

Fields:

  • plan_id [String]: The subscription’s plan tier (e.g., basic)
  • is_trial [Boolean]: True if the account is still in the trial period
  • renewal_date [Date]: When the subscription renews
  • billing_period [String]: The type of billing period [monthly/yearly]
  • days_left [Int]: The number of days left until the subscription ends

Example query:

query {
  app_subscription {
    plan_id
    is_trial
    renewal_date
    billing_period
    days_left
  }
}

apps_monetization_status

A query to check if an account supports monetization.

Fields:

  • is_supported [Boolean]: True if the account supports app monetization

Example query:

query {
  apps_monetization_status {
    is_supported
  }
}

set_mock_app_subscription

The mutation will create a mock subscription for the account and app based on the token you’re using. It returns an app_subscription object. Please refresh your browser while using monday after creating the mock subscription so that it shows in your account.

Mock subscriptions disappear after 24 hours, and each account-app pair can create one mock subscription.

The mutation takes an “app_id” argument, which you can get from the URL of your app. To find your app_id:

  • Open the Developers section
  • Click on your app
  • The URL of the page will follow this format: myaccount.monday.com/apps/manage/{YOUR_APP_ID}/app_versions/12345/sections/appDetails

Required arguments:

  • app_id [Int!]: Your app’s unique ID that you can get from the URL
  • partial_signing_secret [String!]: Last ten characters of your app’s signing_secret

Optional arguments:

  • is_trial [Boolean]: Defaults to false
  • renewal_date [String]: Defaults to a year from now, UTC DateTime
  • plan_id [Int]: The developer's internal id for the plan

Example query:

mutation {
  set_mock_app_subscription (
       app_id:12345,
       partial_signing_secret: "abcde12345",
       is_trial: true,
       renewal_date:"2022-08-27Z10:00:00+00:00",
       plan_id: "basic_plan_15_users"
  ) {
    plan_id
  }
}

remove_mock_app_subscription

Remove the mock subscription for the current account. This method will return an error if no mock subscription exists and returns an app_subscription object.

Required arguments:

  • app_id [Int!]: The unique ID for your app
  • partial_signing_secret [String!]: The last ten digits of your signing secret

Webhooks

You can use the endpoint found in the webhooks section of your app's configuration screen to receive a notification when someone installs or uninstalls your app, creates a subscription, changes a subscription, or cancels a subscription.

18791879

You can find samples of the different event payloads below. Timestamps are in UTC:

{
  "type":"install",
  "data":{
    "app_id":1000000000,
    "user_id":3,
    "user_email":"[email protected]",
    "account_id":1,
    "version_data":{
      "major":1,
      "minor":2,
      "patch":0,
      "type":"minor"
    },
    "timestamp":"2022-06-28T06:48:06.643+00:00",
    "subscription":{
      "plan_id":"plan2",
      "renewal_date":"2022-07-19T00:00:00+00:00",
      "is_trial":false,
      "billing_period":"monthly",
      "days_left":21
    }
  }
}
{
  "type":"uninstall",
  "data":{
    "app_id":1000000000,
    "user_id":3,
    "user_email":"[email protected]",
    "account_id":1,
    "version_data":{
      "major":1,
      "minor":2,
      "patch":0,
      "type":"minor"
    },
    "timestamp":"2022-06-28T06:48:06.643+00:00",
    "subscription":{
      "plan_id":"plan2",
      "renewal_date":"2022-07-19T00:00:00+00:00",
      "is_trial":false,
      "billing_period":"monthly",
      "days_left":21
    }
  }
}
{
  "type":"app_subscription_created",
  "data":{
    "app_id":1000000000,
    "user_id":1,
    "user_email":"[email protected]",
    "account_id":777777,
    "version_data":{
      "major":1,
      "minor":2, 
      "patch":0,
      "type":"minor"
    },
    "timestamp":"2022-06-23T05:52:25.782+00:00",
    "subscription":{
      "plan_id":"plan1",
      "renewal_date":"2022-07-19T00:00:00+00:00",
      "is_trial":false,
      "billing_period":"monthly",
      "days_left":26
    }
  }
}
{
  "type":"app_subscription_cancelled_by_user",
  "data":{
    "app_id":1000000000,
    "user_id":1,
    "user_email":"[email protected]",
    "account_id":777777,
    "version_data":{
      "major":1,
      "minor":2,
      "patch":0,
      "type":"minor"
    },
    "timestamp":"2022-06-23T06:05:44.294+00:00",
    "subscription":{
      "plan_id":"plan1",
      "renewal_date":"2022-07-19T00:00:00+00:00",
      "is_trial":false,
      "billing_period":"monthly",
      "days_left":26
    }
  }
}
{
  "type":"app_subscription_changed",
  "data":{
    "app_id":1000000000,
    "user_id":1,
    "user_email":"[email protected]",
    "account_id":777777,
    "version_data":{
      "major":1,
      "minor":2,
      "patch":0,
      "type":"minor"
    },
    "timestamp":"2022-06-23T05:52:25.782+00:00",
    "subscription":{
      "plan_id":"plan1",
      "renewal_date":"2022-07-19T00:00:00+00:00",
      "is_trial":false,
      "billing_period":"monthly",
      "days_left":26
    }
  }
}

We also expose subscription information in webhooks from monday to your app. In each case, the subscription is encoded in the Authorization header of the request as a JWT. This JWT is signed with your app’s signing secret.

We will include the subscription information in three webhooks:

  • Install webhook
  • Custom action webhook
  • Uninstall webhook

Code example:

app.post("/action", function(req, res) {
    res.status(200).send({})
    const token = req.headers.authorization;
    const decoded = jwt.verify(token, “MY_SIGNING_SECRET”);
    const subscription = decoded.subscription;
})

Implementation tips

This section will cover simple tips and FAQs regarding how to manage monetization for different kinds of apps.

How do I define my plan tiers?

To prepare for monetization, the monday dev team will need to add your app’s plan tiers to our backend. You can have multiple tiers corresponding to each feature set. You must select one tier as the “recommended” tier and one for trial.

For each tier, please include:

  • App Plan ID: String that will be sent to your backend as the “plan_id”, less than 255 characters
  • Name: The title that the user will see in our marketplace
  • Description: Less than 255 characters
  • Bullet points for plan features (3 recommended, max 5, each bullet is a short sentence, ten words max
  • Monthly price in USD: Whole numbers only
  • Yearly price in USD: Whole numbers only

To give you an idea of what this information will show, check out this mockup:

781781

📘

About the fees

Each tier's fees will display as monthly fees (both for the monthly and the annual options). The monthly fee should be a round number.

For example, a yearly $55 fee would result in a monthly fee of $4.58. In this case, the yearly fee should be $48 or $60, so the monthly fee would be $4 or $5.

How do I know if a customer is on the old billing system?

If an account is on the old billing system, they do not support monetization. You will not get the subscription object in the context or via the API. The account will need to pay for the app independently through your platform.

How do I implement logic to support existing and new users?

We’ve created a diagram to show the various states a user can be in, so you can understand the logic you need to include in your app. Check it out here:

884884

How do I check subscriptions on a frontend app?

When the app loads, check the Subscription object in the JWT token. Depending on the subscription plan_id, you can enable/disable features and display block screens as needed.

When users access a feature not available on their plan, show them a block screen. You can then prompt them to open the billing tab using the SDK method.

How do I check subscriptions on an integration app?

Custom action: When integration runs, get subscription information in the authorization JWT. Restrict features on the backend based on subscription information.

Custom trigger: Use GraphQL method to return the subscription of the current user

Optional: You can cache the most recent subscription information on your backend

How do I test monetization?

You can create a mock subscription using our GraphQL API to test your app’s logic. You can set the subscription to the different tiers of your app to test the upgrade/downgrade flow, block screens, etc.

Mock subscriptions only apply to the specific app and account that created them, so they will not affect any of your existing customers. If you do not remove the mock subscription explicitly, it will disappear after 24 hours.

What happens if the payment from an account fails?

When a payment method fails on a renewal date, the account will have a 45-day grace period to change the payment method or resolve the current issue. The app will continue to work during those 45 days.

After the grace period ends, the account's app will stop working and get a webhook for canceling the subscription if they have not added a valid payment method. The payment method failure may occur on the renewal date because of a chargeback.


Did this page help you?