Skip to main content

The Problem

When a third-party app (like a form builder, CRM, or bug reporting tool) sends a notification email on behalf of a user, the email comes from the app’s noreply@ address — not the actual customer. This means Halo creates the contact as [email protected] instead of the real user, and:
  • The ticket is linked to the wrong contact
  • The AI agent can’t pull up the customer’s history or context
  • Replies go to the notification address instead of the customer
  • You lose all the structured data from the original form submission
This guide covers two approaches to solve this, depending on your integration capabilities.
If you can make HTTP requests from your app or webhook handler, use the Tickets API to create tickets with proper user association. This is the cleanest solution and what tools like Intercom recommend for programmatic integrations.

How it works

Basic example

curl -X POST https://api.haloagents.ai/api/sdk/tickets/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ab_live_xxxxxxxxxxxxxxxx" \
  -d '{
    "email": "[email protected]",
    "name": "Jane Doe",
    "subject": "Bug: SEO settings missing from Share page",
    "message": "The SEO settings were previously available on the Share page but are now missing.",
    "metadata": {
      "severity": "major",
      "area": "Form Editor"
    },
    "source": "bug_report"
  }'
The ticket is created in your Halo inbox, linked to [email protected], and the AI agent has full context to respond.

Integration examples

Most form builders (Typeform, Tally, JotForm, OrbitForms) support sending webhooks when a form is submitted. Point the webhook at a handler on your backend that calls the Halo Tickets API:
import { NextRequest, NextResponse } from "next/server";

const HALO_API_URL = "https://api.haloagents.ai/api/sdk";
const HALO_API_KEY = process.env.HALOAGENTS_API_KEY!;

export async function POST(request: NextRequest) {
  const submission = await request.json();

  const response = await fetch(`${HALO_API_URL}/tickets/create`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${HALO_API_KEY}`,
    },
    body: JSON.stringify({
      email: submission.email,
      name: submission.name,
      subject: `${submission.type}: ${submission.title}`,
      message: submission.description,
      metadata: {
        severity: submission.severity,
        area: submission.area,
        form_id: submission.form_id,
      },
      source: "contact_form",
    }),
  });

  return NextResponse.json({ received: true });
}

Enabling AI responses

Set "ai_enabled": true to have Halo’s AI agent automatically respond to tickets created via the API. The AI uses your configured email agent and replies to the user’s email address:
{
  "email": "[email protected]",
  "subject": "How do I export my data?",
  "message": "I need to export all my form responses as a CSV.",
  "ai_enabled": true
}
AI responses require AI email auto-reply to be enabled in Settings > AI Agents. The AI agent uses your trained knowledge base to respond, just like it would for email tickets.

Enriching user data

For richer AI context, call the identify endpoint before creating the ticket. This gives the AI access to the user’s plan, role, company, and custom attributes:
// Step 1: Identify the user with full context
await fetch(`${HALO_API_URL}/users/identify`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${HALO_API_KEY}`,
  },
  body: JSON.stringify({
    user_id: "user_123",
    traits: {
      name: "Jane Doe",
      email: "[email protected]",
      plan: "pro",
      role: "admin",
    },
  }),
});

// Step 2: Create the ticket (user is already identified)
await fetch(`${HALO_API_URL}/tickets/create`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${HALO_API_KEY}`,
  },
  body: JSON.stringify({
    user_id: "user_123",
    subject: "Need help with SSO setup",
    message: "We're trying to configure SAML SSO but getting an error.",
    ai_enabled: true,
  }),
});

Approach 2: Email Best Practices

If your integration must send emails (e.g., you can’t modify the third-party app’s webhook behavior), follow these guidelines to help Halo identify the real sender.

Use the customer’s email as the From address

The most effective approach is configuring your notification system to send emails from the customer’s actual email address, not from a noreply@ address:
From: [email protected]           <-- Halo creates the contact as Jane
To: [email protected]
Subject: Bug Report: SEO settings missing
vs.
From: [email protected]   <-- Halo creates the contact as noreply@
To: [email protected]
Subject: Bug Report: SEO settings missing
Sending emails from a customer’s address you don’t control may cause deliverability issues (SPF/DKIM failures). Only do this if you’re sending from a domain you have DNS control over, or if the email provider supports “send as” with proper authentication.

Use the Reply-To header

If you can’t change the From address, set the Reply-To header to the customer’s email. This ensures that when your team replies from Halo, the response goes to the right person:
From: [email protected]
Reply-To: [email protected]
To: [email protected]
Subject: Bug Report: SEO settings missing

Enable forwarded customer detection

If your notification emails include a From: line in the body (common with email forwarding), Halo can automatically extract the original sender.
  1. Go to Settings > Emails > Email Settings
  2. Enable Detect forwarded customers
This works when the email body contains a line like:
From: Jane Doe <[email protected]>
Halo parses this and creates the contact as [email protected] instead of the envelope sender.

Include structured data in the subject

When sending notification emails, put key information in the subject line so it’s visible in the Halo inbox at a glance:
Subject: [Bug Report] Major - Form Editor - SEO settings missing (reporter: [email protected])

Limitations of email-based integrations

IssueImpact
Sender is noreply@Contact linked to wrong email, AI can’t identify the customer
No structured metadataForm fields are buried in email body text
No AI contextAI agent can’t access user’s plan, history, or company info
Reply threadingReplies may not thread correctly if headers are stripped
For these reasons, the Tickets API is strongly recommended over email for third-party integrations.

Comparison

FeatureTickets APIEmail
User identity preservedAlwaysOnly if From is the customer
Structured metadataFull JSON supportPlain text only
AI agent contextFull (user, company, history)Limited
AI auto-replySupported (ai_enabled)Supported (if sender is identified)
No code requiredNo (HTTP request needed)Yes (email forwarding)
Works with Zapier/MakeYesYes
Email threadingN/ANative

Next Steps

Tickets API Reference

Full API reference for creating tickets programmatically.

Identify Users

Enrich user records with traits and context before creating tickets.

Receiving Emails

Set up email forwarding from your existing support address.

Automatic Ticket Creation

Create tickets through the AI chat pipeline for triage and auto-response.