What you'll build
By the end of this guide, you'll have a single leave request form that routes itself to whichever manager an employee names, no fixed approval hierarchy required. Every request gets an AI-generated coverage check flagging schedule conflicts before anyone reviews it, and Status changes automatically trigger the right email to the employee. People Ops works from an internal Kanban pipeline with filtered views for what's pending, approved, rejected, and unpaid.
When to use this
Your company still runs leave requests over email, and approvals get buried in someone's inbox for days
You don't have a fixed reporting hierarchy in your HR system, so "route to the employee's manager" needs to work off whatever email the employee provides, not a predefined org chart
HR wants a private, internal read on whether a request overlaps with other approved leave before anyone signs off on it
You need one place to see approved leave by date range, without exporting spreadsheets every time someone asks
Part 1 — Build the leave request form
This is the only form in the workflow. Employees fill out the public section when they submit a request; Status, Assignee, and Internal notes are admin-only and live on the same record, so People Ops reviews everything from one place instead of a separate system.
1. Open Magic Create: From your Formaloo homepage, click Magic Create. Paste the prompt below, then click Create.
Create a single-page leave request form for employees. Public fields: full name (short text), work email address (email field), department (dropdown: Engineering, Sales, Marketing, Support, Finance, HR, Operations, Other), leave type (dropdown: Vacation, Sick leave, Personal, Bereavement, Parental leave, Unpaid leave), start date (date field), end date (date field), reason for leave (long text, required), reviewing manager's email address (email field). Also add a hidden statement field titled "Date warning" that reads "Your end date is before your start date. Please double-check before submitting." Add these admin-only fields: Status as a dropdown with options Submitted, Awaiting manager review, Approved, Rejected; an Assignee field titled Assignee; and Internal notes as a long text field.
2. Verify your fields: Your form should now look like the table below. Magic Create will have generated most of this structure automatically. Open each field's settings and check that the field ID matches exactly, since logic, emails, and the PDF template all reference these IDs.
Field (question form) | Field ID | Type | Section |
What's your full name? |
| Short text | Public |
What's your work email address? |
| Public | |
Which department are you in? |
| Dropdown | Public |
What type of leave are you requesting? |
| Dropdown | Public |
When does your leave start? |
| Date | Public |
When does your leave end? |
| Date | Public |
What's the reason for your leave request? |
| Long text, required | Public |
What's your manager's email address? |
| Public | |
Date warning |
| Statement, hidden by default | Public |
Status |
| Dropdown: Submitted / Awaiting manager review / Approved / Rejected | Admin only |
Assignee |
| Assignee | Admin only |
Internal notes |
| Long text | Admin only |
📖 See what are admin-only fields and how they help for how Status, Assignee, and Internal notes behave differently from the fields above them.
3. Add the coverage check field: Click Add field and choose AI Analysis. It arrives admin-only by default. Give it the title "Coverage check" and field ID coverage_check, then open its prompt box and write: "Based on @department, @leave_type, @start_date, and @end_date, check whether this request overlaps with other already-approved leave in the same department. Flag any overlap or blackout-period conflict in one short paragraph, or state that there's no conflict." Use the @ menu to insert each field rather than typing field names from memory.
Note: The AI Analysis field is available on the Business and Enterprise plans. It runs automatically on every submission, there's no separate step to trigger it, and it always stays admin-only, so the employee never sees it.
💡 Want the full picture of how this field behaves, including why its output can arrive slightly after the rest of the submission? How to generate AI analysis on form submissions without showing it to respondents in Formaloo covers it in full.
4. Publish the form: Click Publish in the island bar at the top of the editor.
Part 2 — Create your email templates
Three templates fire automatically as the request moves through the workflow: a review request to the manager, an approval notice to the employee, and a rejection notice to the employee. Build all three now so they're ready to attach to logic in Part 4.
1. Open the email template editor: Click your profile icon → Apps & integrations → Custom email templates → Add new template.
2. Build each of the three templates: Give each a name and subject line, then clear the body field, add an AI block, and paste the prompt below it. Save each one before moving to the next.
Manager review request (to the reviewing manager) Subject: New leave request from @employee_name needs your review AI prompt: "Write a clear, efficient email to a manager letting them know a team member has submitted a leave request that needs their review. Reference the employee's name (@employee_name), leave type (@leave_type), start date (@start_date), end date (@end_date), and reason (@reason) if one was given. Keep the tone neutral and businesslike, this is a routine internal notification, not a sales pitch. State plainly what's being asked: review the request and let HR know the decision. 3-4 sentences, under 80 words." Design: white background, single centered column, max-width 560px, Inter/system-ui font. Present the leave details as a compact key-value data table rather than inline prose. Muted footer in #999 with a placeholder for the company name.
Leave approved (to the employee) Subject: Your leave request has been approved AI prompt: "Write a warm, brief confirmation email to an employee whose leave request was approved. Reference their leave type (@leave_type), start date (@start_date), and end date (@end_date). Keep it upbeat but short, and add one line reminding them to hand off any pending work before they're out. Friendly, professional tone. 3-4 sentences, under 70 words." Design: same layout as above, with a small green "Approved" status badge near the top and the dates shown in the same compact data table.
Leave rejected (to the employee) Subject: An update on your leave request AI prompt: "Write a calm, respectful email telling an employee their leave request was not approved. Reference their leave type (@leave_type) and requested dates (@start_date, @end_date) without dwelling on them. Avoid harsh or bureaucratic language, and invite them to reach out to their manager or HR to discuss timing or alternatives. Tone: empathetic, non-defensive, never apologetic to the point of sounding uncertain. 3-4 sentences, under 70 words." Design: same layout, with a muted amber (not red) "Not approved" status badge, so the two decision emails feel like one consistent family.
📖 See how to create and send custom email templates for the full template editor walkthrough, including how AI can generate the HTML design from a prompt.
Part 3 — Create your PDF template
One PDF template captures the outcome once a decision is made: employee and manager details, the leave dates and reason, the AI-generated coverage check, and the final status. Logic generates it automatically in Part 4. You're just building it here.
1. Open the PDF template editor: Click your profile icon → Apps & integrations → Custom PDF templates → Add new template.
2. Switch to HTML view and paste the template below: This uses answer piping to pull in field values, including @rowid for the reference number and @created_at for the submission date. It's laid out in three sections: Employee, Leave details, and Internal review, the last of which holds the Status badge, the reviewer, the coverage check, and internal notes, everything the employee's version of this data should never include.
Leave request decision record
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Leave Request Decision Record</title> <style> * { box-sizing: border-box; } body { margin: 0; padding: 0; background: #ffffff; font-family: 'Inter', system-ui, -apple-system, sans-serif; color: #1a1a1a; } .page { max-width: 760px; margin: 0 auto; padding: 60px 72px; } /* Header */ .header { margin-bottom: 40px; } .header h1 { font-size: 22px; font-weight: 600; margin: 0 0 12px 0; color: #1a1a1a; } .header-meta { display: flex; gap: 32px; font-size: 12px; color: #999999; } .header-meta span strong { color: #555555; font-weight: 500; } /* Status badge */ .status-badge { display: inline-block; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; padding: 4px 11px; border-radius: 20px; background: #f2f2f2; color: #666666; } /* Sections */ .section { margin-bottom: 32px; } .section-title { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: #aaaaaa; margin-bottom: 14px; } /* Field grid */ .field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 32px; } .field-full { grid-column: 1 / -1; } .field { padding: 10px 0; border-bottom: 1px solid #ececec; } .field-label { font-size: 11px; color: #999999; margin-bottom: 4px; } .field-value { font-size: 14px; color: #1a1a1a; line-height: 1.5; } /* Internal note inset */ .internal-block { background: #f9f9f9; border-left: 3px solid #dcdcdc; padding: 14px 18px; font-size: 13px; color: #555555; line-height: 1.6; border-radius: 0 4px 4px 0; } /* Footer */ .footer { margin-top: 56px; padding-top: 20px; border-top: 1px solid #ececec; display: flex; justify-content: space-between; font-size: 11px; color: #999999; } </style> </head> <body> <div class="page"> <div class="header"> <h1>Leave Request Decision Record</h1> <div class="header-meta"> <span><strong>Reference:</strong> LR-@rowid</span> <span><strong>Submitted:</strong> @created_at</span> </div> </div> <div class="section"> <div class="section-title">Employee</div> <div class="field-grid"> <div class="field"> <div class="field-label">Full name</div> <div class="field-value">@employee_name</div> </div> <div class="field"> <div class="field-label">Work email</div> <div class="field-value">@employee_email</div> </div> <div class="field"> <div class="field-label">Department</div> <div class="field-value">@department</div> </div> <div class="field"> <div class="field-label">Reviewing manager</div> <div class="field-value">@manager_email</div> </div> </div> </div> <div class="section"> <div class="section-title">Leave details</div> <div class="field-grid"> <div class="field"> <div class="field-label">Leave type</div> <div class="field-value">@leave_type</div> </div> <div class="field"> <div class="field-label">Duration</div> <div class="field-value">@start_date → @end_date</div> </div> <div class="field field-full"> <div class="field-label">Reason</div> <div class="field-value">@reason</div> </div> </div> </div> <div class="section"> <div class="section-title">Internal review</div> <div class="field-grid"> <div class="field"> <div class="field-label">Status</div> <div class="field-value"><span class="status-badge">@status</span></div> </div> <div class="field"> <div class="field-label">Reviewed by</div> <div class="field-value">@assignee</div> </div> <div class="field field-full"> <div class="field-label">Coverage check (AI-generated, internal use only)</div> <div class="internal-block">@coverage_check</div> </div> <div class="field field-full" style="border-bottom: none; margin-top: 14px;"> <div class="field-label">Internal notes</div> <div class="field-value">@internal_notes</div> </div> </div> </div> <div class="footer"> <span>Confidential — internal HR record, not for external distribution</span> <span>@form_title</span> </div> </div> </body> </html>Kept as HR's audit record for every decision: employee and manager details, leave type and dates, the reason, the coverage check, and the final status, all in one document.
📖 See how to create PDF templates to turn responses into documents for the full editor walkthrough.
Part 4 — Automate routing and approvals with advanced logic
This is where the workflow comes together. One set of rules assigns every new request to People Ops, emails the reviewing manager, warns the employee about mismatched dates, and, once a decision is made, emails the employee and generates the decision PDF. Magic Logic can build all of it from a single prompt.
1. Open Magic Logic: In the form editor, open Advanced logic from the form settings panel on the right side, then go to the Logic tab. Click Magic Logic in the top right corner.
💡 Want a rule to fire the moment a request is first submitted, versus one that reacts whenever the record changes later? What is On Submit logic and how it works and what is On Update logic and how it works cover the difference.
2. Describe the full workflow in one prompt: Paste the prompt below and click Generate rules.
When the form is submitted: assign the record to the People Ops team, set status to "Awaiting manager review," and send the "Manager review request" email to the manager email field. When end date is before start date, show the Date warning field, which is hidden by default. When status is changed to "Approved": send the "Leave approved" email to the employee email field, and generate the leave request decision PDF. When status is changed to "Rejected": send the "Leave rejected" email to the employee email field, and generate the leave request decision PDF.
3. Review and approve each rule: The AI previews every rule it built. Approve, redo, or cancel each one individually, then confirm the correct email template is selected for each "Send email" action and the correct PDF template for each "Generate PDF" action.
4. Save your logic: Click Save in the top right corner.
Note: The coverage check field generates after the response row is created, so if you also want it piped into an On Submit email, the value can come through blank. That's why the decision PDF, which does reference it, is generated On Update instead, once People Ops has already had time to review the request.
📖 See what is logic in Formaloo and how to add advanced logic to your form for more on how these rules work. For the full list of supported variables, see how to dynamically pull form data into custom emails, PDFs, and AI prompts.
Part 5 — Set up the People Ops pages
No client portal is needed here. Employees submit through the open form link, and the only people who ever need restricted access are your own People Ops team, working from pages inside the same project.
1. Create the People Ops team: In your workspace settings, go to Members, create a team called People Ops, and add whoever handles leave requests. This is the team the Assignee field routes to.
💡 Want to route work to a group instead of naming one person every time? What is a team in Formaloo and how to manage it covers setting teams up. And for the Assignee field itself: what is the Assignee field in Formaloo and how to use it.
2. Build the All requests page: Add a Kanban board grouped by Status, with columns for Awaiting manager review, Approved, and Rejected. Dragging a card between columns updates the record's Status and triggers the matching logic automatically.
📖 See how to create a Kanban board for the setup.
3. Build the filtered views: Add My assigned requests, a table filtered to Assignee = logged-in user, sorted newest first. Add Awaiting manager review, filtered to Status = Awaiting manager review, sorted oldest first. Add Approved leave, filtered to Status = Approved, grouped by month and sorted by start date. Add Rejected requests, filtered to Status = Rejected. Add Unpaid leave requests, filtered to Leave type = Unpaid leave, since it has payroll implications the other categories don't.
📖 See how to sort and filter your submissions data for the underlying filters used on these pages.
4. Build the department chart: Add a bar chart of approved leave grouped by department, for spotting coverage gaps before they become a problem.
5. Restrict the group to People Ops: On each page above, open the three-dot menu → Access, and restrict it to internal users on the People Ops team. Since Status, Assignee, and Internal notes are all admin-only, this keeps the entire review pipeline invisible to anyone outside that team.
📖 See how to restrict users' access to pages in your portal for the full walkthrough of internal team-based page access.
What you now have
You now have a leave request workflow that routes itself to whatever manager an employee names, with no fixed hierarchy to configure or maintain. Every request arrives with an AI-generated coverage check already flagging scheduling conflicts, and a single Status change fires the right email without anyone drafting it by hand. People Ops works from one internal pipeline instead of a scattered inbox, with a permanent decision record for every request.
Ready-to-use templates
Don't build this from scratch — we've already put it together for you.
Employee request workflow — Internal request management built for HR and ops teams. Swap in the leave-specific fields from Part 1 and the same routing pattern applies directly.
Scholarship & grant application with scoring and approval — Automated approval and rejection emails triggered by a status change, the same branching pattern used here for the employee's decision notice.
Job applicant tracking workflow — Status tracking and reviewer assignment from one internal view, structured the same way as the People Ops pipeline in this guide.
Don't have a form yet? Create one in seconds with Magic Create — describe what you need and Formaloo builds the form for you.
What's next
Add a second approval stage for longer leave If long-term or unpaid leave should also need a department head's sign-off, not just the direct manager, this covers stacking a second approval stage on top of the first. → How to build a dual-approval request workflow
Go deeper on the coverage check field This guide covers everything the AI Analysis field can do beyond a single conflict check, including running more than one private read on the same submission. → How to generate AI analysis on form submissions without showing it to respondents in Formaloo
Let employees track their own leave history If you'd rather employees check their own status than wait on an email, this covers the "view only your own data" access pattern a self-serve history page would need. → How to let users view and edit their own data in your portal
Learn more how-tos
See another AI-scored workflow route submissions automatically A different context for the same idea used here: an AI read on a submission driving routing, before a human ever looks. → How to build an AI-powered lead qualification system
Clean up leave records after they're no longer needed Leave requests carry personal details that shouldn't sit in your workspace forever. This covers automatically anonymizing records after a retention period. → How to automatically anonymize records after form submission in Formaloo
See more on routing different emails by condition The same conditional email pattern used here for Approved versus Rejected applies to any workflow with more than one outcome. → How to send and receive conditional email notifications

