Monetize your apps

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

Section 1: 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 needing to set up 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.

In order for you to use the monetization feature, you have to become a vendor. You can do this by submitting this form.

📘

Want to skip to the API reference? Click here.

To support monetization, your app needs to support the following flows:

  • 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

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

Subscriptions

The framework revolves around the concept of a subscription. Each subscription represents 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: unique identifier of the subscription tier
  • Renewal date: date the subscription ends and will renew
  • Is Trial: whether the user is currently in a trial period

App and Subscription Life Cycle

Here is the typical app life cycle:

App installation and trial: Admin installs the app and begins a trial. The trial will have a default plan tier, defined by you. For example, you may want all trial users to have the Pro plan.

Trial end: After 14 days, the app will be disabled or revert to the free plan (if your app supports one).

Payment: Admin pays for the app. They can pay either annually or monthly. monday will handle the payment page, billing, currency conversions, tax, etc. Your app will simply see the subscription object get updated with the correct plan_id that they paid for.

Usage: Based on the subscription information, you should enable the relevant features.

In each step of the life cycle, there are different outcomes. We've prepared a diagram to show the various states that a user could be in. Download it so you can zoom in!

Supporting existing and new customers

Our monetization is built on our new billing infrastructure, which is in gradual release. While this infra is being released, you will need to handle two groups of customers:

  • Supported accounts – can pay for your app
  • Unsupported accounts– will need to pay externally or use a free version of your app

During this transition period, you will need to decide how to handle unsupported accounts. Your app should have logic to prevent double payment. and to migrate customers from one billing system to another. Check out the last section for some tips on doing this.

Checking if account supports monetization

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

Section 2: 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 to create mock subscriptions for testing
  • Webhooks: to send subscription information to your backend, and for custom actions

SDK methods

These are methods 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, and cancel.

A typical use case is when a user wants to use a feature that is 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. This should be used when you want the user to first pay for the app.

If the isInPlanSelection parameter is false, the apps billing section will open instead.

Code example:

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

Session token

Every time your app is loaded, we will generate a session token that is 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 way to get the current subscription.

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 useful 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.

This is a convenience method – you should always verify the subscription details in the session token, because 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

Query to return the subscription object for the current app and account, based on the token being used. Method does not accept any arguments. Returns an array.

If an account has both a mock subscription and a real one, only the mock subscription will be returned.

Fields:

  • plan_id [String] – The subscription’s plan tier (eg, 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 the 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

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

Create a mock subscription for an app, for testing purposes. The mutation will create a mock subscription for the account and app, based on the token you’re using. Returns an app_subscription object. Please refresh your browser while using monday after creating the mock subscription, so that it is shown in your account.

Mock subscriptions are removed after 24 hours, and only 1 mock subscription can be created per account-app pair.

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 have 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, which you can get from the URL
  • partial_signing_secret [String!]: Last 10 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. Returns an app_subscription object.

Required arguments:

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

Webhooks

We also expose subscription information in webhooks from monday to your app. In each of these cases, 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;
})

Section 3: Implementation tips

In this section, we will go over some simple tips and FAQs on 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 and will be shown in our marketplace
  • Description – less than 255 characters
  • Bullet points for plan features (3 recommended, max 5, each bullet is a short sentence, 10 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:

📘

About the fees

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

For example a yearly $55 fee would result in a monthly fee of $4.58, which is not rounded. In this case, the yearly fee should be either $48 or $60 so that the monthly fee would be either $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. In this case, 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 both existing users and new users?

We’ve creating 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:

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 a user accesses 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 backend based on subscription information.

Custom trigger: Use GraphQL method to return the subscription of 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 they are created on, so they will not affect any of your existing customers. If you do not remove the mock subscription explicitly, it will be removed after 24 hours.


Did this page help you?