Platform Integration

How to integrate Slootly with each messaging platform.

Info

The Slootly SDK is platform-agnostic. The same methods work across all platforms. This guide covers platform-specific details like user ID extraction and checkout link delivery.

Telegram

User ID

Telegram provides the user ID via from.id in the Bot API update object. Always convert to string.

SourceAccess PathExample
Bot APImessage.from.id123456789
Inline queryinline_query.from.id123456789
Callback querycallback_query.from.id123456789

Sending Checkout Links

typescript
// node-telegram-bot-api
bot.on('message', async (msg) => {
  const userId = msg.from.id.toString();
  const sub = await gate.check(userId, 'telegram');

  if (!sub.active) {
    const url = gate.checkoutUrl(userId, 'pro', 'telegram');
    bot.sendMessage(msg.chat.id, 'Upgrade to Pro:', {
      reply_markup: {
        inline_keyboard: [[
          { text: 'Subscribe to Pro - $9.99/mo', url }
        ]]
      }
    });
  }
});

Checkout links open in the device browser. After payment, the success page includes a deep link back to the bot.

Grammy.js Example

typescript
import { Bot } from 'grammy';
import { Slootly } from '@slootly/sdk';

const bot = new Bot(process.env.BOT_TOKEN);
const gate = new Slootly('sk_live_...');

bot.command('premium', async (ctx) => {
  const userId = ctx.from.id.toString();
  const sub = await gate.check(userId, 'telegram');

  if (sub.active && sub.plan === 'pro') {
    await ctx.reply('You already have Pro access!');
  } else {
    const url = gate.checkoutUrl(userId, 'pro', 'telegram');
    await ctx.reply('Get unlimited access with Pro:', {
      reply_markup: {
        inline_keyboard: [[
          { text: 'Subscribe - $9.99/mo', url }
        ]]
      }
    });
  }
});

Discord

User ID

Discord provides the user ID via the interaction object.

SourceAccess PathExample
Slash commandinteraction.user.id987654321012345678
Messagemessage.author.id987654321012345678
Button clickinteraction.user.id987654321012345678

Sending Checkout Links

typescript
// discord.js v14
import { Client, SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
import { Slootly } from '@slootly/sdk';

const gate = new Slootly('sk_live_...');

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName !== 'premium') return;

  const userId = interaction.user.id;
  const sub = await gate.check(userId, 'discord');

  if (sub.active && sub.plan === 'pro') {
    await interaction.reply({
      content: 'You already have Pro access!',
      ephemeral: true,
    });
  } else {
    const url = gate.checkoutUrl(userId, 'pro', 'discord');
    const row = new ActionRowBuilder().addComponents(
      new ButtonBuilder()
        .setLabel('Subscribe to Pro - $9.99/mo')
        .setStyle(ButtonStyle.Link)
        .setURL(url)
    );

    await interaction.reply({
      content: 'Unlock unlimited features with Pro:',
      components: [row],
      ephemeral: true,
    });
  }
});

WhatsApp

User ID

WhatsApp Cloud API provides the user ID as wa_id.

SourceAccess PathExample
Cloud APImessages[0].from15551234567
Webhookcontacts[0].wa_id15551234567

Sending Checkout Links

typescript
// WhatsApp Cloud API
import { Slootly } from '@slootly/sdk';

const gate = new Slootly('sk_live_...');

async function handleMessage(from: string, phoneNumberId: string) {
  const sub = await gate.check(from, 'whatsapp');

  if (!sub.active) {
    const url = gate.checkoutUrl(from, 'pro', 'whatsapp');

    await fetch(
      `https://graph.facebook.com/v18.0/${phoneNumberId}/messages`,
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${process.env.WHATSAPP_TOKEN}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          messaging_product: 'whatsapp',
          to: from,
          type: 'interactive',
          interactive: {
            type: 'button',
            body: { text: 'Upgrade to Pro for unlimited access' },
            action: {
              buttons: [
                { type: 'url', title: 'Subscribe', url }
              ]
            }
          }
        }),
      }
    );
  }
}

Slack

User ID

SourceAccess PathExample
Events APIevent.userU0123456789
Slash commanduser_idU0123456789
Block actionuser.idU0123456789

Sending Checkout Links

typescript
// Slack Bolt
import { App } from '@slack/bolt';
import { Slootly } from '@slootly/sdk';

const gate = new Slootly('sk_live_...');
const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
});

app.command('/premium', async ({ command, ack, respond }) => {
  await ack();

  const userId = command.user_id;
  const sub = await gate.check(userId, 'slack');

  if (sub.active && sub.plan === 'pro') {
    await respond('You already have Pro access!');
  } else {
    const url = gate.checkoutUrl(userId, 'pro', 'slack');
    await respond({
      blocks: [
        {
          type: 'section',
          text: {
            type: 'mrkdwn',
            text: 'Unlock premium features with Pro:',
          },
          accessory: {
            type: 'button',
            text: { type: 'plain_text', text: 'Subscribe - $9.99/mo' },
            url,
          },
        },
      ],
    });
  }
});

Custom Platform

Use the custom platform for web apps, CLI tools, or any platform not listed above. You define the user ID format.

typescript
// Web app example
const sub = await gate.check(user.email, 'custom');
const url = gate.checkoutUrl(user.email, 'pro', 'custom');

Cross-Platform Identity Linking

Slootly can link multiple platform identities to a single subscriber. If a user pays on Telegram, they can link their Discord account and get Pro features there too without re-subscribing.

Linking is handled through the Slootly hosted checkout page. When a subscriber visits the checkout page from a new platform, Slootly detects the existing subscription and offers to link the accounts.

Tip

Identity linking is available on the Pro plan and above. On the Free plan, each platform identity is treated as a separate subscriber.