Endpoint
noreply@app.com), this endpoint lets you explicitly specify who the ticket is from.
Authentication
Requires your publishable widget key in theAuthorization header:
org_id is derived from the widget key.
Use your widget key from Setup > Install. It is publishable (safe in browser code). Enable Identity Verification when scoping requests by
user_id.Request Body
User Identification
At least one ofuser_id or email is required. If the user doesn’t exist yet, they are created automatically.
When identity verification is enforced for your workspace,
user_id plus a valid user_token (or user_hash) is required. The email-only path returns HTTP 403 in that mode, because the widget key is public and an unverified email could open tickets on any contact’s record. See Identity Verification.string
Your system’s unique identifier for this user. If provided, Halo looks up the user by
external_id first.string
The user’s email address. Used as a fallback lookup if
user_id doesn’t match, or as the primary identifier if user_id is omitted. Also used for email notifications and AI agent replies.string
The user’s display name. Used when creating a new user record, or to enrich context if the user already exists.
Ticket Content
string
required
The ticket subject line. This appears as the ticket title in your inbox. Max 1,000 characters.
string
The full ticket body / description. If omitted, the
subject is used as the initial message. Max 50,000 characters.object
Arbitrary key-value data attached to the ticket. Visible to your team in the dashboard and accessible to the AI agent. Max 50,000 bytes. Use this for structured form data, severity levels, categories, etc. It is stored under the ticket’s
metadata.api_metadata key, so it never overwrites system fields.Options
string
default:"api"
A label identifying where the ticket came from (e.g.,
"contact_form", "bug_report", "webhook"). Max 50 characters. The ticket’s channel is set to one of chat, support, sales, help_center, in_app_message, or api. Any other value, including "email", is recorded as api, and your original label is kept in the ticket’s metadata.requested_source. Email-channel tickets cannot be created through this endpoint.string
default:"normal"
Set to
"priority" to mark the ticket as high priority. Otherwise defaults to "normal" (open status).boolean
default:"false"
When
true, the AI agent is triggered to respond to this ticket automatically (using your configured email AI agent). Requires AI email auto-reply to be enabled in your settings. Only honoured for a verified user (identity verification enforced, valid user_token/user_hash). The AI replies to the email already stored on that user’s record, never to an email passed in the request body. Otherwise the flag is ignored and your team replies from the inbox.Example
User Resolution Logic
The endpoint resolves users in this order:- By
user_id— looks upend_users.external_idmatching youruser_id - By
email— falls back toend_users.emaillookup - Auto-create — if no match is found, creates a new end user with the provided
email,name, anduser_id
What Happens After Creation
- The ticket appears in your Halo inbox immediately
- Your team is notified via Slack and email (if configured)
- If
ai_enabledistrue, the user is verified, and your AI email agent is configured, the AI processes the ticket and replies to the email stored on the user’s record - The user record is created or linked, so the AI has full context for future interactions