Skip to content
Skip to main content

Monitor an inbox for support tickets

Most support ticket systems start the same way: an email lands in a shared inbox, someone reads it, decides where it should go, and forwards it along. That triage step is the bottleneck. It delays response times, leads to misrouted tickets, and disappears entirely outside business hours.

This recipe replaces the triage step with a webhook handler. Instead of polling an inbox, Nylas pushes a notification the moment a message arrives. Your code inspects the subject, body, and sender domain, applies routing rules, and hands the ticket to whatever system you use — Jira, Zendesk, a database, a Slack channel. Same code works for Google, Microsoft, and IMAP accounts.

If you want a lighter classify-and-archive flow on a personal inbox, see the email triage agent instead. This recipe is for shared support inboxes where tickets need to fan out to teams.

inbound message ─▶ message.created webhook ─▶ verify signature
skip auto-replies / bounces
fetch full body if truncated
keyword scan (subject + body) → category
sender domain check → priority adjust
route to ticket system

Six steps. The classification logic is intentionally simple keyword + domain matching so you can swap in your own rules without touching the webhook plumbing.

Make sure you have the following before starting this tutorial:

  • A Nylas account with an active application
  • A valid API key from your Nylas Dashboard
  • At least one connected grant (an authenticated user account) for the provider you want to work with
  • Node.js 18+ or Python 3.8+ installed (depending on which code samples you follow)

You also need:

  • A publicly accessible HTTPS endpoint for Nylas to send webhook notifications to. During development, use VS Code port forwarding or Hookdeck to expose your local server.
  • Express (Node.js) or Flask (Python) installed in your project.

Create a webhook subscription that listens for the message.created trigger. This tells Nylas to send a POST request to your endpoint every time a new message arrives in any connected grant.

Replace <NYLAS_API_KEY> with your API key from the Nylas Dashboard and <YOUR_WEBHOOK_URL> with the public HTTPS URL where your server is listening.

Nylas returns the webhook object with a webhook_secret. Save this value. You need it to verify incoming notifications.

The moment you create the webhook (or reactivate one), Nylas sends a GET request to your endpoint with a challenge query parameter. Your server must return the exact value of that parameter in a 200 response within 10 seconds. If it doesn’t, the webhook stays inactive and Nylas won’t retry.

# Nylas sends something like this:
GET <YOUR_WEBHOOK_URL>?challenge=bc609b38-c81f-47fb-a275-1d9bd61a968b

Your server returns:

200 OK
bc609b38-c81f-47fb-a275-1d9bd61a968b

No JSON wrapping, no extra whitespace, no chunked encoding. Just the raw challenge string in the response body.

Once the webhook is active, Nylas sends a POST request to your endpoint for every new message. The payload includes the message object (or a truncated version if it exceeds 1 MB). Your handler needs to do three things: verify the signature, parse the notification, and fetch the full message if needed.

Now that you have the full message, you can inspect its content and decide where it should go. The processMessage function below checks the subject line and body for keywords, looks up the sender’s domain, and assigns a category and priority.

KeywordsCategoryDefault priority
urgent, down, outage, critical, brokenIncidentsHigh
bug, error, crash, not working, issueBugsMedium
billing, invoice, charge, refund, paymentBillingMedium
feature, request, suggestion, would be niceFeature requestsLow
cancel, unsubscribe, close accountChurn riskHigh

Not every incoming message is a real support request. Auto-replies, out-of-office messages, and delivery failure notifications should be filtered out before your routing logic runs.

A production-ready webhook handler needs to deal with several real-world scenarios that don’t show up during development.

Nylas guarantees at-least-once delivery. That means your endpoint might receive the same notification more than once, especially if your server was slow to respond the first time. Track processed message IDs and skip duplicates:

When a message exceeds 1 MB (common with large attachments or rich HTML), Nylas sends a message.created.truncated notification with the body removed. The handler code above already covers this: check the trigger type for .truncated or check whether the body field is missing, then fetch the full message from the API.

You don’t need to subscribe to a separate message.created.truncated trigger. Nylas sends it automatically on the same webhook subscription.

If your inbox receives a burst of messages, your handler will fire multiple fetch calls to the Nylas API in quick succession. Respect the rate limits by adding a simple queue or delay:

Beyond auto-replies, consider filtering out:

  • Calendar invitations that generate email notifications
  • Messages from your own application (check if the sender matches your support address to avoid infinite loops)
  • Messages in Sent or Drafts folders that trigger message.created when synced

You can check the folder by looking at the folders array on the message object. If it contains SENT or DRAFTS, skip processing.

You have two options for testing without waiting for real email to arrive.

Option 1: Use the Nylas Send Test Event endpoint

Section titled “Option 1: Use the Nylas Send Test Event endpoint”

Nylas provides a Send Test Event endpoint that sends a mock message.created payload to your webhook URL. This confirms your endpoint is reachable and your signature verification works:

Send an email to the inbox connected to your Nylas grant with a subject like “Urgent: Production database is down” or “Billing question about last invoice.” Watch your server logs to confirm the webhook fires, the message gets categorized correctly, and the routing logic triggers.

  • At-least-once delivery means dedup is your problem. Nylas may deliver the same message.created notification more than once — usually because your handler was slow on the first attempt. Track processed message IDs in Redis or a database table with a TTL. An in-memory Set won’t survive a restart.
  • Truncated payloads come through the same subscription. When a message exceeds 1 MB (large attachments, rich HTML), Nylas sends message.created.truncated on the same webhook with the body removed. Detect it (suffix or missing body) and refetch the full message from the API.
  • Filter your own outbound. Sent messages also fire message.created for the connected mailbox. Check the folders array for SENT or DRAFTS and skip — otherwise your handler will route the team’s outgoing replies as new tickets.
  • Out-of-office replies are noise. Detect them by auto-submitted headers, precedence: bulk, and subject patterns (“out of office”, “automatic reply”). Don’t ship a ticket monitor that creates a ticket every time a customer goes on vacation.
  • Respond 200 fast, process async. Nylas considers a slow response a failed delivery and retries. Acknowledge immediately, queue the work, and process behind the response.