Ticqex
Extending Ticqex

Adding a channel

Build your own channel — Slack, chatbots, web forms — by following the email channel pattern.

Ticqex is designed around composable channel and integration registries. The built-in email channel is the reference implementation; a new channel (Slack, a chat widget, a WordPress form, …) follows the same shape.

Concepts

  • Channel (server/channels/<name>/) — product behavior: how conversations work, which ticket fields apply, what the board card shows, and how inbound/outbound messages are handled.
  • Integration (server/integrations/<name>/) — the external provider: declared capabilities (e.g. email.inbound, email.outbound), required env vars, transport functions, and webhook handlers.
  • Activation config binds an enabled channel to an enabled integration with matching capabilities.

A channel definition includes:

  • key and label
  • conversation behavior (e.g. whether public replies can be sent, the label for the contact address)
  • fields — field policies (see below)
  • card — how tickets of this channel render on the board (badges, chips)
  • inbound, outbound, and deliveryEvents handlers
  • optional settings.sections contributing panels to the admin settings UI

Steps

  1. Add keys — register the new channel/integration keys in shared/ticqex-keys/ and extend the config types in shared/ticqex-config/.
  2. Implement the integration under server/integrations/<name>/ (capabilities, required env, transport, webhook verification) and register it in server/integrations/index.ts.
  3. Implement the channel under server/channels/<name>/ with shared client-safe metadata under shared/channels/<name>/, and register it in server/channels/index.ts.
  4. Wire webhooks — the generic dispatcher at /api/webhooks/integrations/[integration] routes incoming requests to your integration's handlers; no new route needed.
  5. Add settings UI (optional) — declare settings.sections on the channel and register the matching component in the settings section registry.
  6. Update the activation config example, enable your channel, and run pnpm config:sync to review the planned field sync.
  7. Test — the registry test suite (tests/unit/channels-registry.test.ts) shows the expected contract.

Field policies

Channels declare policies for ticket fields — which are required, visible, or locked for tickets of that channel. For example, email conversations require a contact address; a task ticket doesn't have one. Policies are enforced server-side so the API and MCP respect them too.

Inbound flow (email as reference)

  1. Provider POSTs a webhook to /api/webhooks/integrations/<integration>.
  2. The integration verifies the signature and normalizes the event.
  3. The channel's inbound handler matches or creates the contact, threads the message into an existing conversation or creates a new ticket in the default inbound status.
  4. Processing runs async in-process via Next.js after() — no external job runner.

Outbound flow

When a staff member (or agent, via API/MCP) replies on a conversation ticket, the channel's outbound handler hands the message to the bound integration's transport, and delivery events (sent, bounced, …) flow back through the webhook into the thread.

On this page