Skip to main content
Ticket events are published whenever tickets are created, updated, or undergo state changes. These events are delivered through the platform events system.

Developer quickstart

Minimal handler (tickets only)

app.post("/webhook/platform-events", async (req, res) => {
  const event = req.body;
  if (!event?.eventId || !event?.eventType?.startsWith("ticket:")) {
    return res.status(200).send("OK"); // ignore non-ticket events
  }
  res.status(200).send("OK"); // ack early

  switch (event.eventType) {
    case "ticket:created":
      await onTicketCreated(event.payload);
      break;
    case "ticket:status:changed":
      await onTicketStatusChanged(event.payload);
      break;
    default:
      break;
  }
});

Checklist

  • Use eventId for idempotency; store processed IDs for 24–48h.
  • Fetch full ticket via API if you detect truncated fields.
  • Treat ticket:updated as a meta-event and listen for the derived specific events.
  • Process asynchronously; do not block the HTTP response.

Event types

Core lifecycle events

ticket:created

Triggered when a new ticket is created. Payload structure:
interface TicketCreatedPayload {
  ticket: {
    id: string;
    ticketId: string;
    title: string;
    description: string;
    customerContactFirstName: string;
    customerContactLastName: string;
    customerContactEmail: string;
    priorityId: string;
    statusId: string;
    statusName: string;
    priorityName: string;
    sentimentId: string;
    sentimentName: string;
    source: string;
    createdAt: Date;
    teamId: string;
    teamName: string;
    teamIdentifier: string;
    subTeamId?: string;
    subTeamName?: string;
    subTeamIdentifier?: string;
    isEscalated: boolean;
    customer: {
      id: string;
      email: string;
      name: string;
    };
    assignedTo: string | null;
    assignedAgent: {
      id: string;
      email: string;
      name: string;
    } | null;
    tags?: string[];
    isArchived: boolean;
    customFields?: Record<string, string>;
    metadata?: Record<string, string>;
    aiGeneratedTitle?: string;
    aiGeneratedSummary?: string;
    lastCustomerComment?: Date;
    lastVendorComment?: Date;
    proactiveChannels?: string[];
    isProactive?: boolean;
  };
  comment?: {
    id: string;
    content: string;
    contentHtml: string;
    contentJson: string;
    customerContactId: string;
    createdAt: Date;
  };
}

ticket:updated

Triggered when a ticket is updated. This is a general update event that may trigger additional specific events. Payload structure: Same as ticket:created, but includes:
{
  ticket: TicketPayload;
  previousTicket: TicketPayload; // Previous state of the ticket
}

ticket:deleted

Triggered when a ticket is deleted. Payload structure:
{
  previousTicket: TicketPayload; // The deleted ticket data
}

ticket:archived

Triggered when a ticket is archived.

ticket:unarchived

Triggered when a ticket is unarchived.

State change events

These events are automatically triggered when specific fields change during a ticket:updated event:

ticket:status:changed

Triggered when the ticket status changes.

ticket:priority:changed

Triggered when the ticket priority changes.

ticket:assigned

Triggered when the ticket is assigned to a different agent.

ticket:type:changed

Triggered when the ticket type changes.

ticket:sentiment:changed

Triggered when the ticket sentiment changes.

ticket:escalated

Triggered when a ticket is escalated.

Custom field events

ticket:custom_field_value:added

Triggered when a custom field value is added to a ticket. Additional payload:
{
  changedCustomFields: Array<{
    fieldUid: string;
    newValues: string[];
    changeType: "added";
  }>;
}

ticket:custom_field_value:removed

Triggered when a custom field value is removed from a ticket. Additional payload:
{
  changedCustomFields: Array<{
    fieldUid: string;
    previousValues: string[];
    changeType: "removed";
  }>;
}

ticket:custom_field_value:changed

Triggered when a custom field value is changed on a ticket. Additional payload:
{
  changedCustomFields: Array<{
    fieldUid: string;
    previousValues: string[];
    newValues: string[];
    addedValues?: string[];
    removedValues?: string[];
    changeType: "updated";
  }>;
}

Tag events

ticket:tag:updated

Triggered when tags are added to or removed from a ticket.

Migration events

ticket:migrated

Triggered when a ticket is migrated to a different team. Additional payload:
{
  migration: {
    source: string;
    sourceId: string;
    [key: string]: unknown;
  };
}

Comment events

ticket:comment:added

Triggered when a comment is added to a ticket.

ticket:comment:updated

Triggered when a comment on a ticket is updated.

ticket:comment:deleted

Triggered when a comment is deleted from a ticket.

ticket:comment:reaction:added

Triggered when a reaction is added to a ticket comment.

ticket:comment:reaction:removed

Triggered when a reaction is removed from a ticket comment.

CSAT events

ticket:csat:sent

Triggered when a CSAT survey is sent for a ticket. Additional payload:
{
  csat: {
    id: string;
    feedbackType: string;
    surveyConfig?: any;
    deliveryChannel?: string;
    ruleName: string;
    sentAt?: Date;
    requestorEmail: string;
  };
}

ticket:csat:received

Triggered when a CSAT survey response is received. Additional payload:
{
  csat: {
    id: string;
    feedbackType: string;
    deliveryChannel?: string;
    ruleName: string;
    completedAt?: Date;
    requestorEmail: string;
    ratingValue?: number;
    hasComment?: boolean;
    commentText?: string;
  };
}

SLA events

ticket:sla:breached

Triggered when an SLA breach is detected on a ticket.

ticket:sla:breach_warning

Triggered when an SLA breach warning is detected on a ticket.

Event processing

Automatic event generation

When a ticket:updated event is processed, the system automatically analyzes the changes and generates appropriate specific events:
  1. Status change detection: Compares ticket.status.uid with previousTicket.status.uid
  2. Priority change detection: Compares ticket.priority.uid with previousTicket.priority.uid
  3. Assignment change detection: Compares ticket.assignedAgent.uid with previousTicket.assignedAgent.uid
  4. Custom field change detection: Analyzes custom field values for additions, removals, and changes
  5. Tag change detection: Compares tag sets between current and previous ticket states

Message size management

Ticket events can contain large amounts of data. The system automatically:
  • Monitors payload size (256KB limit)
  • Truncates large content fields when necessary
  • Replaces truncated content with “Payload too large. Use API instead”
  • Logs truncation events for monitoring

Integration examples

Handling ticket creation

function handleTicketCreated(payload) {
  const { ticket } = payload;

  // Send welcome email to customer
  if (ticket.source === "EMAIL") {
    sendWelcomeEmail(ticket.customer.email, ticket.ticketId);
  }

  // Notify assigned agent
  if (ticket.assignedAgent) {
    notifyAgent(ticket.assignedAgent.id, ticket);
  }

  // Log in CRM
  updateCRM({
    customerId: ticket.customer.id,
    ticketId: ticket.id,
    priority: ticket.priorityName,
  });
}

Handling status changes

function handleStatusChange(payload) {
  const { ticket, previousTicket } = payload;

  if (
    ticket.statusName === "Closed" &&
    previousTicket.statusName !== "Closed"
  ) {
    // Ticket was closed
    triggerCSATSurvey(ticket);
    updateMetrics("ticket_closed", ticket.teamId);
  }
}

Custom field monitoring

function handleCustomFieldChange(payload) {
  const { changedCustomFields } = payload;

  changedCustomFields.forEach((change) => {
    if (change.fieldUid === "severity-field-uid") {
      if (change.newValues.includes("Critical")) {
        escalateToManagement(payload.ticket);
      }
    }
  });
}

Best practices

  1. Event filtering: Use platform message attributes to filter for specific event types
  2. Idempotency: Use eventId to ensure idempotent processing
  3. Error handling: Implement proper retry logic for failed event processing
  4. Large payloads: For truncated payloads, use the API to fetch complete data
  5. Performance: Process events asynchronously to avoid blocking ticket operations

Event frequency

Ticket events are high-frequency events, especially in active organizations. Consider:
  • Implementing rate limiting for downstream systems
  • Using batch processing for non-critical integrations
  • Filtering events at the platform subscription level to reduce unnecessary processing
I