Core Concepts
Understand the building blocks of Dispatch Tickets. Every resource in the API maps to one of these concepts.
Overview
Dispatch Tickets is organized around a simple hierarchy. An account owns one or more brands. Each brand is an isolated container of tickets, customers, statuses, and configuration. This makes it easy to support multiple products, clients, or business units from a single API integration.
Account
└── Brand (isolated ticket container)
├── Tickets
│ ├── Comments
│ ├── Attachments
│ └── Watchers
├── Customers & Companies
├── Statuses (system + custom)
├── Categories
└── TagsBrands
A brand (also called a workspace) is the top-level container for all ticketing data. Each brand has its own customers, statuses, categories, tags, and email configuration. Data is fully isolated between brands.
Common uses for multiple brands:
- Separate support queues for different products
- Client-specific inboxes for agencies
- Regional support teams (US, EU, APAC)
- Departmental separation (Support, Sales, Billing)
const brand = await dispatch.brands.create({
name: 'Acme Support',
slug: 'acme', // Used in email addresses
});
console.log(brand.id); // 'br_abc123'Every API endpoint that accesses tickets, comments, or other data is scoped to a brand via /brands/:brandId/....
Tickets
Tickets are the core resource. Each ticket has a title, status, priority, and optional fields like assignee, customer, category, tags, and custom fields.
const ticket = await dispatch.tickets.create('br_abc123', {
title: 'Cannot access my account',
customerEmail: '[email protected]',
customerName: 'Jane Doe',
priority: 'high',
source: 'email',
customFields: {
orderId: 'ORD-12345',
plan: 'enterprise',
},
});
console.log(ticket.ticketNumber); // 'DT-1042'Ticket Fields
| Field | Type | Description |
|---|---|---|
| title | string | Short summary of the issue |
| status | string | Current status (open, pending, resolved, closed, or custom) |
| priority | string | low, normal, high, or urgent |
| source | string | Channel origin (api, email, web, slack, etc.) |
| customFields | object | Any JSON data (schemaless) |
| customerEmail | string | Auto-creates or links to existing customer |
Source Tracking
Every ticket tracks where it came from. The source field records the channel (api, email, web, slack, sms, etc.), sourceId stores the original ID from that channel, and sourceData holds channel-specific metadata as JSON.
Comments
Comments are the conversation thread on a ticket. Each comment has a body (text or HTML), an author, and an author type indicating whether it came from a staff member or customer.
const comment = await dispatch.comments.create('br_abc123', 'tkt_def456', {
body: 'Thanks for reaching out! Let me look into this.',
authorType: 'STAFF',
authorName: 'Support Team',
authorEmail: '[email protected]',
});Author Types
STAFF- Team member reply (visible to customer in notifications)CUSTOMER- Customer reply (triggers notification to assignee)SYSTEM- Automated message (status changes, assignments)
Comments can also include attachments and support threading via the parentId field for nested replies.
Customers & Companies
Customers are automatically created when a ticket includes a customerEmail that doesn't already exist. You can also create customers explicitly.
// Customer is created automatically from ticket data
await dispatch.tickets.create('br_abc123', {
title: 'Billing question',
customerEmail: '[email protected]',
customerName: 'New Customer',
});
// A customer record now exists for [email protected]Customers can be grouped into companies for B2B use cases. Companies let you see all tickets from an organization in one place and apply shared settings.
Customer Fields
email- Primary identifier (unique per brand)name- Display namecompany- Optional company associationcustomFields- Any additional metadata as JSON
Statuses
Every brand starts with four system statuses: open, pending, resolved, and closed. You can add custom statuses to match your workflow.
For a deep dive into status configuration and lifecycle management, see the Statuses & Workflows guide.
Categories & Tags
Categories provide a single, structured classification for each ticket (e.g., "Billing", "Technical", "Feature Request"). A ticket can have one category.
Tags are flexible labels that can be applied to tickets for filtering and organization. A ticket can have multiple tags (e.g., "urgent", "enterprise", "bug").
const ticket = await dispatch.tickets.create('br_abc123', {
title: 'Feature request: Dark mode',
customerEmail: '[email protected]',
categoryId: 'cat_billing',
tagIds: ['tag_feature', 'tag_enterprise'],
});Both categories and tags are managed per brand. Create them in the dashboard under Settings → Brand → Categories / Tags, or via the API.
Attachments
Attachments are files uploaded to tickets or comments. Files are stored in Cloudflare R2 and accessed via presigned URLs. Files never pass through the API server directly.
Upload Flow
- Request an upload URL from the API
- Upload the file directly to the presigned URL
- Confirm the upload to finalize the attachment
// 1. Request upload URL
const upload = await dispatch.attachments.requestUpload('br_abc123', 'tkt_def456', {
filename: 'screenshot.png',
contentType: 'image/png',
});
// 2. Upload directly to presigned URL
await fetch(upload.uploadUrl, {
method: 'PUT',
body: file,
headers: { 'Content-Type': 'image/png' },
});
// 3. Confirm the upload
await dispatch.attachments.confirm('br_abc123', 'tkt_def456', upload.id);Download URLs are also presigned and time-limited. Request a fresh download URL each time rather than caching them.