NHU Group-Based Ticket Routing β€” Staff Training

How every Zendesk ticket flows from creation through the Open Pool to resolution. For all staff who touch Zendesk.

Live system status

Reload the page to refresh. Pulled live from Supabase. Counts reflect tickets updated in the last 90 days; Smart Router metric reflects last 24 hours.

Open Pool
β€”
Needs our attention
Pending
β€”
Waiting on requester
On Hold
β€”
Waiting on 3rd party
Solved Today
β€”
Velocity signal
Specifically Assigned
β€”
Named owner required
Smart Router Β· 24h
β€”
Auto-routed by identity

Open Pool β€” what needs attention right now

Loading live data…
v15 Β· 2026-05-13 late

NTV chain refinementsShip 2

The signed_ntv Action Chain is now doing real work. When you click βœ… NTV Signed - Notice Accepted on a parent NTV ticket, 10 steps run on the parent β€” including two new handoffs that replace manual hunt-and-peck work: Ryan gets a utility coordination task in a dedicated view, Ashley gets an AI-drafted owner-decision email pre-filled with the owner's name and the property details.

v15 β€” 3 things new since v14
1 Β· πŸ”Œ Utility Coordination on the parent NTV ticket For Ryan
When the NTV macro fires, the chain posts a πŸ”Œ internal note on the parent ticket with the Utility Coordination SOP checklist (electric / gas / water / trash / internet) pre-filled with the property address, tenant info, lease end date, surrender date, owner contact. It also adds the tag pending_utility_research.
Ryan finds his queue at the new view πŸ”Œ Utility Coordination Pending (filters on the tag). He side-conversations utility companies directly from the parent NTV ticket β€” full audit stays in one place. No new child ticket is created β€” keeps the NTV journey unified.
When done, Ryan applies πŸ”Œ Utility Coordination Complete macro β€” removes the pending tag, adds utility_research_complete, and prompts him with a structured decision template (which utility went where, transfer dates, provider info).
2 Β· πŸ“¬ Owner Decision Email draft For Ashley
The chain auto-drafts a full owner-decision email and posts it as an internal note on the parent NTV ticket. The draft is pre-resolved with the owner's first name, the property address, the tenant's name, the lease end date, the surrender date, the current rent, and a 3-business-day deadline computed from today. Zero brackets for Ashley to fill in.
Owner gets 3 options to reply to:
  • πŸ” Re-rent β€” find a new tenant. Reply with adjustments ("increase rent to $X", "available [date]", "no pets this time", etc.).
  • πŸ’° Sell β€” refer to an agent for sale. NHU acts as referring brokerage and earns a referral fee. PDF Referral Agreement generator coming in next refinement.
  • πŸ’¬ Let's discuss β€” owner has questions, wants a call.
Ashley reviews the draft, hits copy, sends from her email or as a Zendesk public reply. Owner replies β†’ lands as comment on the same parent NTV ticket. The tag pending_owner_decision is on the ticket; magic-link buttons + hosted decision forms are queued for the next refinement (will replace structured-reply pattern with one-click options for the owner).
External-Send Rule still in force: Ashley copy-paste-sends. Nothing leaves Zendesk automatically.
3 Β· Engine v2 β€” auto-enrichment for all chain steps Foundation
Every chain run now auto-fetches the parent ticket, parses the original TRF submission payload, and looks up the owner in AppFolio. 30+ template variables resolve automatically across all chain step internal notes β€” {{owner_first_name}}, {{property_address}}, {{lease_end_date}}, {{surrender_date}}, {{current_rent}}, {{tenant_name}}, {{forwarding_address}}, etc.
What this means for the bigger picture: every future chain refinement (RentCheck auto-schedule, tenant pre-vacate reminders, watchdogs, downstream decision chains) gets this for free. We never have to hand-fill ticket data again.
Graceful fallback: for tickets that didn't come through the TRF (older NTV requests, side-convo-created tickets), the chain still runs β€” just with fewer auto-filled vars. Generic ticket info (subject, requester) always resolves.

The signed_ntv chain β€” full 10-step sequence (in order)

  1. Internal note: "βœ… NTV Signed - Notice Accepted" with auto-filled property/tenant/lease/surrender details
  2. Tags added: lifecycle_ntv_signed + ntv_workflow_active + ntv_workflow_fired
  3. Group set to Support & Requests
  4. Assignee cleared (parks ticket in Open Pool for staff pickup)
  5. Status flipped to open
  6. πŸ”Œ Utility Coordination internal note with SOP checklist β€” Ryan's task
  7. Tag added: pending_utility_research
  8. πŸ“¬ Owner Decision email draft auto-resolved with all owner/property details β€” Ashley copy-paste-sends
  9. Tag added: pending_owner_decision
  10. Roadmap internal note listing what's still queued (RentCheck auto-schedule, tenant reminders, watchdogs, magic links, PDF referral generator, downstream decision chains)

What's NOT firing automatically yet (queued for next refinements)

  • RentCheck Move-Out Inspection auto-schedule (pending RentCheck automation audit)
  • Tenant pre-vacate reminders (14d / 7d / 2d / 0d) β€” drafts only until Steven approves auto-send
  • pg_cron watchdogs for utility (2 business days) and owner decision (3 business days) SLAs
  • Magic-link buttons + hosted owner-decision forms (one-click UX instead of structured reply)
  • PDF Referral Agreement generator for the Sell decision path
  • Downstream chains by decision: owner_decision_rerent / owner_decision_sell / owner_decision_discuss
v14 Β· 2026-05-13

What's new in this releaseRead first

Eight live behavior changes you'll see in Zendesk today. The routing system moved from "tells you what it would do" to "does it for you" on high-confidence decisions. Several macros are gone. New auto-merge behavior collapses NTV journeys into one ticket. Read this section before working tickets β€” the rest of the doc still applies, this is the changelog.

v14 β€” 8 behavior changes
1 Β· Universal Router is now in APPLY mode Live
When the router has β‰₯ 0.90 confidence, it now physically changes the ticket β€” group, form, category, status, tags β€” instead of just logging what it would have done. Before today this was shadow mode (read-only logging). If you see a ticket move group on its own within a few seconds of arrival, that's the router applying.
Safety: Router only overrides when the cascade landed in Triage / Support / no-group. If a specific group like Maintenance was already set by a trigger or staff, the router leaves it alone.
2 Β· Default New β†’ Open trigger Live
Every brand-new ticket landing in status=new auto-flips to open on Create. The Open Pool filter (status=open AND assignee=empty) now catches everything by default. Exception triggers (Voicemail β†’ Hold, Energy Report β†’ Solved, RentCheck PASS β†’ Solved, etc.) still take precedence β€” those run first.
What it means for you: stop relying on the manual "New" view as a safety net. The Open Pool is now the canonical "needs attention" view.
3 Β· AppFolio doc-signed notifications auto-merge into the parent NTV request Behavior change
Before: tenant submits Request to Vacate (one ticket) β†’ tenant signs in AppFolio β†’ Zendesk gets a second ticket "A document has been signed and is ready for review". Two disconnected tickets per NTV.
Now: when AppFolio's doc-signed notification arrives, the router detects it, finds the matching active NTV request ticket by property + form_id, and auto-merges the notification into the parent. You see ONE ticket showing the full journey β€” tenant submission β†’ staff verification β†’ doc-signed merged comment with the View Document link β†’ next steps.
Where to apply the macro: on the surviving parent NTV request ticket, not on the merged notification.
4 Β· New macro: βœ… NTV Signed - Notice Accepted New macro
Apply after countersigning the NTV in AppFolio. In one click it does all of: adds tag ntv_signed_workflow_fire, flips group to Support & Requests, clears the assignee, sets status to open, posts the confirming internal note. Hit Submit-as-Open and the ticket is in the Open Pool ready for staff to execute the move-out coordination.
Behind the scenes, the tag fires the Action Chains move-out workflow via webhook β†’ nhu-post-event-fanout. The chain posts internal note drafts of what we WILL automate (utility coordination, owner-decision email, RentCheck) β€” none of those external sends fire automatically yet. They remain copy-paste from internal note drafts until Steven approves auto-send.
5 Β· 10 outdated macros deactivated Removed
If you previously used any of these, stop β€” they no longer appear in your macro picker:
  • NTV :: 1 Β· Verified through NTV :: 7 Β· Complete (Brandon's 4/29 stage-gate pipeline β€” superseded by Action Chains)
  • NTV :: ⚠ Escalate to Steven (same pipeline)
  • Property Management::Owner::Notice to Vacate (2022 β€” predates current form)
  • One duplicate Application :: 3 Β· Lease Signed β€” Create Move-In (kept the other)
Replacement for the NTV gates: the single βœ… NTV Signed - Notice Accepted macro plus the auto-merged journey covers the whole pre-vacate phase. Future surrender / disposition / refund stages will get their own purpose-built macros.
6 Β· Router enrichment notes on sparse-body identity tickets Live
When a ticket has a thin body (e.g., "give me a call about Anderson") AND the requester matches a known owner / vendor / tenant, the router auto-posts a 🧭 enrichment note with: identity profile, AppFolio link, phones, likely property guess (matched by street-name nickname), any open WO on that property. Five-minute lookup becomes zero touches.
Won't fire if subject already has full address / WO number / a merge-suggestion note covers context / body is rich (>500 chars).
7 Β· Vendor identity layer in the router Live
AppFolio's mailer-alias addresses (*.mailer.appfolio.us) used to break identity recognition β€” replies from vendors got misclassified as tenant by AI Copilot. v5 router now queries source_appfolio_vendors by requester name (handles "First Last" β†’ "Last, First" variations) and by email when available. When matched, the vendor identity overrides the wrong AI Copilot tag.
Net effect: vendor replies (estimate questions, invoice followups, dispatch updates) now route to Maintenance / Receivables correctly without staff intervention.
8 Β· Action Chains engine is live Foundation
Behind the new NTV macro is a generic workflow engine (nhu-post-event-fanout). Tag-driven webhook fires β†’ engine reads workflow_definitions.steps JSONB β†’ executes step-by-step β†’ logs to nhu_action_chains_log. Step types include internal notes, status/group/assignee changes, tag updates, AI drafting, and webhook calls.
Currently active chain: signed_ntv (6 internal-safe steps, ships internal note drafts only β€” no external sends).
Queued chain refinements (will be added to workflow_definitions.steps over time, no redeploy needed):
  • Utility Coordination ticket to Ryan (trigger condition TBD β€” not every NTV)
  • Owner-decision email draft (AI draft: "Re-rent / Sell / Take back?")
  • RentCheck Move-Out Inspection auto-schedule
  • Tenant pre-vacate reminders (14d / 7d / 2d / 0d) β€” drafts only until Steven approves auto-send
  • pg_cron watchdogs β€” escalate to Steven's cockpit ONLY when something is dropped (not steady-state noise)

What staff should do differently starting today

  • Trust the auto-routing. Within ~5 seconds of a ticket landing, the router may change its group / form / status / tags. That's expected. Don't undo it unless it's clearly wrong (flag it to Steven if so).
  • NTV signature flow: AppFolio doc-signed notifications get folded into the parent NTV request ticket automatically. Look for the original NTV request ticket (with the form name Notice to Vacate) β€” the View Document link from AppFolio will be in the merged comment.
  • One macro for NTV countersignature. The old NTV :: 1-7 stage gate macros are gone. Use βœ… NTV Signed - Notice Accepted and Submit-as-Open. The ticket flips into the Open Pool and the workflow chain fires in the background.
  • Internal notes are drafts, not sends. Owner emails, tenant comms, vendor messages drafted by AI all post as internal notes for you to copy-paste-send. Nothing leaves Zendesk automatically until Steven flips that switch.
  • Steven's cockpit gets only exceptions. When a step is overdue, blocked, or escalated, it shows up there. Don't worry about updating him on routine progress.
Step 1

A new ticket enters Zendesk

Email, web form, AppFolio bridge, side conversation reply, or API call creates a ticket. This is the start of every workflow at NHU β€” no exceptions. The system doesn't care where the ticket came from; it cares what to do next.

Sources of new tickets
Inbound email
Tenant emails support@nexthomeunlimited.zendesk.com β†’ ticket auto-created.
Web form submission
Tenant Request Form, Owner Request Form, HOA form β€” ticket created with form pre-set.
AppFolio bridge
New WO, application, lease event, NTV request in AppFolio β†’ ticket synced into Zendesk.
Side conversation reply
External vendor or contact replies to an outbound side convo β†’ updates the parent ticket.
Bat phone call
Vendor maintenance hotline β†’ ticket created and routed to Maintenance group.
Edge Function / API
Daily digests, scheduled reports, internal automations create their own tickets.

What staff should know

  • Every inbound channel becomes a ticket. If something needs our team's attention, it should exist as a Zendesk ticket. Side conversations, internal Slack chatter, and one-off emails don't count as "work" until they're a ticket.
  • You don't decide where it goes. The routing happens in the next two steps automatically. Your job starts in Step 4.
  • The ticket has a requester β€” the person who created or is asking about the issue. Most tickets have the tenant or owner as requester. For internal-source tickets (digests, automations), the requester is a system user.
Step 2

The routing trigger picks a group

A Zendesk trigger fires immediately on ticket creation. It reads the ticket's subject, tags, source, and custom fields, then sets the group_id so the ticket lands in the right queue. No human touches this step.

Routing decision tree
Ask in order:
  1. Spam, ambiguous, or missing details? β†’ Triage
  2. Maintenance / repair issue? β†’ Maintenance / Work Orders
  3. Pipeline event (application, move-in, renewal, NTV, countersign)? β†’ Convert & Commit
  4. Accounting / money execution (vendor bill, payment posting, owner disbursement)? β†’ Receivables & Payables
  5. General tenant / owner / vendor / agent question? β†’ Support & Requests
  6. Requires Steven's or Ryan's personal decision? β†’ NHU CEO & Owner
  7. Elbow Creek HOA-specific? β†’ HOA - Elbow Creek

The 7 active routing groups:

Triage
Sort fast. Route right. Default for anything unclear.
Support & Requests
Day-to-day questions from tenants, owners, vendors, agents.
Maintenance / Work Orders
Repairs, vendor dispatch, scheduling, emergencies.
Convert & Commit
Pipeline events β€” applications, renewals, NTV, move-in.
Receivables & Payables
Vendor bills, payments, disbursements, ledger corrections.
NHU CEO & Owner
Steven + Ryan. Strategic decisions, executive review.
HOA - Elbow Creek
Specialty group for Elbow Creek HOA management workflow.

What staff should know

  • Groups define ownership. A ticket's group_id is the answer to "who owns this?" β€” collectively, by the group, not by one person.
  • Triage is the safety net. If the routing trigger can't make a confident decision, it falls through to Triage. Whoever scans Triage classifies the ticket and re-routes it. Repeating patterns that hit Triage should prompt a routing-trigger improvement.
  • One group, many views. Inside a group like Support & Requests, separate views filter by requester type (tenant vs owner vs vendor vs agent). One ownership group, many lenses.
  • The 8th and 9th groups β€” Sales | Call-Ins and zPMWBatPhone β€” exist but are dormant. Don't route to them.
Step 2a Β· NEW (2026-05-12)

Smart Router β€” automatic identity routingLive

Before the standard routing trigger runs, a Supabase-backed Smart Router checks the ticket's requester email against NHU's identity tables β€” Applications, Tenants, Owners, Vendors. If it matches, the ticket gets routed automatically with the right form, group, and tags. If no match, the ticket falls through to the Step 2 routing trigger like any other.

Smart Router β€” chunked rollout

How it works:

  1. Zendesk fires the "Smart Router β†’ ticket.created" trigger on every new ticket.
  2. Trigger sends ticket id + requester email + subject to a Supabase Edge Function.
  3. Function looks up the email in the AppFolio identity tables.
  4. If a match: function PATCHes the ticket with the correct form + group + tags. It never sets the assignee β€” the Open Pool model takes it from there.
  5. If no match: function logs the miss and leaves the ticket alone. Step 2 routing handles it.

Rollout β€” one identity type at a time:

Chunk 1
Applicants
β˜… Live Β· 2026-05-12
Chunk 2
Tenants β€” Current
β˜… Live Β· 2026-05-12
Chunk 3
Tenants β€” Notice
β˜… Live Β· 2026-05-12
Chunk 4
Tenants β€” Future
β˜… Live Β· 2026-05-12
Chunk 5
NHU Agents
β˜… Live Β· 2026-05-12
Chunk 6
NHU Owners
β˜… Live Β· 2026-05-12
Chunk 7
NHU Vendors
β˜… Live Β· 2026-05-12
Chunk 8
Inactive Applicants (cleanup)
Staged

What Chunk 1 (Applicants) does:

Email matches an Application record (any status β€” In Review, Info Needed, Converting, Converted, Denied, Canceled) OR email is an AppFolio mailer alias (*.mailer.appfolio.us) with the word "application" in the subject
β†’ Form set to Applications
β†’ Group set to Convert & Commit
β†’ Tag added: applicant_routed + applicant_status_<status>
β†’ Custom field Routing Classification set to convert___commit
β†’ Assignee left empty β€” anyone in C&C can grab from the Open Pool

What Chunk 5 (NHU Agents) does (NEW 2026-05-12):

Email matches the nhu_agents table β€” 23 active NHU agents on @nexthomeunlimited.com (Junction City, Manhattan, Abilene)
β†’ Group set to Support & Requests
β†’ Form left alone (no agent-specific form)
β†’ Custom field Requester Type: set to an_agent__nhu
β†’ Custom field Routing Classification set to support___requests
β†’ Tag added: nhu_agent_routed
β†’ Assignee left empty β€” anyone in S&R can grab from the Open Pool
β†’ Ticket appears in πŸ™‹ Support :: Agent :: All Active automatically

What Chunk 6 (NHU Owners) does (NEW 2026-05-12):

Email matches the v_owner_emails view β€” 244 (owner, email) rows from 177 NHU PM owners. 65 owners have multi-email entries (co-owners, spouses, business partners) β€” the view explodes those into one row per email so exact match is safe (no partial-email risk).
β†’ Group set to Support & Requests
β†’ Form left alone (no owner-specific form)
β†’ Custom field Requester Type: set to a_property_owner__currently_managed_by_nexthome_unlimited
β†’ Custom field Routing Classification set to support___requests
β†’ Tags added: nhu_owner_routed + owner_pm
β†’ Assignee left empty β€” anyone in S&R can grab from the Open Pool
β†’ Ticket appears in πŸ™‹ Support :: Owner :: All Active automatically

What Chunks 2-4 (NHU Tenants) do (NEW 2026-05-12 late):

Email matches the v_tenant_emails view β€” 419 distinct emails across 255 active occupancies. Status-aware: Current/Notice β†’ a_tenant__current_tenant_requester, Future β†’ a_tenant__future_tenant, Past β†’ a_tenant__previous_tenant_requester.
β†’ Group set to Support & Requests
β†’ Form left alone (lets AppFolio bridge + WO orphan trigger handle lifecycle-specific routing)
β†’ Custom field Requester Type: set by status (above)
β†’ Custom field Routing Classification set to support___requests
β†’ Tags added: nhu_tenant_routed + tenant_status_<current|notice|future>
β†’ Assignee left empty β€” anyone in S&R can grab from the Open Pool
β†’ Ticket appears in πŸ™‹ Support :: Tenant :: All Active automatically

What Chunk 7 (NHU Vendors) does (NEW 2026-05-12, end of day):

Email matches the v_vendor_emails view β€” 114 distinct emails across 117 NHU vendors (exploded one-row-per-email from source_appfolio_vendors.email).
β†’ Group set to Support & Requests (vendors do both PM and Sales work β€” Support is the right ownership default, not Maintenance)
β†’ Form left alone (no vendor-specific form)
β†’ Custom field Requester Type: set to a_vendor__other (safe default β€” most vendor emails are general comms; specific types a_vendor__invoice / a_vendor__work_order can be set downstream by content rules)
β†’ Custom field Routing Classification set to support___requests
β†’ Tags added: nhu_vendor_routed + vendor_default_other + bridge_needs_enrichment
β†’ Assignee left empty β€” anyone in S&R can grab from the Open Pool
β†’ Ticket appears in πŸ™‹ Support :: Vendor :: All Active automatically (view id 40419954803863)
About bridge_needs_enrichment (the deliberate tag): This is the entry point for the upcoming Property Context Enricher. That Edge Function will scan the email body and attachments for a property address, fuzzy-match against source_appfolio_properties, look up open parent WO tickets at that property, and auto-merge the vendor email into the WO ticket when confidence is high (e.g., exactly one open WO at the matched property). Until that ships, vendor emails land in πŸ™‹ Support :: Vendor :: All Active and Shawnee/Ashley handle the merge.

Architectural note β€” why WO/maintenance routing doesn't conflict with tenant routing:

WO work tickets are created upfront via Supabase β†’ wo-intake-automation. They land on the Maintenance form, in the Maintenance group, with all the WO context attached. Those are the work tickets.

Inbound tenant emails are tenant communications, not WO work. They route to Support::Tenant via Smart Router. Tenant comms about a specific WO get merged into the parent WO ticket the same way voicemails do via πŸ”§ Maintenance :: Calls to Merge.

The WO email orphan trigger keeps doing its job for AppFolio system notifications (from *.mailer.appfolio.us) β€” those aren't tenant comms either, so no conflict.

Precedence when an email matches multiple identities:

Smart Router checks identities in order: NHU Agents (internal staff wins) β†’ NHU Owners (established PM relationship) β†’ NHU Tenants (active leaseholders) β†’ NHU Vendors (paid service providers) β†’ Applications (new inbound) β†’ mailer-alias fallback. An agent who's also a tenant gets agent routing; an owner who's also a tenant gets owner routing; a tenant who's also applying for a new rental gets tenant routing; a vendor who's also a tenant gets vendor routing (paid service relationship is the operationally relevant lens). First match wins.

What staff should know

  • You'll see fewer applicant emails in Triage. Applicants whose emails are on file with AppFolio now auto-land in Convert & Commit on the Applications form. Triage is for unknown senders.
  • Look for the applicant_routed tag. If a ticket has that tag, the Smart Router placed it β€” not a human. If you see it routed to the wrong place, flag the ticket and we'll tune the rules. Don't just re-route silently or we miss the signal.
  • Mailer-alias applicants get tagged appfolio_mailer_unmatched. These come from AppFolio's anonymized email forwarders. The Smart Router can't see the applicant's real email, but it can see the pattern. Tagging keeps them visible for audit.
  • The Smart Router never assigns to a person. Per NHU's Open Pool rule, automation sets the group only. Cross-trained staff pulls from the pool.
  • Audit table: smart_router_log in Supabase. Brandon can pull any time to see what the router did and why.
Step 2b Β· NEW (2026-05-12)

AppFolio Bridge Triggers β€” auto-routing by lifecycle tagLive Β· 4 triggers

AppFolio sends notification emails to pm@nexthomeunlimited.com when lifecycle events fire β€” move-outs, renewals, lease signings, application updates. Zendesk's AI Copilot tags those tickets with lifecycle_* tags. Four Zendesk triggers watch those tags and switch the ticket onto the right form + set the right custom fields, so each AppFolio email lands in its dedicated view automatically.

Four AppFolio bridge triggers β€” fire on tag, idempotent via audit tag
Trigger Watches for tag Sets form β†’ view Audit tag
AppFolio β†’ NTV formlifecycle_ntvNTV form β†’ πŸ“¦ NTV :: All Activeappfolio_routed_ntv
AppFolio β†’ Renewals formlifecycle_renewalRenewals form β†’ πŸ”„ Renewals :: All Activeappfolio_routed_renewal
AppFolio β†’ Move-In formlifecycle_moveinMove-In form β†’ πŸ”‘ Move-In viewappfolio_routed_movein
AppFolio β†’ Support::Tenant catchalltenant + appfolio + no lifecycle tag(no form change) β†’ πŸ™‹ Support :: Tenantappfolio_routed_support

Idempotency via audit tag:

Each trigger fires on a ticket exactly once. The first fire adds its audit tag (e.g. appfolio_routed_ntv). Subsequent updates skip the trigger because the audit tag is now present. Safe to leave running indefinitely; no infinite loops.

What staff should know

  • Move-out emails, renewal confirmations, and lease-signing notifications now route themselves. When an AppFolio email arrives, within seconds Zendesk's AI Copilot tags it (e.g. lifecycle_ntv), the relevant trigger fires, and the ticket lands in the correct view. No manual triage needed.
  • The audit tag tells you the trigger ran. If you see appfolio_routed_ntv on a ticket, you know the routing was automatic. If a ticket should have been routed but doesn't have the tag, flag it β€” that's a routing miss worth investigating.
  • NTV and Renewals are simplified to the rollup view. As of 2026-05-12 the granular sub-views (NTV :: Surrender Gate, NTV :: RED Escalations, Renewals :: Owner Decision Gate, Renewals :: RED Escalations) are removed. The trigger lands tickets in πŸ“¦ NTV :: All Active or πŸ”„ Renewals :: All Active. We'll re-introduce granular gates later when there's real volume to justify them.
  • The catchall is one-time on backlog. When the catchall trigger shipped, every active AppFolio tenant ticket got Requester is filled in and tagged appfolio_routed_support. That's a one-time fix, not a recurring storm.
Step 3

The ticket lands in the group's Open Pool

The ticket is now in the group queue with status Open. "Open" means "needs our attention." The pool is shared across everyone in the group. There is no specific assignee β€” unless the work uniquely requires one person.

Conceptual: how the Open Pool works
βœ“ The default β€” group only

Ticket goes to group queue with no assignee. Anyone on the group's roster can pull it.

Group: Maintenance / Work Orders
Assignee: β€” (unassigned)
Status: Open

95% of tickets work this way.

⚠ The exception β€” specific assignee

Ticket goes to a group and has a named assignee. The system is saying: only this person can do this work.

Group: NHU CEO & Owner
Assignee: Steven Burch
Status: Open

Rare. Reserved for signatures, owner-decisions, brokerage transactions.

What staff should know

  • The Open Pool is a shared queue. No one "owns" a ticket in the pool until they decide to take action on it. Everyone in the group can see everything in their pool.
  • Specific assignee = signal. If your name appears on a ticket, the system is telling you: YOU are the only person who can do this work. Treat it as a personal flag, not a routine assignment. Examples: signatures land on Steven, water bills land on Ryan, HOA Elbow Creek work lands on Ryan.
  • If you see your name on a ticket and you genuinely can't do the work (out of office, wrong skill set), reassign back to group-only β€” don't leave it stuck on you.
  • If you find a ticket without a group at all, it's a triage gap β€” push it to Triage and tell Brandon so the routing trigger (or Smart Router) can be improved.
Step 4

Staff opens Zendesk and pulls from the Open Pool

You open Zendesk. You scan the views for the groups you belong to. You pull a ticket from the Open Pool and start working it. No claim ceremony β€” whoever gets there first does the work.

nexthomeunlimited.zendesk.com/agent β€” your group views

Each staff member sees the views for the groups they're a member of. The sidebar dropdowns group views by pipeline / work type.

Sidebar (your views)
πŸ›Ÿ Open Pool
πŸ”§ Maintenance (87)
:: Resident (39)
:: Internal (45)
:: Unit Turn (0)
:: Payables (3)
:: Calls to Merge β˜…
πŸ“‹ Applications (12)
πŸ”‘ Move-In (2) β˜… All Active NEW
πŸ”„ Renewals (2)
πŸ“¦ NTV (2)
🀝 Convert & Commit (7)
πŸ™‹ Support :: Agent (β€”)
πŸ™‹ Support :: Owner (β€”) β˜… NEW
πŸ™‹ Support :: Tenant (β€”)
πŸ™‹ Support & Requests (18)
β˜… My Tickets (2)
How to scan your pool
  1. Start with β˜… My Tickets. If your name is on something, that's your priority β€” only you can do it.
  2. Move to the highest-count pool across your groups. That's where the biggest backlog of "needs attention" is.
  3. Pick a ticket and work it. Don't claim, don't assign to yourself, don't add ceremony. Just do the work.
  4. Update the status when you're done. Pending if waiting on someone. Solved if resolved. Leave it Open if the next action is still yours.

What staff should know

  • Open Pool, not your inbox. You're not waiting for tickets to be assigned to you β€” you're choosing what to pull next. Inbox is push; the pool is pull. Pulling is faster.
  • Cross-trained team. Whoever gets to a ticket first works it. Don't ask "is this mine?" β€” if it's Open in a group you belong to and not assigned to a specific person, the answer is "yes if you have time."
  • β˜… Calls to Merge (NEW). Voicemails routed to Maintenance with the call_overflow tag show up here. Open the voicemail, find the parent WO ticket it's about, merge them. The voicemail disappears from this view automatically once merged.
  • Avoid double-work. If a teammate is already on a ticket (you see them in the activity log or they've added a comment), move on to another one in the pool.
  • If two people accidentally work the same ticket, the second one to comment is the one who keeps going. Cheap to coordinate.
🚨 POLICY (v13): DO NOT self-assign tickets

As of 2026-05-12, the system automatically reverses any self-assignment by anyone outside the NHU CEO & Owner group (Ryan and Steven). The ticket gets tagged policy_auto_unassigned_self_claim and bounces back to Open Pool within seconds.

Why: If you claim a ticket and get pulled into something else (call, vendor, meeting, vacation), that ticket sits orphaned on your plate. The team can't see it in the pool to help. Cross-training only works if the pool stays the pool.

How to work: Open a ticket from Open Pool β†’ do the work β†’ set status to Pending (waiting on customer), Hold (waiting on 3rd party), or Solved (done). You don't claim. You act. The status tells everyone where the ticket stands.

Escape hatch: a ticket tagged manual_assign_approved bypasses snap-back. Used for edge cases that genuinely require single-person continuity β€” Steven approves these.

Step 5

Staff works the ticket

Reply to the requester, send a side conversation to a vendor or third party, update custom fields, attach documents, run a macro. The work itself happens here.

Working a ticket β€” common actions
Public reply

Sends an email to the requester (tenant, owner, applicant, etc.). They see it in their inbox; their reply lands back on the ticket.

Side conversation

Email to a third party (vendor, attorney, internal teammate). Their reply also lands on the ticket. Use this for vendor coordination.

Internal note

A note no one outside the team sees. Use for context, decisions, "I tried X β€” didn't work," handoff notes for the next teammate.

Macro

A pre-written response template. Speeds up common replies (e.g., "we received your maintenance request"). Apply, edit if needed, send.

Merge ticket

Combines a duplicate or related ticket into a parent. The child becomes "Closed by merge" and its conversation is appended to the parent. Use this for voicemails about an existing WO (open from πŸ”§ Maintenance :: Calls to Merge), email replies that lost their thread, and obvious duplicates.

What staff should know

  • Keep the conversation on the ticket. If a tenant texts you directly or a vendor calls your cell, copy the key info into the ticket as an internal note. Otherwise the next person who picks it up has no idea what happened.
  • Use side conversations for vendors. Replies from vendors land on the parent ticket and auto-reopen it β€” verified working in production. Don't email them outside Zendesk.
  • Voicemails about a WO go in Calls to Merge. Open the voicemail, find the parent WO ticket (search the WO number or property address), and merge. The merged voicemail disappears from the Calls to Merge view automatically.
  • Internal notes are free. Cheap to write, high value for the next person. When you put a ticket on Pending or Hold, leave a quick internal note explaining what you're waiting on.
Step 6

Status moves to Pending or On Hold when waiting

When the ball is in someone else's court, change the status. Two wait states, two distinct meanings. Choose the right one.

Pending Waiting on the requester

Use when: You've sent a question or update to the person whose name is on the ticket as requester β€” typically the tenant, owner, or applicant.

Examples:

  • Tenant submitted a maintenance request without enough detail β†’ you asked for clarification β†’ Pending until they reply.
  • Owner needs to approve an estimate β†’ you sent the estimate β†’ Pending until they decide.
  • Applicant needs to upload missing documents β†’ you sent the request β†’ Pending until they upload.
Auto-reopens to Open the moment they reply. Verified in production.
On Hold Waiting on a 3rd party

Use when: You're waiting on someone other than the requester β€” a vendor, an attorney, an internal teammate who has to action, or anyone outside the original conversation.

Examples:

  • Tenant reported a leak β†’ you dispatched a vendor β†’ On Hold until vendor sends the estimate.
  • Owner asked about a tax document β†’ you escalated to the CPA β†’ On Hold until CPA responds.
  • Lease ready for countersign β†’ On Hold until Steven signs (specific assignee on the ticket).
Also auto-reopens to Open on any reply, including vendor side conversations.

What staff should know

  • The distinction matters for the next person scanning the queue. "Pending" tells them the tenant ghosted us. "Hold" tells them the vendor stalled. Different follow-up actions.
  • Both states auto-reopen on reply. You don't have to babysit either one. Once a reply lands, the ticket flips back to Open and reappears in the Open Pool. Verified at 100% pass rate in production audit.
  • Don't leave a ticket Open if you're actually waiting. Open means "needs our attention." If we can't do anything until someone else responds, it shouldn't be in the Open Pool β€” that wastes everyone's scan time.
  • If you're not sure whether it's Pending or Hold, ask: "Is the person I'm waiting on the requester on this ticket?" Yes β†’ Pending. No β†’ Hold.
Step 7

Status moves to Solved when resolved

The work is complete, the outcome is confirmed, the ticket can leave the active queue. Mark it Solved. Zendesk auto-closes Solved tickets after a few days.

When to mark Solved β€” the checklist
βœ“ The requester's outcome is actually achieved (not just "we did our part").
βœ“ Documentation is in the ticket β€” what was done, who did it, when.
βœ“ Custom fields are filled in correctly (status, stage, decision, etc.) β€” so reports pull clean data.
βœ“ Any side conversations are wrapped up or marked closed.
Don't solve early. A ticket marked Solved when the work isn't actually done leaves the queue, drops out of every scan, and reopens later as a customer complaint. If you're not sure it's done, leave it Pending or Hold.

What staff should know

  • Solved is the success state. Don't be afraid to use it β€” clean queues beat full queues. But also don't use it to make the queue look smaller when work isn't actually done.
  • Solved auto-closes after 4 days in Zendesk's default. Closed is permanent β€” the ticket can never be re-opened. If a customer follows up after that, a new ticket is created and linked.
  • If a Solved ticket reopens (via reply, side conversation, or trigger), it moves back to Open and reappears in the pool. Pick up where it left off.
Step 8

Pending or On Hold tickets auto-reopen on reply

When the person you're waiting on finally replies β€” by email, side conversation, or portal message β€” Zendesk automatically flips the status back to Open. The ticket reappears in the Open Pool. You don't have to chase.

The safety net β€” verified working
100% pass rate β€” production audit 2026-05-09

Sampled 60 recently-updated tickets. Of 4 testable side-conversation replies on Pending/Hold tickets, all 4 reopened correctly within minutes. No replies were missed.

Real examples from the audit:
  • Ticket #85674 β€” lease confirmation reply landed β†’ Solved β†’ Open
  • Ticket #85715 β€” vendor sent privacy fence estimate β†’ Hold β†’ Open
  • Ticket #85715 β€” same ticket, next day, second reply β†’ Pending β†’ Open

What staff should know

  • Trust the safety net. Once you've put a ticket on Pending or Hold with a clean internal note about what you're waiting on, you're done. No reminders to set, no calendar entry, no follow-up file.
  • The trigger watches every channel. Email reply, side conversation reply, portal message β€” all of them flip the status back to Open and surface the ticket in your pool.
  • If you notice a reply came in but the ticket didn't reopen, tell Brandon β€” that's a routing bug worth fixing.
Reference Β· NEW (2026-05-12)

πŸ•³ Unassigned Tickets vs πŸ›Ÿ Open Pool β€” what's the differenceLocked

These two views look similar at a glance (both show tickets with no assignee, status open or pending) but they mean very different things. Knowing which one a ticket is in tells you whether the system knows what to do with it.

The locked principle
πŸ•³ Unassigned Tickets

We don't know where this should go. Needs human triage to determine identity, route, and next steps. The system has no routing layer that's claimed this yet.

Conditions:
β€’ Status < solved
β€’ Not in Maintenance group
β€’ WO Ticket Category is NOT one of: support___requests, convert___commit, maintenance___work_order, receivables___payables
Note: "No assignee" intentionally NOT a condition (removed v10, 2026-05-12). Many unrouted tickets get auto-assigned by default group/round-robin β€” the routing question is about classification, not ownership.

Empty value or not_sure_β†’_triage = still in view. Goal: this count trends toward zero.

πŸ›Ÿ Open Pool β€” the "needs us, nobody owns it yet" queue

Open = Red = Action needed NOW. Tickets where the ball is in OUR court AND nobody has claimed them yet. Cross-trained staff grab from here.

Conditions (locked v12):
β€’ Status IS open
β€’ Assignee IS empty
Once someone claims a ticket (sets themselves as assignee), it leaves Open Pool and lands on their personal Home dashboard. Group permissions handle who CAN see which row inside Open Pool β€” Ryan/Steven-only tickets (signatures, owner decisions) are visible only to them via the NHU CEO & Owner group.

Specialty views (Calls to Merge, NTV, Applications, Receivables, etc.) are additive lenses β€” unclaimed tickets show in both the specialty view AND Open Pool, so nothing falls through if a specialty team is overloaded or out.

⚠ "Zero Open Pool β‰  zero undone work" until the SLA pop-open watcher ships. Claimed-and-open tickets sitting on a person beyond a threshold should auto-unassign and bounce back here. Next build target.

The closed loop β€” what to do when Unassigned grows

  • Smart Router never assigns a ticket to a person (per the Open Pool model). So unassigned alone doesn't mean unrouted β€” only unclassified means unrouted. The view tightening (2026-05-12) excludes the 4 routed classifications so the view actually reflects "needs triage."
  • When a pattern shows up repeatedly in Unassigned, that's the signal to build automation. The workflow is:
    • Identify the pattern (sender domain, subject keyword, email channel, lifecycle tag…)
    • Add a trigger / extend Smart Router to classify it
    • Trigger sets WO Ticket Category β†’ ticket exits Unassigned automatically going forward
  • Goal: Unassigned Tickets count trends toward zero over time. Anything still in the view after we've watched it a few days = work the system can't yet do without a human. That's the priority for the next routing automation.
  • Goal: Open Pool count is the real workload signal. Tells you how much active work is waiting on the team. Triage-by-classification stops being a daily task; pulling from Open Pool becomes the only daily task.
  • Validated on 2026-05-12: tickets #86376 (Final Move Out info from tenant) and #86378 (Tenant Request Form β€” General Question) were both showing in Unassigned despite Smart Router having already routed them to Support::Tenant. After the view tightening, both dropped out automatically β€” exactly the desired behavior.
  • Audit finding 2026-05-12 (late) β€” the "No assignee" bug: Supabase mirror audit found 163 active tickets, 26 truly unrouted β€” but the prior filter's "No assignee" condition hid all 26 because each had been auto-assigned by default routing. Dropping "No assignee" from the filter (v10) surfaces these as the real daily triage queue.
  • Next 3 routing automations β€” patterns identified from the 26 audit blind spots. Each is a concrete trigger to build:
    • AR auto-tag β€” subject contains "invoice", "payment", "past due", or "payment agreement" β†’ set WO Ticket Category = receivables___payables. ~7 tickets/cycle today (Athletic Cleaning invoices, Past Due notices, Payment Agreement tenant requests).
    • Tenant maintenance auto-convert β€” keyword match on appliance / repair / quote / paint terms with a tenant requester β†’ tag work_order + set group to Maintenance. ~3 tickets/cycle today (Dishwasher, home warranty service, Elderberry Run Paint).
    • Reply tag inheritance β€” when a reply creates a child ticket OR a parent reply arrives without tags, copy the parent ticket's category + lifecycle tags forward. Compounds as reply threads multiply.
  • Open follow-up for Brandon β€” verify AppFolio Bridge triggers set the WO Ticket Category field. The 4 AppFolio bridge triggers (NTV, Renewals, Move-In, Support::Tenant catchall) set form + tags. If they don't also set WO Ticket Category, lifecycle-routed tickets can still leak into Unassigned.
Reference

Lifecycle scenarios β€” what each status looks like

Five status states. Five distinct meanings. Use this as a quick reference when you're scanning a queue and trying to decide what to do next.

New Just created β€” routing trigger about to fire
Transient. A ticket exists in this state for less than a second before the routing trigger sets the group and flips to Open. You'll rarely see this status in the wild.
If you see a ticket stuck in New for more than a few minutes, the routing trigger failed β€” flag it to Brandon.
Open Needs our attention β€” pull from the pool
The ticket is waiting on someone in our team. This is the Open Pool. Everyone in the group can see it; whoever has time pulls it and does the work. If you see your name on an Open ticket, you specifically need to do the work.
This is the only status that should appear in your scan view when you're looking for "what should I work on?"
Pending Waiting on the requester
We've sent a question, update, or request to the person who owns the ticket as requester (the tenant, owner, or applicant). Ball is in their court. Will auto-reopen when they reply.
Pending = "waiting on the customer." If a Pending ticket has been sitting too long, the customer ghosted us β€” escalate or close.
On Hold Waiting on a 3rd party
We're waiting on someone outside the original conversation β€” a vendor, an attorney, an internal team member who has to action, or another party with no direct stake in the requester relationship. Will auto-reopen when they reply.
Hold = "waiting on someone we're managing the relationship with." Different escalation path than Pending.
Solved Work complete, outcome confirmed
The requester's outcome is achieved, documentation is in the ticket, custom fields are filled in. Ticket leaves the active queue. Auto-closes after a few days. If a reply lands, it flips back to Open.
Don't solve early. Better to leave it Pending or Hold than mark Solved before the work actually wraps.
Reference

What an Open Pool view actually looks like

An example of the Maintenance / Work Orders group's Open Pool. The columns and layout are the same pattern across every group β€” scan, decide, pull.

πŸ”§ Maintenance :: All Active 7 tickets Β· grouped by status
Status WO # Property Requester Assignee Vendor Updated
Open WO #5848-1 404 S Washington St Tenant β€” β€” 2h ago
Open WO #5625-1 826 S Madison St Tenant β€” PDG Mike 1d ago
Open WO #5701-2 1010 Bayview Cir Owner Steven β€” 3h ago
On Hold WO #5715 2517 Elm Creek Dr Tenant β€” Privacy Fence Co. 2d ago
Pending WO #5680 518 Brookelawn Dr Tenant β€” β€” 4d ago

How to scan this view in 10 seconds

  • First pass β€” find your name. Any ticket where you appear as the Assignee gets worked first. (Above: WO #5701-2 is Steven's signature work, only Steven can do it.)
  • Second pass β€” scan the Open rows. Open + unassigned = the pool you pull from. Pick by age (older first) or priority (urgency).
  • Skip Pending and On Hold. Those are waiting on someone else. They'll auto-reopen when ready. Don't waste scan-time on them unless you're investigating why something's stuck.
  • Watch the Updated column. Anything that hasn't moved in 5+ days is a flag β€” either it's genuinely stuck or someone forgot to update the status.