How to Add a Referral System to Your Bot in 2 Minutes
A referral program is when your users bring you new users, and you pay them for it. Sounds simple. Usually it ends with a developer spending two weeks writing code generation, a balance table, anti-fraud checks and a payout admin panel — then another month fixing all of it.
Graspil already has all of that built in. There are really only two things to do: connect your bot and turn on the referral program. A minute each — you’ll spend longer reading this article than actually setting it up.
Why bother with a referral system at all
Short version: it’s the cheapest acquisition channel there is.
- A referral arrives with a friend’s recommendation already attached — trust is baked in, and conversion to paying tends to be higher.
- You pay for results, not for impressions. No “burned the budget on ads, got a pile of bots” moments.
- Referrers stick around longer: someone who’s brought in five friends has a much higher bar for leaving your bot.
- It compounds on its own. One happy user → three new ones → each with their own link.
Obvious, really. Moving on.
What you get out of the box
So you can appreciate the scale of the disaster you won’t have to code:
| Feature | What it does |
|---|---|
| Codes and links | A unique code and a ready-made link t.me/bot?start=... for every user — generated by the platform |
| “Who brought whom” tracking | The referrer → referral link is written automatically on /start via the link |
| Bots and Mini Apps | Works with regular bots and Telegram Mini Apps alike — tags are parsed by the same rules |
| Reward rules | Percentage of a payment, a fixed bonus per referral, an external reward — with conditions on the event’s value |
| Multi-currency | Balance is tracked separately per currency, no forced conversion |
| Hold period | An accrual is “frozen” for N days — in case of refunds |
| Payouts | Manual, via webhook, through popular payment providers, or automatically on a schedule |
| Ready-made automation | A referral cabinet inside your bot — pulled from the catalog, zero code |
| Stats | Funnel, top referrers, accrual and payout dynamics |
| Referral reports | Referral data is available in the report builder: you can build a report for just the users who came through the referral program and compare them to everyone else |
| Flexible API | If our built-in scenarios don’t fit — codes, accruals, balances and payouts are all available via API, so you can build your own logic |
And the important bit: you can connect Graspil’s referral system even if you already have your own. It then runs in observe mode and just gives you analytics, without touching your existing logic.
Connecting the bot
If your bot is already in Graspil — skip this section.
There are four ways to connect, but for our purposes the simplest one is enough:
Auto-connect (MTProto). Paste in your bot token and the system takes it from there. Works with any bot or no-code builder, nothing to change in your code, and it collects slightly more data than the other methods.
Don’t want to hand over the token? There’s API connection: a single HTTP request from your bot that sends us updates. About five minutes of a developer’s time, but the token stays with you.
First, sort out the start parameter
This is the one place worth slowing down for. It’s the only step where you can hurt yourself and have to redo everything later.
What the start parameter is
Telegram gives you exactly one way to pass data into a bot on launch — a deep link:
https://t.me/YourBot?start=YOUR_DATA_HERE
One string, 64 characters max. That’s it. Both your UTM tags and your referral code have to fit through this same narrow door.
Turn off simple mode
By default, every new bot has simple mode enabled for start parsing. It takes whatever’s in the parameter as-is, as one solid chunk:
| start= | Parameter | Value |
|---|---|---|
docs |
none | docs |
For a referral system, that means the entire start value is treated as the referral code. No UTM, no source, no campaign — just the code. Someone opens ?start=kT7xQm2p from a Telegram channel and you’ll know who referred them, but you’ll have no idea where they actually came from.
So: go to “My bots” → the bot in question → “UTM tags” (start processing rules) and turn simple mode off.
Decide on a link format up front
Full mode parses the string using two separators: a parameter separator (splits the string into pairs) and a value separator (splits each pair into key and value).
For example, with _ as the parameter separator and - as the value separator, the string
?start=ref-kT7xQm2p_source-tgchannel
parses into a clean table:
| Parameter | Value |
|---|---|
| ref | kT7xQm2p |
| source | tgchannel |
So one link carries both the referral code and a UTM source tag. Later, in reports, you’ll be able to say not just “John brought in 40 people” but “John brought in 40 people, 30 from his channel and 10 from DMs.”
Three things worth deciding before launching the program, not after:
- Which parameter holds the referral code.
refby default — keep it unless you have a reason not to. Latin letters, digits and_are allowed. - Which separators to use. Remember the 64-character limit: long, fancy separators eat into the space you have for actual data.
- Which UTM tags travel alongside the referral code. Usually
sourceis enough.
💡 The rules page has a live preview: type in sample links and see instantly how the system will parse them. Don’t skip this — you won’t want to redesign your link format after it’s already in a thousand users’ hands.
If simple mode is still on, Graspil will flag it right on the referral program activation screen. We tried to have your back here.
Turning on the referral system
Find the “Referral program” section in your dashboard. It’s off by default — hit activate.
Pick a mode
Manage. The platform generates the codes and links itself, calculates accruals, tracks balances and runs payouts. Pick this if you don’t have a referral program yet — it gives you the full feature set and requires no code on your side.
Observe. We just watch what codes come in through ?start=, and record the transitions and the “who brought whom” link. Your bot generates the codes, and there are no accruals. Pick this if you already have your own referral system and just want analytics on top of it.
The mode can be changed in settings at any time, and the accumulated history of transitions is preserved. So if you’re unsure, start with Observe and switch later.
One nuance: for the system to calculate rewards, it needs to know who owns a code. In manage mode this happens automatically. In observe mode, there are three ways:
- turn on “Parameter value is the referrer’s Telegram ID” and put the referrer’s Telegram ID itself in the link, not a code — then the owner of the transition is known instantly, no code-to-user mapping layer required;
- report code ownership in bulk via the API,
POST /v1/referral/set-code-owners— works both ahead of time and retroactively (all past transitions through that code get recalculated to the referrer); - directly mark a user as a referral via
POST /v1/referral/mark-referral.
Remaining activation settings
- Start parameter name — the one we thought through above. There’s a live preview of the referral link right there too.
- When to register a referral — on first bot launch (the main case) and/or on repeat launches and returns after being blocked.
Hit “Activate program” and the menu expands into subsections: Overview, Settings, Referrers, Referrals, Accruals, Payouts, Stats.
Bonus: a referral cabinet with zero code
The referral system can count money just fine, but you still need to show it to your users somehow. And that’s usually where “let’s write a /me command” starts.
Don’t. Open the Automations catalog and grab the ready-made “Referral Cabinet” template.
What it does out of the box:
- Fires on an event you choose — a
/meor/balancecommand, for example. - Fetches the referrer’s code and link (“Get code and link”) — creates one if it doesn’t exist yet.
- Pulls the balance (“Get balance”) — available, on hold, paid.
- Sends the user a message roughly like this:
🎁 Your referral cabinet
🔗 Code: kT7xQm2p
Link: https://t.me/YourBot?start=kT7xQm2p
👥 Referred: 12
💰 Available for payout: 1400
- Below the message — a “Request payout” button that continues the flow, calls “Request payout”, and replies with a confirmation.
After importing, there’s exactly one thing to do: pick the trigger event and publish. The payout button wires itself up to your bot automatically.
From there you can tweak the template like any other automation: add a “Register referrer” step to the welcome message, add a condition to only show the payout button when the balance is above zero, wire up multilingual texts — the language switcher inside the message block works here too.
What to pay for, and how to pay it
This is the meatiest part, but it’s still all done with clicks.
Reward rules
Settings → Reward rules. There are presets — % of payments, Fixed per referral, Extend service, Custom field — grab one and adjust it.
A rule reads like a sentence: for which event → how much to accrue → what else to do.
For which event. Any event your bot already reports to the platform: a payment, a signup, completing a step. The same list used in reports.
Extra conditions on the event value. A numeric filter: accrue only if value ≥ value_min, ≤ value_max, or = value_eq. The classic case: “10% of payments, but only for orders over 1000.”
How much to accrue — three reward types:
| Type | How it’s calculated |
|---|---|
| Fixed | A set amount in the currency you choose — 100 coins per referral payment |
| Percent | A percentage of the event’s value. Currency is inherited from the event itself, no need to pick one |
| External | The platform doesn’t calculate an amount at all, it just fires your webhook. For cases like “extend the subscription by 7 days” — nothing measured in money |
Hold window, in days. How long an accrual sits in “on hold” status before it becomes available for payout. If you offer 14-day refunds, set it to 14 and sleep easy.
Effects — what else to do when an accrual happens:
- Webhook — a POST to your URL with a templated body and variable substitution:
{{referrer_id}},{{amount}},{{event_value}}and more. - Custom field — increment (
inc) or set (set) a custom field on the referrer’s profile. Handy if you want to keep an accumulated balance right in the user’s profile and use it for broadcast segments.
Priority. More than one rule can match the same event — different rates for different order sizes, say. Rules apply in ascending priority order; drag to reorder.
Payouts
Settings → Payouts.
Manual. You transfer the money however’s convenient for you, then mark the payout as “Paid” or “Failed” (with a comment) in the system. The platform keeps the ledger, you keep the wallet.
Webhook. When a payout is triggered, we send a POST to your URL along the lines of “credit X in currency Y to user Z.” Your server credits it and returns 2xx — the payout gets marked paid. Return an external_ref and we’ll store it as your transaction ID for reconciliation. A good fit if you have an in-house wallet or your own payment stack.
Payment providers. Payouts through popular payment services and cryptocurrency connect as a separate method — check your payout settings for the current list.
🛠 Don’t see the provider you need? Write to support. We’ll add it within a day.
Auto-payouts — a separate mechanism, toggled on: a schedule (monthly or every N days), a default method, and per-currency thresholds (“only pay out once at least 5000 ₽ is available”). Manual payouts and API payouts always work, regardless of the schedule.
You can trigger a payout from a referrer’s card, from the Payouts section, via the API POST /v1/referral/payout, or with a button inside an automation.
Lifecycle:
Requested → Processing → Completed
↘ Failed (amount returns to the balance)
What happens to the balance
The balance is tracked separately per currency and made up of four pieces:
| What | Means |
|---|---|
| Available | Approved accruals not tied to a payout. Can be paid out right now |
| Reserved | Already included in a payout that’s currently in progress |
| On hold | The hold period hasn’t passed yet |
| Paid | Total across all successful payouts |
An accrual travels the route: On hold → Approved → In payout → Paid, with branches for Reversed (a compensating accrual) and Cancelled.
Checking the results
Overview — a 30-day summary: total referrers, referrals brought in, active rules, accruals; balances by currency; a funnel of “new users → trigger event → accruals → payouts”; day-by-day dynamics; top 5 by earnings and by number of referrals.
Referrers — a list with filters (period, currency, “has available balance”, minimum referrals), sortable by earnings, with export. From a referrer’s card: their link and a payout button.
Accruals and Payouts — a full ledger with statuses. Every unit of currency is accounted for, and if something goes wrong, you can see exactly what.
But the interesting part starts here. Every accrual is written to analytics as its own event, and referral data plus the UTM tags from the start parameter are available in the report builder. That means you can build more than just “how much we handed out” — actual product reports:
- Referral cohorts vs. everyone else — referred users’ retention is almost always higher, and it’s nice to see that in numbers.
- Funnel by referral link source — if you split
refandsourceinto separate parameters (as we talked about earlier), you can see which channels your referrers actually bring paying users from, and which just bring traffic. - Program economics — how much revenue referrals generated versus how much you paid referrers to get them. You can raise or lower a rule’s payout based on that, instead of a gut feeling.
- Trends by rule — which rule is actually pulling its weight, and which one is just giving money away.
What if we ever want to move to our own or a different system?
A fair question, and one worth asking any service before you hand it your referral program. Honest answer: you can leave, and your data leaves with you.
Everything the system has accumulated is available through the API:
- Codes and their owners — which user owns which code.
- Referrals — who brought whom, the full list.
- Accruals — the entire ledger, with amounts, currencies, statuses, and which rule triggered each one.
- Balances — available, on hold, paid, per currency.
- Payout history — what, when, by which method, and with which external transaction ID.
Plus a referrer export straight from the interface.
So pulling everything out and loading it into your own database is an evening’s script, not a negotiation with support. We don’t put a lock on your data: if Graspil ever stops being the right fit, you leave with the entire history of your program intact. That’s how it should work, really.
Wrapping up
The whole checklist fits in six steps:
- Connected the bot with a token.
- Turned off simple mode for start parsing and settled on a link format.
- Activated the referral program in
managemode. - Created a reward rule.
- Picked a payout method.
- Imported the “Referral Cabinet” from the automations catalog.
The only step worth spending real time on is the second one. Redoing a link format hurts; everything else can be changed in settings whenever you like.
Still have questions about setup, or need a payout method that isn’t there yet — write to support.

