Skip to main content
The Thena platform publishes various events through the platform events system to enable real-time integrations and webhooks. This documentation provides a comprehensive overview of all available events, their payloads, and metadata.

Event categories

The platform publishes events across several categories:
  1. Ticket events - Events related to ticket lifecycle and operations
  2. Account events - Events for account management operations
  3. Organization events - Organization-level events
  4. Comment events - Comment and communication events
  5. User events - User mention and interaction events
  6. Custom object events - Custom object lifecycle events

Developer quickstart

  1. Expose a secure HTTPS endpoint that accepts JSON POST requests.
  2. Parse the incoming body as a platform event and validate required fields.
  3. Enforce idempotency using eventId to avoid duplicate processing.
  4. Route by eventType and process asynchronously; respond 2xx quickly.
  5. Log minimally and filter only the events you need in your subscription.

Minimal webhook handler (Node.js/Express)

import express from "express";

const app = express();
app.use(express.json());

// Simple in-memory idempotency guard (replace with Redis/DB in production)
const seenEventIds = new Set();

app.post("/webhook/platform-events", async (req, res) => {
  const event = req.body;

  // Basic validation
  if (!event?.eventId || !event?.eventType || !event?.payload) {
    return res.status(400).send("Invalid event");
  }

  // Idempotency
  if (seenEventIds.has(event.eventId)) {
    return res.status(200).send("OK");
  }
  seenEventIds.add(event.eventId);

  // Acknowledge early
  res.status(200).send("OK");

  // Async processing by type
  switch (event.eventType) {
    case "ticket:created":
      await handleTicketCreated(event.payload);
      break;
    case "ticket:comment:added":
      await handleCommentAdded(event.payload);
      break;
    default:
      // ignore unhandled events
      break;
  }
});

app.listen(3000, () => console.log("listening on :3000"));

Local testing

  • Use a tunneling tool (for example, ngrok) to expose your local server:
ngrok http 3000
  • Replay a sample event to your endpoint:
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "eventId": "evt_123",
    "eventType": "ticket:created",
    "timestamp": "2024-01-01T10:00:00Z",
    "orgId": "org_123",
    "actor": {"id": "user_1", "type": "AGENT", "email": "agent@acme.com"},
    "payload": {"ticket": {"id": "t_1", "ticketId": "AC-1", "title": "Example"}}
  }' \
  https://YOUR-NGROK-URL/webhook/platform-events

Production checklist

  • Return 2xx quickly; process heavy work asynchronously.
  • Enforce idempotency with a persistent store (for example, Redis) using eventId.
  • Validate payload shape per event page before using fields.
  • Implement retries/backoff in your processors; handle duplicate deliveries.
  • Log eventId, eventType, and orgId for traceability.

Common event structure

All platform events follow a common structure with the following properties:

Base event schema

interface PlatformEvent<T> {
  eventId: string; // Unique identifier for the event
  eventType: string; // Event type identifier (e.g., "ticket:created")
  timestamp: string; // Event timestamp (ISO string or Unix timestamp)
  orgId: string; // Organization ID
  actor: {
    // User who triggered the event
    id: string;
    type: string; // User type (e.g., "AGENT", "CUSTOMER")
    email: string;
  };
  payload: T; // Event-specific payload
  metadata?: Record<string, unknown>; // Optional metadata
}

Event attributes

All platform events include the following attributes for filtering and routing:
  • event_name - The event type (e.g., “ticket:created”)
  • event_id - Unique event identifier
  • event_timestamp - Event timestamp
  • context_user_id - ID of the user who triggered the event
  • context_user_type - Type of the user (AGENT, CUSTOMER, etc.)
  • context_organization_id - Organization ID

Event delivery

Message size limits

All events respect the platform payload size limit of 256KB. If an event payload exceeds this limit, the system automatically truncates large content fields (such as comment content) and replaces them with “Payload too large. Use API instead”.

Retry logic

Failed events are automatically retried with exponential backoff. The system distinguishes between:
  • Transient errors: Network issues, timeouts - automatically retried
  • Permanent errors: Not found errors, validation errors - not retried

Ordering

Where applicable, the platform ensures per-organization ordering of events.

Integration examples

Webhook integration

// Example webhook handler for ticket events
app.post("/webhook/platform-events", (req, res) => {
  const event = req.body;

  switch (event.eventType) {
    case "ticket:created":
      handleTicketCreated(event.payload);
      break;
    case "ticket:comment:added":
      handleCommentAdded(event.payload);
      break;
    // Handle other events...
  }

  res.status(200).send("OK");
});

Event filtering

Use subscription filters to select only the events you need:
{
  "event_name": ["ticket:created", "ticket:updated"],
  "context_organization_id": ["org-123"]
}

Next steps

  • Explore specific event types in the navigation menu
  • Set up platform subscriptions for your integration needs

Support

For questions about our platform events or integration support, please contact our developer support team.
I