Chat-based approvals for internal workflows: a practical setup
Chat-based approvals for internal workflows let teams approve or reject requests from Telegram or email links, using expiring tokens and an audit trail.

Why approvals get stuck in internal teams
Approvals usually do not stall because people are lazy. They stall because the decision is separated from the moment someone can actually make it. A request sits in a tool nobody checks often, or it arrives when the approver is away from their desk, and it quietly becomes “later”.
The most common bottlenecks are simple:
- Waiting on the right person who is busy or traveling
- Unclear status (is it pending, rejected, or just unseen?)
- Missing context (what is being approved, why, and what it costs?)
- Too many back-and-forth questions in separate threads
- No clear owner when the original approver is out
That is where chat-based approvals for internal workflows can help. In plain terms, it means the approver gets a short message in a channel they already use (often Telegram or email) with clear details and two actions: approve or reject. The goal is not to move the whole process into chat. The goal is to let people make small, time-sensitive decisions without hunting for a dashboard.
This works best for low-to-medium risk decisions where speed matters more than a long review. Examples include approving a small purchase, granting access to a shared folder, signing off on a schedule change, or confirming a customer refund within a limit.
It is the wrong tool when the decision needs careful analysis, multiple reviewers, or strict separation of duties. For high-risk actions (large payments, HR actions, vendor contracts), a chat button can create pressure to click quickly, and that is exactly what you do not want.
If you build this kind of flow in a no-code tool like AppMaster, the real win is reducing “approval friction” while still keeping the process controlled, tracked, and easy to understand.
What a chat-based approval flow looks like
A chat-based approval flow is a simple loop: someone asks for permission, the right person answers quickly from wherever they are, and the system records what happened. When it works, it removes the “I didn’t see your ticket” problem without turning approvals into casual, untracked chat.
There are three roles.
- Requester: creates the request (for example, “Approve a $120 software subscription”).
- Approver: decides what to do.
- System: sends messages, applies rules, and saves the final result.
The system can notify approvers in two common places: a Telegram message for fast responses, and an email message for people who live in their inbox. Both should show the same core details, so the approver never has to guess what they are approving.
A typical message includes a short summary, key fields (amount, vendor, reason, cost center), and three clear actions: Approve, Reject, or Ask for changes. “Ask for changes” is useful when the request is close, but missing a detail like a receipt or a project code.
Once the approver chooses an action, the system should do four things immediately:
- Update the request status (for example, Pending -> Approved).
- Notify the requester (and any watchers) of the decision.
- Log an audit record with who, what, and when.
- Block the action from being repeated by accident.
For chat-based approvals for internal workflows, the safest pattern is: show the full context in the message, but make the actual action happen in the system (not “reply YES”). If you build this in AppMaster, the messaging module can deliver Telegram and email notifications, while your backend logic enforces states and records every decision.
Expiring tokens in approval links, explained simply
An expiring token is a short, random code that proves a person is allowed to take one specific action, for a limited time. In chat-based approvals for internal workflows, it’s what makes a Telegram button or an email approval link safe enough to use in daily work.
Think of the token as a temporary “key” that only fits one lock. When you click Approve or Reject, the system reads the token, checks it, and then records the action.
What the token should (and should not) grant
A token in a link should grant exactly one permission: “perform this approval decision for this request.” It should not grant access to the full request history, your account, or anything else.
Good tokens are tied to:
- One request (example: purchase request #1842)
- One approver (or one approver group, if you allow that)
- One action set (approve/reject)
- A clear expiry time
- A clear status (unused, used, revoked)
Expiration, single-use, and revocation
Expiration limits damage if a message is forwarded, a mailbox is compromised, or someone clicks the link days later. A common window is a few hours for urgent items, or 24 to 72 hours for normal work.
Single-use tokens are usually best for approvals. Once used, any second click should be blocked, even if the page is still open. Multi-use tokens can make sense for “acknowledge” actions, but they are risky for approve/reject because they invite double-submits and confusion.
Revocation matters when details change. If the request amount, vendor, or scope is edited, revoke old tokens and issue new ones. Tools like AppMaster can model this as simple fields on the approval record (expires_at, used_at, revoked_at) plus a short business process that validates them before accepting the decision.
When the token is expired or already used
Don’t show a scary error. Show a clear result:
- “This approval link expired. Request a new one.”
- “This request was already approved by Alex at 10:42.”
Then offer one safe next step: send a fresh approval message to the current approver(s), with a new token.
Designing the request message so it is clear and safe
A good approval message lets someone decide in seconds, without opening anything. A bad one makes them guess, or worse, pushes sensitive details into chat history. For chat-based approvals for internal workflows, aim for “enough to decide” and “not enough to leak.”
Start with a consistent summary that reads well on a phone. Put the decision-critical facts near the top, then the details, then the action buttons or links.
What to include (minimum)
Approvers usually need just a small set of fields to say yes or no:
- Who is requesting (name + team)
- What is being requested (short title)
- Cost or impact (amount, plan tier, hours, or stock units)
- When it is needed (due date or urgency)
- Why it is needed (one sentence)
Example (Telegram or email): “Purchase request: Bluetooth barcode scanner, $189, needed by Feb 2, reason: replace broken unit in warehouse.”
What not to include
Assume messages get forwarded, screenshotted, and stored. Keep secrets out of both the message text and the URL.
Do not include full card numbers, bank details, passwords, private customer data, or internal comments that are meant only for finance or HR. If you need to reference something sensitive, include a short label like “Vendor quote: on file” rather than the quote itself.
For approval links, keep the token opaque and short-lived. Do not put readable data (like amount or user email) into the link. Put those in the message body instead.
Finally, add a safe fallback so people can still approve the right item if the link expires or looks suspicious: include a Request ID (for example, PR-10438) and a simple “Open in app” option. If you build this in AppMaster, treat the Request ID as the anchor: it is what the approver can search for in your internal portal to confirm they are acting on the right request.
Approval rules and states to define before you build
Before you send the first Telegram or email approval request, decide what “done” means. Chat-based approvals for internal workflows feel simple on the surface, but they break when the workflow has no clear states.
Start with a small set of request states you will store in your database. Keep them boring and predictable, so every person and every report reads the same way.
- Draft (optional): created but not sent
- Submitted: sent to approvers
- Pending: waiting on at least one decision
- Approved or Rejected: final decision recorded
- Cancelled: request withdrawn before final decision
Next, define who is allowed to approve. Don’t rely on “whoever sees the message first.” Tie approval rights to a role or team, and decide what happens when the main approver is out.
A simple rule set to agree on early:
- Primary approver (by role or team)
- Backup approver (when primary is unavailable)
- Requester can cancel (yes/no, and until when)
- Conflict rule (can someone approve their own request?)
If you have multiple approvers, choose one pattern and name it. “Any-of” means the first approval completes the request. “All-of” means every listed approver must approve. Also decide how you handle a rejection in an all-of flow (usually: one rejection ends it).
Finally, write down what happens after approval. Example: an approved purchase request might create a payment task, notify finance, and lock the original request so it cannot be edited. In AppMaster, this maps cleanly to database state changes plus a Business Process that triggers the next steps and notifications.
Step-by-step: build the approve or reject flow
To build chat-based approvals for internal workflows, keep the flow small: one request record, one decision, and a clear audit entry. You can add extra rules later without changing the basic shape.
First, create a single “Request” record with the fields you need to decide: what it is, who asked, who must approve, and the amount or impact. Set status = Pending and save it before you message anyone, so every action has something real to point to.
Next, generate an approval token that expires. Store it in a separate “ApprovalToken” record that references the request and the intended approver, plus expires_at and used_at. This binding matters: it prevents someone from forwarding a message and having a different person approve.
Here’s a simple build order:
- Save the request with
Pendingstatus. - Create two tokens (Approve, Reject) or one token plus an
actionparameter, with a short expiry. - Send a Telegram message and/or email that includes two clear buttons or links.
- On click, validate token, expiry, and approver identity; then apply the decision.
- Notify the requester and write an audit entry.
When handling the click, treat it like a transaction: check “not expired” and “not used,” confirm the token matches both the request and the approver, then update the request to Approved or Rejected. Save who acted, when they acted, and what they chose.
In AppMaster, this fits well with a Data Designer model (Request, ApprovalToken, ApprovalAudit) and a Business Process that runs the validation and updates. Use built-in messaging modules for Telegram and email so the same process can notify both channels.
Finish by sending two short messages: one to the requester (“Approved by Maria, 10:42”) and one to the approver (“Recorded, token closed”). That feedback reduces repeat clicks and support pings.
Make actions auditable without making things complicated
An audit trail is not just for compliance. It is how you answer basic questions later: Who approved this, when, from where, and based on what information? For chat-based approvals for internal workflows, the key is to log a few facts consistently, not everything.
Start by deciding what counts as one “approval action”. Usually it is a single click on Approve or Reject from a Telegram message or an email approval link. Each action should create one immutable record.
Log the same core fields every time:
- Timestamp (server time, plus optional user timezone)
- Actor (the authenticated user, and their role at that moment)
- Channel (Telegram, email, web, mobile)
- Decision (approve/reject) and optional reason/comment
- Request snapshot (the important fields as they were when the user decided)
Reasons for rejection are worth collecting, but keep it simple: a short text field plus a small set of optional tags (for example “budget”, “missing info”, “policy”). If you require a reason, do it only for Reject, and cap the length so people actually write something useful.
To handle disputes, show a readable history on the request: created, submitted, approved/rejected, and any re-submissions. Avoid exposing secrets in the log. Instead of storing full payment details or private notes, store a safe snapshot (vendor name, amount, cost center) and keep sensitive data in its own protected area.
Reporting can stay lightweight. The useful signals are:
- Who approves most often
- Average time to decision
- Top rejection reasons
- Where requests sit the longest
If you build this in AppMaster, a practical approach is a dedicated “ApprovalActions” table in the Data Designer and a single Business Process step that writes the log record before changing the request state. This keeps history reliable even when the message is forwarded or a token link expires.
Common mistakes and traps
Most chat-based approvals for internal workflows fail for boring reasons: someone clicks a link twice, forwards it, or the request changes after the message was sent. You can avoid most of it with a few rules that are easy to enforce.
A classic trap is treating the approval link like a password. If a token can be reused, the same action might be recorded twice. If the link is forwarded, a different person can approve something they were never meant to see.
Another common issue is not binding the token to the intended approver. If your system only checks, “is this token valid?”, then any logged-in user (or even a user with the link) might be able to act. Bind it to both the request and the approver identity, and require login if the channel is not trusted.
Expiration causes problems in both directions. Tokens that never expire become permanent backdoors. Tokens that expire too quickly create a support burden and push people to “work around” the process. Aim for a practical window (like a few hours), and always offer a safe way to request a new link.
Request changes are another source of bad approvals. Someone edits the amount or vendor after the message went out, then the approver clicks “Approve” on an outdated view.
Watch for these symptoms:
- The same token can approve twice (or approve and reject)
- The link works for anyone who has it
- The link never expires (or expires in minutes)
- The action does not check the request version
- Invalid tokens produce a confusing, silent failure
A simple fix set (easy to implement in tools like AppMaster) includes single-use tokens, approver binding, and clear error screens. For example: “This link is expired. Request a new approval message.” That one sentence prevents most panic clicks and shadow approvals.
Security checks that actually matter
Chat-based approvals for internal workflows feel simple because the user just taps Approve. The security work is mostly in the parts they never see: how you create links, validate tokens, and handle edge cases.
Start with the approval link itself. Use HTTPS-only endpoints and treat the token like a password. Keep it out of places that get copied around, such as server access logs, analytics, and chat previews. A practical trick is to avoid logging full request URLs and to store only a short token fingerprint server-side.
Rate limiting is the next big win. Token validation and the final approve/reject endpoint should be protected from guessing and repeated retries. Even if your tokens are long, rate limits stop noisy attacks and also protect you from accidental double-taps.
Some approvals are higher risk than others. For things like vendor payments or access to customer data, require an extra step after the user clicks the link, such as a quick login or MFA. In AppMaster, this can be modeled as a rule in your Business Process: low-risk requests complete with a valid token, while high-risk requests redirect into an authenticated session before the state changes.
Have a clean way to revoke tokens when roles change. If someone moves teams, leaves the company, or loses a phone, you should be able to invalidate all outstanding tokens for that person and for any pending requests they touched.
A few decisions to make upfront:
- Expire tokens quickly (minutes or hours, not days) and make them single-use.
- Decide what happens if an email is forwarded or a Telegram message is shared.
- Handle shared devices by requiring a quick identity check for sensitive actions.
- Prevent replay by recording the first successful use and rejecting the rest.
- Return a safe message on failure (do not reveal if a token is “almost valid”).
Example: if a manager forwards an approval email to a colleague, the system should either block the action or force the colleague to sign in before approving.
Example scenario: approving a small purchase request
Maya, an operations manager, needs a $180 replacement label printer for the shipping desk. She opens the internal “Purchase Request” form, fills in vendor, amount, and a short note, then submits. The request gets a status of Pending and is assigned to her team lead, Jordan.
Jordan receives a Telegram message that is easy to scan: “Purchase request from Maya: Label printer, $180. Needed this week.” Under it are two clear actions: Approve and Reject. Each action is a button or a short command that maps to a single-use, expiring token.
Jordan taps Reject and adds a reason: “Please use the approved vendor list, and attach the quote.” The system immediately does two things. First, it updates the request to Rejected with Jordan’s reason. Second, it notifies Maya in the same channel she used (or by email, depending on your rules) so she can fix and resubmit without guessing what went wrong.
Behind the scenes, you keep a simple audit trail that answers the basic questions without adding paperwork:
- Who decided (Jordan’s user ID)
- What they decided (Rejected)
- When they decided (timestamp)
- Where they decided (Telegram vs email)
- Why (optional text reason)
If someone clicks the Approve or Reject link later, after the token expires, the action does not go through. Instead, they see a clear message like “This action link has expired” and the request stays Pending. That prevents accidental approvals from old messages and keeps your record clean.
This is the kind of flow you can build in a no-code tool like AppMaster using a simple request table, a status field, and a business process that sends Telegram or email actions and writes the audit record.
Next steps: ship a small version and improve it
The fastest way to get value from chat-based approvals for internal workflows is to ship a small version that is safe, measurable, and easy to support. Pick one request type that already causes delays (like small purchases or access requests), and run it with one team first.
Before you launch, do a quick final pass with a short checklist:
- Approval rules are clear (who can approve, when escalation happens, what “reject” means)
- Links expire and can be used only once (token + expiry + “already used” handling)
- Audit fields are captured (who, what action, when, from which channel)
- Error messages are human (expired token, wrong approver, already decided, request not found)
- Notifications are consistent (request received, approved/rejected, and fallback when chat delivery fails)
After week one, measure turnaround time: how long it takes from “requested” to “decided”, plus how often people ignore the message and need a reminder. A simple metric like “median time to approve” makes improvements obvious.
Plan a basic admin view early. It does not need to be pretty, but it must let you search by request ID, requester, and status, and see the full decision history. This is what your ops or finance teammate will use when someone says, “I approved it yesterday, where did it go?”
If you want to build this without heavy coding, AppMaster can help you model the request and audit tables, design the approve/reject logic in a visual flow, and send Telegram or email messages as part of the same workflow. Start small, watch real usage, then add extras like reminders, delegation, and escalation only when the basics are stable.


