Before you start
Get your credentials
x-account-id). Create keys in the dashboard under Settings → API keys. Never expose SERVER keys in browser code.Know the base URL
Pick your workflow
- Dashboard only: use CRM → Tickets for day-to-day work.
- Integration: your mail/helpdesk connector creates threads + messages via API; agents work in Masivo or your UI.
- Hybrid: reviews create tickets automatically; agents reply via API or dashboard.
Quick reference — all ticket & communication endpoints
Part 1 — Creating tickets
1A. Find the pipeline and stage ids
id and stage code. If both are omitted when creating a ticket, Masivo uses the account’s default pipeline and that pipeline’s default stage.
Pipeline administration is dashboard-only under CRM → Pipelines. The
Storefront API intentionally exposes discovery through GET /ticket-pipelines
but does not expose create, update, or delete pipeline endpoints.
1B. Create a manual ticket
Use when an agent or your system opens a case without a linked review.idempotency_key from your integration so network retries do not create duplicate tickets.
1C. Create a ticket from a review
Whenreview_id is present, Masivo:
- Creates a ticket with
source_type: review - Deduplicates — only one open ticket per review
- Links review, customer, and journey associations when available
- Creates a review communication thread with the review answers as the first inbound message
review channel thread with the submission text.
Part 2 — Reading and updating tickets
2A. Get a ticket (with communication rollup)
communication_summary on list/board views. Load full threads only when the user opens the conversation.
2B. Update title, description, or priority
2C. Change stage (move on the board)
GET /ticket-pipelines; do not hard-code display names.
To move between pipelines, send both target values:
reopened_at when leaving a closed-type stage. An inbound customer reply also reopens the ticket automatically in the first open stage of its current pipeline.
You can combine stage changes with assignee updates in the same PATCH request.
2D. Manage assignees
Option A — via PATCH (common in integrations):Part 3 — Communication threads (the conversation layer)
Mental model
- One ticket can have many threads (e.g. email + WhatsApp).
- Each thread belongs to one channel and optionally maps to an external provider thread id.
- Messages always belong to exactly one thread.
3A. List threads for a ticket
Returns summaries only — not message bodies.3B. Create a thread on a ticket
Do this once per external conversation before posting messages.ticket_id, review_id, customer_id, or external_thread_id.
If you POST again with the same (channel, channel_account_id, external_thread_id), Masivo returns the existing thread — this is intentional.
3C. List messages in a thread
sent_at, then created_at). Pagination default: rows 0–99, max range 200.
3D. Post messages
Inbound customer email (first message in thread)
Agent outbound reply (linked to parent)
message_type is omitted and parent_message_id is set, Masivo defaults to reply.
Internal note (agents only — customer never sees this)
TICKET_CUSTOMER_REPLIED or TICKET_AGENT_REPLIED.
Message field cheat sheet
What updates automatically when you post a message
Masivo updates the parent thread:latest_message_id,latest_message_at,latest_message_previewlatest_message_channel,latest_message_directionunread_count(+1 for inbound messages withoutread_at)
communication_summary updates the next time you GET /tickets/{id}.
Part 4 — End-to-end recipes
Recipe A — Angry email, then resolve on WhatsApp
Real pattern from multi-channel support:Create the ticket
POST /tickets with title/description and optional customer_id.Create email thread
POST /communication/threads with channel: email and provider ids.Ingest customer emails
POST …/messages with unique external_message_id.Create WhatsApp thread on same ticket
POST /communication/threads with channel: whatsapp.Continue conversation on WhatsApp
Resolve the ticket
PATCH /tickets/{id} with to_stage_code: resolved and
resolution_summary.Recipe B — Sync-only integration (your app owns the UI)
- Webhook from email provider → map to
POST …/threads(if new) +POST …/messages. - Poll
GET …/threads?ticket_id=for unread badges. - When agent sends from your UI →
POST …/messageswithdirection: outbound. - Stage changes →
PATCH /tickets/{id}.
thread.id and message.id alongside provider ids in your database.
Recipe C — Review → ticket → human follow-up
- Customer submits review (existing review API).
POST /ticketswithreview_id— ticket + review thread created automatically.- Agent reads review in Conversation tab or via messages API.
- Create additional threads (email/WhatsApp) if you contact the customer on other channels.
- Resolve with
resolution_summarywhen done.
Part 5 — Working in the dashboard
Configure ticket classification
Create a top-level category
Orders.Define its e-commerce scope
Create a subcategory
Define the leaf Schema
Save and classify tickets
category_id and its dynamic
field values in category_answers; storefront create and patch inputs do not
accept these fields.
Part 6 — Pagination and limits
from/to as inclusive row indices (not page numbers). Example: next page of threads → from=50&to=99.
Part 7 — Errors and how to fix them
400 messages:
Part 8 — Automation hooks
Communication on ticket threads emits journey events you can use in Ticket Journey Triggers:TICKET_STAGE_CHANGED, TICKET_RESOLVED, etc.) work the same way.
Frequently asked questions
What is the difference between a ticket and a thread?
What is the difference between a ticket and a thread?
Why does GET /threads not return message text?
Why does GET /threads not return message text?
latest_message_preview only. Call GET /communication/threads/{id}/messages
for full history.Do I need external_thread_id and external_message_id?
Do I need external_thread_id and external_message_id?
Can one message belong to two threads?
Can one message belong to two threads?
How does unread_count work?
How does unread_count work?
read_at increments the thread’s
unread_count. The ticket communication_summary.unread_count sums all
threads on that ticket. Mark as read by posting/updating with read_at set
(future API) or via dashboard consumption.What happens if I create two tickets for the same review?
What happens if I create two tickets for the same review?
review_id, the API returns the existing ticket instead of creating a second
one.Can I delete a thread or message via API?
Can I delete a thread or message via API?
Which channel value should I use?
Which channel value should I use?
email, whatsapp, chat, review (auto for review submissions), system, or other. The channel on a message defaults to its thread’s channel if omitted.Checklist before going to production
- SERVER API key stored securely on your backend
- Every create-ticket call sends
idempotency_key - Every synced message sends
external_message_id - Every synced thread sends
external_thread_id+channel_account_id - Resolve/close flows collect
resolution_summary/closure_reason - Your UI loads thread shells first, messages on demand
- Journey automations tested for
TICKET_CUSTOMER_REPLIEDand stage changes
Related documentation
- Tickets & communication (concepts) — diagrams and field definitions
- Ticket Journey Triggers — automate on ticket events
- Create and manage review forms — review → ticket pipeline
- API reference — Tickets group in the sidebar