Skip to main content
This guide is written for support leads, CRM operators, and integrators who need to run tickets correctly in Masivo — including when conversations happen on email, WhatsApp, chat, and reviews at the same time. If terms like thread or external_message_id feel unfamiliar, read Tickets & communication (concepts) first, then come back here for practical steps.

Before you start

1

Get your credentials

You need a SERVER API key and your account id (x-account-id). Create keys in the dashboard under Settings → API keys. Never expose SERVER keys in browser code.
2

Know the base URL

All examples use:
Every request also requires:
3

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

API reference pages with schemas: Tickets group in the sidebar.

Part 1 — Creating tickets

1A. Find the pipeline and stage ids

Use the returned pipeline 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.
Tip: Always send an idempotency_key from your integration so network retries do not create duplicate tickets.

1C. Create a ticket from a review

When review_id is present, Masivo:
  1. Creates a ticket with source_type: review
  2. Deduplicates — only one open ticket per review
  3. Links review, customer, and journey associations when available
  4. Creates a review communication thread with the review answers as the first inbound message
After creation, open the ticket in the dashboard Conversation tab — you should see a review channel thread with the submission text.

Part 2 — Reading and updating tickets

2A. Get a ticket (with communication rollup)

Example response (abbreviated — important fields only):
Use 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)

Valid values are scoped to the ticket’s pipeline. Read them from GET /ticket-pipelines; do not hard-code display names. To move between pipelines, send both target values:
Resolving — you must include a resolution summary:
Closing — you must include a closure reason:
Reopening: move back to any open stage. Masivo records 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):
Option B — dedicated assignee endpoints:
Re-adding an existing assignee is safe (idempotent).

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.
Example thread shell:

3B. Create a thread on a ticket

Do this once per external conversation before posting messages.
You must provide at least one of: 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

Messages are ordered chronologically (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)

If message_type is omitted and parent_message_id is set, Masivo defaults to reply.

Internal note (agents only — customer never sees this)

Internal notes do not trigger 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_preview
  • latest_message_channel, latest_message_direction
  • unread_count (+1 for inbound messages without read_at)
The ticket’s 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:
1

Create the ticket

POST /tickets with title/description and optional customer_id.
2

Create email thread

POST /communication/threads with channel: email and provider ids.
3

Ingest customer emails

For each inbound email, POST …/messages with unique external_message_id.
4

Create WhatsApp thread on same ticket

Second POST /communication/threads with channel: whatsapp.
5

Continue conversation on WhatsApp

Post inbound/outbound messages on the WhatsApp thread.
6

Resolve the ticket

PATCH /tickets/{id} with to_stage_code: resolved and resolution_summary.
Verify:

Recipe B — Sync-only integration (your app owns the UI)

  1. Webhook from email provider → map to POST …/threads (if new) + POST …/messages.
  2. Poll GET …/threads?ticket_id= for unread badges.
  3. When agent sends from your UI → POST …/messages with direction: outbound.
  4. Stage changes → PATCH /tickets/{id}.
Always store Masivo’s thread.id and message.id alongside provider ids in your database.

Recipe C — Review → ticket → human follow-up

  1. Customer submits review (existing review API).
  2. POST /tickets with review_id — ticket + review thread created automatically.
  3. Agent reads review in Conversation tab or via messages API.
  4. Create additional threads (email/WhatsApp) if you contact the customer on other channels.
  5. Resolve with resolution_summary when done.

Part 5 — Working in the dashboard

Dashboard actions call the same backend rules as the API (required fields on resolve/close, assignee validation, etc.).

Configure ticket classification

1

Create a top-level category

Open CRM → Categories, choose New category, leave the parent empty, and name the broad problem area, for example Orders.
2

Define its e-commerce scope

Select the Brands, Channels, and Stores available to its subcategories. Leave a selector empty to allow all values for that dimension.
3

Create a subcategory

Choose New category and select its parent. Add a third level when the classification needs it; otherwise the second level can be the leaf.
4

Define the leaf Schema

Add text, long-text, or option fields to the leaf category. Give fields a placeholder when it helps the agent and require only essential information.
5

Save and classify tickets

Save the leaf. The ticket editor now builds the category path one selector at a time, displays its Schema, and applies the top-level availability.
Category configuration and assignment are currently dashboard-only. Ticket API responses expose the selected category in 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

Use 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

Common 400 messages:

Part 8 — Automation hooks

Communication on ticket threads emits journey events you can use in Ticket Journey Triggers: Ticket lifecycle events (TICKET_STAGE_CHANGED, TICKET_RESOLVED, etc.) work the same way.

Frequently asked questions

The ticket is the case you track on the board (stage, priority, assignees, resolution). A thread is one conversation pipe on that case — usually one email chain or one WhatsApp chat. One ticket, many threads.
Performance. Thread list endpoints return shells with latest_message_preview only. Call GET /communication/threads/{id}/messages for full history.
If you integrate with an external inbox: yes. They prevent duplicates when webhooks retry. If you only use the Masivo dashboard manually, Masivo still generates internal UUIDs — but integrations should always send provider ids.
No. Each message belongs to exactly one thread. To link conversations across channels, attach multiple threads to the same ticket.
Each inbound message without 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.
Masivo deduplicates review tickets — if an open ticket already exists for that review_id, the API returns the existing ticket instead of creating a second one.
Public Storefront endpoints documented here are create/list/get only. Soft-delete exists at the database layer for admin operations but is not exposed on these routes.
Use the channel that matches how the customer contacted you: 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_REPLIED and stage changes