How to Intake Maintenance Requests by Email into Monday for Property Managers

Build a Spojit workflow that watches a shared maintenance mailbox, uses an Agent-mode Connector node to classify each request by urgency and category, logs it as an item on your Monday.com property-management board, and escalates true emergencies to your on-call manager in Slack.

What This Integration Does

Property managers usually collect repair and maintenance requests in a shared inbox like maintenance@ on Gmail or Outlook. Those emails arrive in free-form text from tenants who describe the problem in their own words, rarely tagging the unit, the category, or how urgent it is. This workflow reads each new email, asks the intelligent layer across your automation to pull out the structured details (unit number, tenant name, category, and urgency), and writes a clean, consistent ticket onto a Monday.com board so your team works from one prioritized queue instead of an overflowing mailbox.

An Email trigger polls the connected mailbox on a fixed interval and starts one run per new message. Each run passes the raw email through an Agent-mode Connector node that returns a strict JSON object, creates exactly one Monday item with create-item, and then a Condition node checks the classified urgency. If the request is an emergency (for example a burst pipe or no heat), Spojit posts a Slack message to your on-call channel. Re-runs are per-message: each email is processed once when the poll picks it up, so logging a ticket twice is avoided as long as you keep the trigger pointed at a single mailbox.

Prerequisites

  • A Gmail (trigger) or Outlook (trigger) connection on the shared maintenance mailbox, added under Connections -> Add connection. Read-only access is enough; you only need Read+modify if you plan to mark messages read after processing.
  • A Monday.com connection (API token) and a property-management board. Note the board ID, the group ID where new tickets should land, and the column IDs for the columns you want to populate (status, text, and so on).
  • A Slack connection with permission to post to your on-call channel, plus the channel ID or name.
  • The json utility connector is built in and needs no setup; you will use it to read fields out of the classification result.

Step 1: Start with an Email trigger on the maintenance mailbox

Add a Trigger node and set Trigger Type to Email. Select your Gmail or Outlook trigger connection and pick the folder to watch (typically INBOX). Set the poll interval (1-60 minutes, default 2). Optionally tighten the scope with a Subject regex or a From allowlist if tenants always send from a known portal address. The trigger output for each message is available downstream as {{ input }} and includes {{ input.from }}, {{ input.subject }}, {{ input.textBody }}, {{ input.htmlBody }}, {{ input.receivedAt }}, and an attachments list of references.

Step 2: Classify the request with an Agent-mode Connector node and a Response Schema

Add a Connector node and switch it to Agent mode. This lets the agent read the messy email body and return structured fields. Give it a prompt that names exactly what you need extracted, then attach a Response Schema so the output is always valid JSON you can map into Monday. A prompt like this works well:

You are triaging a property maintenance request.
Read the email subject and body and return:
- unit: the unit or apartment number mentioned, or "unknown"
- tenant: the tenant's name, or "unknown"
- category: one of plumbing, electrical, hvac, appliance, structural, pest, other
- urgency: one of emergency, high, normal, low
- summary: a one-sentence plain-text summary

Subject: {{ input.subject }}
Body: {{ input.textBody }}

Set the Response Schema to force the shape, so every run returns the same keys:

{
  "type": "object",
  "properties": {
    "unit": { "type": "string" },
    "tenant": { "type": "string" },
    "category": { "type": "string",
      "enum": ["plumbing","electrical","hvac","appliance","structural","pest","other"] },
    "urgency": { "type": "string",
      "enum": ["emergency","high","normal","low"] },
    "summary": { "type": "string" }
  },
  "required": ["unit","tenant","category","urgency","summary"]
}

Bind the result to an output variable, for example triage, so the parsed object is available as {{ triage }}. Agent mode uses AI credits; the Response Schema keeps the output predictable enough for the deterministic steps that follow. To learn when to reach for Agent mode versus a fixed tool call, see how to choose between Agent Mode and Direct Mode.

Step 3: Read individual fields with the json connector (optional)

The Response Schema already returns a structured object, but if you want to normalize or default any value before writing to Monday, add a Connector node on the json connector in Direct mode and use get to pull a single field. For example, get with a path of urgency against {{ triage }} isolates the urgency string you will branch on later. You can also use set to fill in a fallback when unit comes back as "unknown". For straightforward workflows you can skip this step and reference {{ triage.urgency }} and the other fields directly.

Step 4: Log the ticket on your Monday board with create-item

Add a Connector node on the monday connector in Direct mode and choose the create-item tool. Map the fields:

  • boardId: your property-management board ID.
  • name: a readable title, for example Unit {{ triage.unit }} - {{ triage.category }}: {{ triage.summary }}.
  • groupId: the group where new tickets land, such as your "New Requests" group.
  • columnValues: a structured object keyed by your board's column IDs.

A typical columnValues object maps the classified fields onto your status and text columns (replace the keys with your real column IDs):

{
  "status": { "label": "{{ triage.urgency }}" },
  "text_unit": "{{ triage.unit }}",
  "text_tenant": "{{ triage.tenant }}",
  "long_text_summary": { "text": "{{ triage.summary }}" },
  "text_from": "{{ input.from }}"
}

The node returns the created item, including its ID, which you can reuse downstream (for example in the Slack escalation). For a deeper walk-through of building Monday items from email, see how to create Monday.com tasks from emails.

Step 5: Branch on urgency with a Condition node

Add a Condition node after the Monday step. Set the test to compare the classified urgency against the emergency value, for example check that {{ triage.urgency }} equals emergency. The True branch handles escalation; the False branch ends the run, since the ticket is already on the board for normal triage. Keeping the comparison tied to the enum from your Response Schema means the branch stays reliable run after run. For more on building these tests, see using Condition nodes.

Step 6: Escalate emergencies to Slack with send-message

On the True branch, add a Connector node on the slack connector in Direct mode and choose the send-message tool. Point it at your on-call channel and compose a message that gives the manager everything needed to act without opening the board:

EMERGENCY maintenance request
Unit: {{ triage.unit }}
Tenant: {{ triage.tenant }}
Category: {{ triage.category }}
Summary: {{ triage.summary }}
From: {{ input.from }}
Logged on Monday board as a new ticket.

If you want the on-call manager to acknowledge before the run finishes, you can add a Human approval node ahead of or after the Slack message; see using Human approval nodes. For a fuller pattern that combines email and Slack alerts, see setting up multi-channel notifications.

Tips

  • Keep the Email trigger pointed at one shared mailbox. If several people forward requests from their own inboxes, consider a Mailhook trigger instead, where you control a dedicated Spojit address that tenants or systems mail directly.
  • Start the poll interval at 5 minutes while testing, then tighten it to 1-2 minutes once the workflow is stable to keep response times low for emergencies.
  • Use the same enum values in the Response Schema, the Condition test, and your Monday status column so a status label always matches a valid choice on the board.
  • If you populate a Monday status column, make sure the labels you write in columnValues already exist on that column, or the item will be created without the status set.

Common Pitfalls

  • Monday column IDs are not the column titles. Open the board's column settings to copy the real IDs (for example status, text_unit) before mapping columnValues.
  • Without a Response Schema, an Agent-mode node can return prose instead of JSON, which breaks the downstream mapping. Always attach the schema and reference the fields with {{ triage.field }}.
  • Read-only mailbox access cannot mark messages as read or move them. If you rely on after-processing actions, the trigger connection needs Read+modify access; otherwise leave those options off.
  • The Email trigger fires once per message at poll time. Avoid pointing two enabled workflows at the same folder, or each email will create two tickets.
  • If a tenant omits the unit or their name, the model returns "unknown". Decide in the json step or the Monday mapping whether that should still create a ticket (recommended) or route to a follow-up.

Testing

Before enabling the trigger, send a few sample emails to the maintenance mailbox that cover each urgency level, including one clear emergency such as "No hot water and water leaking from the ceiling in unit 4B." Let the poll pick them up, then open the run in execution history and inspect the Agent-mode output to confirm {{ triage.urgency }} and {{ triage.category }} match what you expect. Verify one new item appears on the Monday board with the right group, title, and column values, and confirm the emergency email posted to your Slack on-call channel while the normal ones did not. Once a small batch behaves correctly, tighten the poll interval and let it run live.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.