Skip to main content
Host: the API is hosted at helpmesh.io. Don't use app.helpmesh.io — that's the dashboard subdomain and is interpreted as a tenant slug (you'll get HM-TENANT-NOT_FOUND). The official @helpmesh-io/sdk uses the correct host by default.
Authentication: Include your API key as a Bearer token in the Authorization header.
Versioning: the OpenAPI spec carries an info.version that tracks the API contract — it bumps when endpoints, request bodies, or response shapes change. The HelpMesh product version (shown on /changelog and in the npm SDK) tracks the whole platform and bumps far more often. The two move independently. Pin to the URL path — /api/v1 — that's the only breaking-change boundary you need to care about.

Threads

Manage customer support threads. Each thread represents a conversation with a customer across any channel.

Code samples

Query Parameters

NameTypeDescription
status optionalstringFilter by status: open, pending, resolved, closed
cursor optionalstringPagination cursor from previous response
limit optionalintegerNumber of results per page (default: 20, max: 100)
Example Request (curl)
curl https://helpmesh.io/api/v1/threads \
  -H "Authorization: Bearer $HELPMESH_API_KEY"
Response 200
{
  "data": [
    {
      "id": "thr_01H8X3YVKM",
      "subject": "Cannot access my dashboard",
      "status": "open",
      "priority": "high",
      "channel": "email",
      "assignee": {
        "id": "usr_01H8X3Z",
        "name": "Sarah Chen"
      },
      "customer": {
        "id": "cst_01H8X4A",
        "email": "user@example.com"
      },
      "createdAt": "2026-07-11T08:47:33Z",
      "updatedAt": "2026-07-11T11:37:33Z"
    }
  ],
  "meta": {
    "cursor": "eyJpZCI6InRocl8wMUg4WDNZVktNIn0",
    "hasMore": true,
    "total": 142
  }
}

Request Body

NameTypeDescription
title requiredstringTicket title (industry shape). Aliases: subject (strict shape).
body requiredstringInitial message body (text or sanitized HTML).
requester requiredobjectCustomer: { email, name? } — auto-upserts the Customer record on create.
external_reference_id optionalstringYour internal ticket id. Repeated POSTs with the same value return the existing thread (idempotent retry).
tags optionalstring[]Free-form tags. Auto-converted to tenant Labels on create.
inboxId optionalstringTarget inbox. If omitted, routes to the tenant's isDefault inbox (or the oldest active EMAIL/API inbox as fallback).
priority optionalstringPriority: LOW, NORMAL, HIGH, URGENT (default: NORMAL).
channel optionalstringOrigin channel: EMAIL, API, WIDGET, SLACK, WHATSAPP, SMS, VOICE (default: API).
Example Request (curl)
curl -X POST https://helpmesh.io/api/v1/threads \
  -H "Authorization: Bearer $HELPMESH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Cannot access my dashboard",
    "body": "I am getting a 403 error on the analytics page.",
    "requester": { "email": "user@example.com", "name": "Jane Doe" },
    "external_reference_id": "your-ticket-id-1f18d868",
    "tags": ["billing", "p1"]
  }'
Request Body Schema
// Industry-compatible shape (recommended — used by Zendesk / Freshdesk / Intercom integrators)
{
  "title": "Cannot access my dashboard",
  "body": "I'm getting a 403 error when trying to access the analytics page.",
  "requester": {
    "email": "user@example.com",
    "name": "Jane Doe"
  },
  "external_reference_id": "your-ticket-id-1f18d868",
  "tags": ["billing", "p1"]
}

// Response includes the HelpMesh ticket number for your ticket-mapping table:
// {
//   "data": {
//     "id": "cmoo7nqw200072cwp7r6yu5qr",
//     "publicNumber": 16,
//     "ticketNumber": "PRO-6-000016",
//     "externalRef": "your-ticket-id-1f18d868",
//     ...
//   }
// }

// Strict id-based shape (for callers that already have inboxId + customerId):
{
  "inboxId": "inb_01H8X4A",
  "customerId": "cst_01H8X4A",
  "subject": "Cannot access my dashboard",
  "body": "I'm getting a 403 error when trying to access the analytics page.",
  "channel": "API",
  "priority": "HIGH"
}