What you'll build
A portal where agency clients log new requests and see, in real time, how many of their monthly retainer hours have been used. Behind the scenes, an account manager tracks each client's retainer cap and logs hours as work gets done, and Formaloo sends automatic alerts to both the client and the account manager as usage climbs toward the limit. Clients get a self-serve view of their own account instead of asking "how many hours do we have left" over email.
When to use this
You run a retainer-based agency and clients keep asking how many hours they've used this month.
You want requests logged in one place instead of scattered across email and Slack, with a clear status per request.
You're tired of finding out a client blew through their retainer only after the invoice conversation gets awkward.
You manage several client accounts and need one view that flags which ones are approaching their limit before it becomes a problem.
You want clients to have transparency into their own usage without giving them access to anyone else's account.
Part 1 — Build the client retainer account form
This form is internal only. There's no client-facing submission here, it's how your account managers set up each client's monthly retainer and keep the hours-used number current as work gets logged. Every other piece of this workflow reads from this record. The fastest way to build it is with Magic Create.
1. Open Magic Create: From your Formaloo homepage, click Magic Create.
2. Describe the retainer account form: Paste this prompt and click Create: "Build an internal form for an agency to set up and maintain each client's monthly retainer. Include: client company name (short text), the best email to reach the client at (email), monthly retainer hours (number), hours used this cycle (number), retainer status as a dropdown with options Active, Paused, Ended, an assignee field for the account manager who owns the account, and a long text field for internal notes."
3. Verify the fields Magic Create generated: Your form should look like this. Magic Create will have generated most of it. Verify each field and field ID matches the table below exactly, since the formula variable and alert logic in Part 3 depend on these IDs.
Field | Field ID | Type |
What's the client's company name? |
| Short text |
What's the best email to reach this client at? |
| |
How many hours are included in their monthly retainer? |
| Number |
How many hours has this client used this cycle? |
| Number |
What's the retainer status? |
| Dropdown (Active, Paused, Ended) |
Which account manager owns this client? |
| Assignee |
Internal notes |
| Long text |
💡 Want to know exactly what the Assignee field can do, assign to a person, a team, or either? See what is the Assignee field in Formaloo and how to use it.
4. Publish the form: Click Publish in the island bar at the top of the editor.
Part 2 — Build the request log form
This is the form clients use every time they need something from the agency. It's the one form the workflow was built around, so every field on it either helps the account team triage the request or feeds the client's own tracking view later.
1. Open Magic Create: From your Formaloo homepage, click Magic Create.
2. Describe the request form: Paste this prompt and click Create: "Build a client request intake form for an agency portal. Public fields: client company or account name (short text), email address (email), what they need help with (short text), a detailed description (long text), deliverable type as a dropdown with options Design, Development, Content, Strategy, Other, how urgent it is as a dropdown with options Low, Normal, Urgent, why it's urgent (long text), when they need it by (date), and a file upload field for reference files. Also add these admin-only fields: status as a dropdown with options New, In progress, In review, Completed, Blocked, an assignee field, hours logged (number), and internal notes (long text)."
3. Verify the fields Magic Create generated: Your form should look like this. Magic Create will have generated most of it. Verify each field and field ID matches the tables below exactly.
Public-facing fields
Field | Field ID | Type |
What's your company or account name? |
| Short text |
What's your email address? |
| |
What do you need help with? |
| Short text |
Describe the request in detail |
| Long text |
What type of deliverable is this? |
| Dropdown (Design, Development, Content, Strategy, Other) |
How urgent is this? |
| Dropdown (Low, Normal, Urgent) |
Why is this urgent? |
| Long text |
When do you need this by? |
| Date |
Any reference files? |
| File upload |
Admin-only fields
Field | Field ID | Type |
Status |
| Dropdown (New, In progress, In review, Completed, Blocked) |
Hours logged |
| Number |
Assignee |
| Assignee |
Internal notes |
| Long text |
💡 Want internal fields, like status or hours logged, invisible to the client filling out the form? See what are admin-only fields and how they help.
4. Publish the form: Click Publish in the island bar at the top of the editor.
Part 3 — Add the usage formula and alert logic
This part connects the two forms. A formula variable on the retainer account form turns raw hours into a usage percentage, and logic rules use that percentage to decide when to reveal the urgency field on requests and when to send the retainer alert emails.
1. Open Advanced logic on the retainer account form: Open the settings panel on the right side of the form editor and go to the Logic tab.
💡 Want to show, hide, or route fields based on what someone answered? See what is logic in Formaloo.
2. Open the Variables panel: Find the Variables section and click + Add.
3. Create the usage percent variable: Select Formula, give it the ID usage_percent, title it "Usage percent," and set the formula to hours_used/monthly_hours*100.
Note: Formaloo formulas don't support parentheses. This one doesn't need any, since division happens before multiplication either way.
4. Open Magic Logic on the request log form: Open Advanced logic in the settings panel on the right side, go to the Logic tab, and click Magic Logic in the top right corner.
5. Paste the urgency prompt: "If How urgent is this equals Urgent, show Why is this urgent. Hide Why is this urgent by default, and make it required only when it's visible." Click Generate Rules, review the preview, and approve it.
6. Save the logic: Click Save in the top right corner.
7. Add the retainer alert rules on the account form: Back on the retainer account form's Logic tab, click Magic Logic and paste: "If Usage percent is 80 or higher and less than 100, and Retainer status equals Active, trigger the Approaching your retainer limit email. If Usage percent is 100 or higher and Retainer status equals Active, trigger the Retainer limit reached email. If Retainer status equals Paused or Ended, don't send either alert email regardless of Usage percent." Click Generate Rules, review each rule, and approve them.
8. Save the logic: Click Save in the top right corner.
9. Add the request status logic: On the request log form's Logic tab, click Magic Logic and paste: "When a client submits this form, trigger the Request received email to the submitter and the New request notification to the account team. If Status is changed to Completed, trigger the Your request is complete email to the submitter." Generate, review, and approve the rules, then click Save.
Part 4 — Create the email templates
Five emails run this workflow: two fire off the request log form, and three fire off the retainer account form as usage climbs.
1. Open the email template editor: Click your profile icon, go to Apps and integrations, find Custom email templates, and click Add new template.
💡 Want to send branded, personalized emails instead of Formaloo's plain default? See how to create and send custom email templates.
2. Build the request received email: Set the subject to "We've got your request, @client_name," open the AI editor, and paste: "Write a warm, brief confirmation email to a client who just submitted a new work request to their agency. Confirm receipt and restate the request title (@request_title) and deliverable type (@deliverable_type). Let them know their account manager will follow up with a timeline. Tone: professional but warm, not corporate. 3 to 4 sentences max. Design: white background, single centered column max 560px wide, Inter or system-ui font, a light badge showing the deliverable type near the top, muted footer in #999." Attach it to the On Submit trigger from Part 3, addressed to @email.
3. Build the new request notification: Set the subject to "New request from @client_name: @request_title," and paste this AI prompt: "Write a short, factual internal notification telling an account manager a new client request came in. State the client name (@client_name), request title (@request_title), deliverable type (@deliverable_type), priority (@priority), and due date (@needed_by). End by prompting them to review and assign it. Tight, no fluff, 3 sentences max. Design: white background, single column max 560px, Inter font, a small data table listing client, request, priority, and due date, muted footer in #999." Attach it to the same On Submit trigger, addressed to your account team.
4. Build the approaching-limit email: Set the subject to "@client_name is at @usage_percent% of their monthly retainer," and paste: "Write a clear, non-alarming heads-up to both the client and their account manager that the client's monthly retainer hours are running low. State hours used (@hours_used) out of the total retainer (@monthly_hours) and the percent used (@usage_percent). Suggest reaching out to discuss adding hours or adjusting scope. Tone: factual, helpful, not alarmist. 4 to 5 sentences. Design: white background, single column max 560px, Inter font, a progress-bar-style visual or status badge showing usage percent, muted footer in #999." Attach it to the 80 percent rule from Part 3, addressed to @client_email and the account manager.
5. Build the limit-reached email: Set the subject to "@client_name has used their full monthly retainer," and paste: "Write a clear, professional email to both the client and their account manager stating the client has used all allotted retainer hours this cycle (@hours_used of @monthly_hours). Explain that further work this cycle may be billed separately or should wait for the next cycle, and invite them to a conversation about adjusting the retainer. Tone: direct, not punitive. 4 to 5 sentences. Design: white background, single column max 560px, Inter font, an amber or red status badge reading 100% used, muted footer in #999." Attach it to the 100 percent rule from Part 3, addressed to @client_email and the account manager.
6. Build the completion email: Set the subject to "Your request "@request_title" is complete," and paste: "Write a short, satisfying completion email letting the client know their request (@request_title) has been completed. Thank them and mention they can log a new request anytime. Tone: warm, appreciative. 2 to 3 sentences. Design: white background, single column max 560px, Inter font, a green Completed status badge, muted footer in #999." Attach it to the Completed status rule from Part 3, addressed to @email.
Part 5 — Create the PDF template
This PDF is a retainer usage summary an account manager can attach to either alert email, so clients get a document with the numbers, not just a line in an email body.
💡 Want every submission to generate a polished, branded document automatically? See how to create PDF templates to turn responses into documents.
1. Open the PDF template editor: Click your profile icon, go to Apps and integrations, click Custom PDF template, and click Add new template.
2. Switch to HTML mode: In the template editor, click the HTML / code toggle.
3. Paste the PDF code: Delete any existing content and paste the full HTML below. The @client_name, @monthly_hours, @hours_used, @usage_percent, @retainer_status, and @account_manager variables pull live data from each retainer account record.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Retainer usage summary</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background: #ffffff; color: #1a1a1a; } .page { max-width: 760px; margin: 0 auto; padding: 60px 72px; } .header { margin-bottom: 40px; border-bottom: 1px solid #eee; padding-bottom: 24px; } .header .doc-title { font-size: 24px; font-weight: 700; letter-spacing: -0.01em; margin-bottom: 8px; } .header .doc-meta { font-size: 12px; color: #999; } .doc-meta span { margin-right: 16px; } .section { margin-bottom: 36px; } .section-title { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: #aaa; font-weight: 600; margin-bottom: 16px; } .field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0; } .field { padding: 14px 0; border-bottom: 1px solid #f0f0f0; } .field.full { grid-column: 1 / -1; } .field-label { font-size: 12px; color: #999; margin-bottom: 4px; } .field-value { font-size: 15px; color: #1a1a1a; font-weight: 500; } .status-badge { display: inline-block; font-size: 12px; font-weight: 600; padding: 4px 12px; border-radius: 100px; background: #eef6f0; color: #2f7a4d; } .usage-bar-wrap { margin-top: 8px; } .usage-bar-track { width: 100%; height: 10px; background: #f0f0f0; border-radius: 100px; overflow: hidden; } .usage-bar-fill { height: 100%; width: @usage_percent%; background: #1a1a1a; border-radius: 100px; } .usage-caption { font-size: 12px; color: #999; margin-top: 8px; } .inset { background: #f9f9f9; border-left: 3px solid #ddd; padding: 16px 20px; font-size: 13px; color: #555; line-height: 1.6; } .footer { margin-top: 48px; padding-top: 20px; border-top: 1px solid #eee; display: flex; justify-content: space-between; font-size: 11px; color: #aaa; } </style> </head> <body> <div class="page"> <div class="header"> <div class="doc-title">Retainer usage summary</div> <div class="doc-meta"> <span>Account: @client_name</span> <span>Account manager: @account_manager</span> <span>Status: @retainer_status</span> </div> </div> <div class="section"> <div class="section-title">Retainer overview</div> <div class="field-grid"> <div class="field"> <div class="field-label">Monthly retainer hours</div> <div class="field-value">@monthly_hours hrs</div> </div> <div class="field"> <div class="field-label">Hours used this cycle</div> <div class="field-value">@hours_used hrs</div> </div> <div class="field"> <div class="field-label">Retainer status</div> <div class="field-value"><span class="status-badge">@retainer_status</span></div> </div> <div class="field"> <div class="field-label">Account manager</div> <div class="field-value">@account_manager</div> </div> </div> </div> <div class="section"> <div class="section-title">Usage this cycle</div> <div class="field full"> <div class="usage-bar-wrap"> <div class="usage-bar-track"> <div class="usage-bar-fill"></div> </div> <div class="usage-caption">@usage_percent% of the monthly retainer used</div> </div> </div> </div> <div class="section"> <div class="section-title">Note</div> <div class="inset"> This summary reflects hours logged as of the generation date above. Reach out to your account manager if you have questions about usage, scope, or adjusting your monthly retainer. </div> </div> <div class="footer"> <span>Confidential, for the named account only</span> <span>[Agency name]</span> </div> </div> </body> </html>4. Save the template: Click Save in the top right corner.
5. Attach it to the alert emails: Open the approaching-limit and limit-reached email templates from Part 4 and turn on Attach PDF, selecting this template for both.
Part 6 — Activate the portal
The last step turns your project into a portal with two roles: clients who only see their own account, and the account team who sees everything.
💡 Want to give clients their own space to submit and track requests? See how to create a portal and manage users' access.
1. Activate the portal: From your project, click the Settings (gear) icon and select Activate Portal, then click Manage User and open the Setup Wizard.
2. Set up a user directory: Search for an existing user directory or add a new one. Every portal needs one to manage registered users. Click Next step to configure login, sign-up, and CAPTCHA settings, then add the profile that connects the user directory to your two forms.
3. Create the two roles: Go to the User directory, click Edit profile fields, and scroll to the User roles field. Add a Client role and an Account team role.
💡 Want reviewers, clients, and your team to each see a different view of the same portal? See how to create and assign user roles in your portal.
4. Restrict the My requests and My retainer usage pages to own data: Switch to Edit mode on each page's data block and click Options. Under Manage access, select the client's profile field from the dropdown and toggle on Allow users to view only their data.
5. Restrict My assigned requests to the logged-in assignee: Switch to Edit mode on this page's data block, click Options, and under Manage access, select the Assignee field and toggle on Allow assignees to view only their data.
6. Hide the Client retainer accounts page from the Client role: Switch to Edit mode, click the three-dot menu next to the page name, and select Access. Set external user access to Specific user roles and choose Account team only, then click Save.
7. Publish the portal: Click Publish in the island bar at the top.
Note: You can set a custom domain on your portal, available on the Business plan or via the Brand removal add-on.
What you now have
Clients have one place to log requests and a live view of exactly how many retainer hours they've used, instead of asking your team over email. Your account managers get a triage board sorted by status, a queue of just their own assigned work, and a proactive list of accounts closing in on their limit before the alert email even lands. The usage percent formula and the alert logic mean nobody has to manually check every account every week, and the PDF summary gives clients a document to point to if they ever question the number.
What's next
Bill overage hours automatically Once a client crosses their retainer, some agencies want to charge for the extra hours instead of just flagging it. → How to create a subscription-based payment form
Route urgent requests to a specialist automatically As your client list grows, you can assign requests by deliverable type instead of one account manager triaging everything. → How to create and assign user roles in your portal
Send a monthly recap to every client automatically Instead of waiting for a client to ask, you can send a scheduled summary of hours used and requests completed. → How to send an email campaign and collect data with AI agents
Ready-to-use templates
Service cost estimator for agencies — Lets clients estimate project costs before booking a call. Pair it with this workflow so a client's estimate and their ongoing retainer usage live in the same portal.
Employee request workflow — Routes internal requests by type and tracks approvals from one view. The status and assignee pattern here is the same one this retainer tracker uses for client requests.
Subscription payment form — Collects recurring payments and monitors them from one folder view. A natural pairing once you're ready to bill retainer overages automatically.
Learn more how-tos
Estimating and billing agency clients This workflow tracks hours against a retainer. This one estimates cost before the work even starts, useful if you also take on project-based work alongside retainers. → How to build a service cost estimator that emails clients a price breakdown
The same threshold-alert pattern, applied to capacity instead of hours Event registration uses the same idea, alerting once a limit is approached, just applied to ticket tiers instead of retainer hours. → How to collect event registrations, manage capacity, and send automated confirmations
Scoring and routing requests automatically as they come in If you want requests scored or prioritized by more than just an urgency dropdown, this shows the same logic-and-routing approach applied to lead scoring. → How to build an AI-powered lead qualification system
