Zaapi Zaapi Developer
Open Zaapi

Zaapi Open API Platform (1.0.0)

Read and manage your Zaapi store data programmatically.

The Zaapi Open API Platform lets you access your store's data directly from your own systems, without going through the Zaapi App.

Getting started

1. Generate an API key

API keys are created and managed by you, inside the Zaapi App. There is no separate application or approval step, and no client secret to exchange.

  1. Open the Zaapi App and go to Settings → Developers.
  2. Select Add API key.
  3. Give the key a name that describes where it will be used, for example Warehouse sync or Reporting dashboard.
  4. Tick the scopes the key should have — at least one is required. A key can only call endpoints covered by the scopes you grant it — see Scopes below. Ticking a write scope also grants the matching read scope.
  5. Select Create, then copy the key.

The key is shown once, at creation. Store it somewhere safe before closing the dialog — you will not be able to see it again. Keys start with zaapi_. The table on the Developers page only shows a masked value (zaapi_•••••••• plus the last four characters).

If you lose the secret you don't have to start over. Use Rotate key on that row: it issues a new secret, keeps the name and scopes, and restarts the 6-month expiry.

Keys expire 6 months after they are created or last rotated. The expiry date is on the Developers page. An expired key is rejected with 401. Rotate before that date if the integration should keep working.

2. Send the key with every request

Pass the key in the x-api-key header. There is no bearer token, no Authorization header, and no token refresh — the key itself is the credential. A signed request, and the 401 / 403 bodies you get back when the header is missing, unrecognised, or under-scoped, are shown in the samples panel.

Every request is authenticated and scope-checked before it reaches your store's data. A request with no x-api-key header, or an unrecognised, inactive, expired, or deleted key, is rejected with 401. A valid key missing the scope an endpoint requires is rejected with 403. On success the request is scoped to your store, so a caller can only ever see their own data.

3. Keep the key safe

A key carries the scopes you granted it and acts on your store, so treat it like a password.

  • Send it only from a server you control. Never embed a key in a mobile app, a browser page, or any client-side code, where it can be read by anyone.
  • Use a separate key per integration. If one has to be deleted, the others keep working.
  • Grant only the scopes an integration actually needs. A reporting tool that only reads data should not hold write scopes. The form has a Read only shortcut that selects every read scope and none of the write scopes.
  • Rotate a key if it may have been exposed, if you lost the secret, or before it expires. Rotating is the usual response to a leaked or lost key, and it restarts the 6-month expiry.
  • Delete a key when the integration using it is being retired.

4. Edit, rotate, or delete a key

Each of these lives on the key's ⋮ menu on Settings → Developers.

Editing renames the key or changes its scopes. The secret itself does not change, and nothing is shown again — integrations already using the key keep working. Taking a scope away starts failing those calls with 403 on the next request.

Rotating issues a new secret for the same key and leaves the name and scopes untouched. The new secret is shown once, the same as at creation, and the 6-month expiry restarts today.

The old secret stays valid for two hours. Use that window to deploy the new one. After two hours, anything still sending the old secret fails with 401. If your integration reads the key from a secrets store it can re-read without restarting, update it there and the cutover is immediate.

If two hours is not enough, add a second key with the same scopes, move the integration onto it, confirm it's working, then delete the first.

Rotate when a key has been lost, when it may have been exposed, or before it expires.

Deleting removes a key permanently. It takes effect immediately — the next request using that key fails with 401 — and it cannot be undone. Delete when the integration using a key is being retired for good.

Who can do this. Store owners and admins can add, edit, rotate, and delete API keys. The Developers page is not shown to other roles.

5. Handle the common errors

Failed requests return the same envelope. 401 and 403 from a missing, unrecognised, or under-scoped x-api-key header are shown in the samples panel. Application errors (400, 404, and endpoint-specific failures) look like:

{
  "requestId": "<requestId>",
  "requestReceivedAt": "<timestamp>",
  "storeId": "<id>",
  "error": {
    "message": "Resource not found",
    "statusCode": 404
  }
}

Four failures can happen on any request, so they are described here once rather than repeated on every endpoint below.

400 — the request was malformed or failed validation. Check the request body and query parameters against the endpoint's schema. error.message names the offending field.

401 — the x-api-key header is missing, or the key is not recognised, inactive, expired, or has been deleted. Check that the header is being sent and that the key is correct. If this started more than two hours after a rotation, the old secret is still deployed somewhere. If the key was lost, rotate it. If it expired, rotate it before the next call. If it was deleted, add a new key.

403 — the x-api-key header is valid but was not granted the scope this endpoint requires. Check the scope listed on the endpoint. Edit the key on Settings → Developers to add that scope, or use a different key that already has it.

404 — no such record in your store, or the key cannot reach it. Check the ID. A record belonging to another store returns 404, not 403.

409 — optimistic concurrency conflict. Returned when updating a ticket field whose ticketFieldsUpdatedAt no longer matches, or when creating a contact whose email or phone is already on the store. Re-read the resource and retry, or use a different email or phone.

Treat 401 and 403 as permanent. Retrying with the same key produces the same result, and a retry loop against 401 will simply generate noise. Both need a change to the key itself.

Endpoints that can fail in ways specific to what they do — a conflicting write, for example — document those responses individually.

Scopes

Scopes decide what a key is allowed to do. You choose them when the key is created, and you can change them later with Edit on that key. Rotating a key preserves its scopes. Granting a write scope also grants the matching read scope; removing a read scope removes the matching write scope.

Each resource has a read and write pair. Write scopes for accounts, users, labels, and teams — and the accounts read scope — are defined so keys issued today do not need reissuing when those routes land.

  • tickets:read — read tickets and ticket field definitions
  • tickets:write — update ticket fields and close tickets
  • conversations:read — read conversations
  • conversations:write — mark conversations read and update labels
  • contacts:read — read contacts and contact field definitions
  • contacts:write — create contacts and update contact fields
  • messages:read — read messages and internal comments
  • messages:write — send messages and create internal comments
  • accounts:read — reserved for future read endpoints
  • accounts:write — reserved for future write endpoints
  • users:read — read store users
  • users:write — reserved for future write endpoints
  • labels:read — read labels
  • labels:write — reserved for future write endpoints
  • teams:read — read teams
  • teams:write — reserved for future write endpoints

Each endpoint below states the scope it requires.

Conventions

URLs. Every path is relative to the versioned base URL, https://openplatform.zaapi.co/v1. Record IDs travel as query parameters on reads and in the request body on writes, rather than as path segments.

Response envelope. Successful responses wrap the result in data:

{
  "requestId": "<requestId>",
  "requestReceivedAt": "<timestamp>",
  "storeId": "<id>",
  "data": { }
}

A single-resource read puts an object in data. A list puts an array in data, including GET /conversations when you look up one conversation by id — that call still returns a one-item array. Failed requests use the same envelope with error instead of data.

Some writes return the updated resource. Others acknowledge the write with { "message": "OK" } inside data and do not echo the resource: marking a conversation read, updating conversation labels, updating a contact field, sending a plain-text message, and adding an internal comment.

Pagination

Collections that can grow without bound are cursor-paginated. Walk them with pageSize and cursor. Do not advance by incrementing page.

Query parameters on paginated endpoints:

  • pageSize — items per page. Defaults to 20. Maximum is 50, except GET /messages where the maximum is 15. A value above the endpoint maximum is rejected with 400. On GET /messages you must send pageSize — the default of 20 is above that endpoint's maximum.
  • cursor — opaque token from the previous page. Omit it on the first page. Pass the previous x-pagination-next-cursor value back verbatim — do not parse, wrap, or reconstruct it. A malformed cursor is rejected with 400.
  • page — optional integer, defaults to 1. Echoed in x-pagination-page. It is not how you walk a collection. Sending page=2 without a cursor does not return the second page.

The response body stays a JSON array inside data. Pagination metadata is returned as headers, not in the body:

  • x-pagination-page
  • x-pagination-page-size
  • x-pagination-total
  • x-pagination-next-cursor — present only when this page is full (data.length === pageSize). Omitted on the last page. When it is present, request the next page with the same filters and pageSize, plus cursor set to this value. Stop when the header is missing.
GET /v1/labels?pageSize=20
# read x-pagination-next-cursor, then:
GET /v1/labels?pageSize=20&cursor=<cursor>

Keep pageSize and every filter the same across pages. Changing them mid-walk skips or repeats rows.

These endpoints are cursor-paginated:

  • POST /tickets/list — newest message first, max pageSize 50
  • GET /conversations — most recent last message first, max pageSize 50
  • POST /contacts/list — most recently updated first, max pageSize 50
  • GET /messages — newest first, max pageSize 15
  • GET /messages/internal-comments — newest first, max pageSize 50
  • GET /labels — most recently updated first, max pageSize 50
  • GET /teams — max pageSize 50

Small per-store catalogs are returned in full, with no pagination parameters or x-pagination-* headers:

  • GET /tickets/fields — all ticket field definitions, display order
  • GET /contacts/fields — all contact field definitions, display order
  • GET /users — every user on the store

Pass expand as a query parameter to resolve related ids into small objects. Send a comma-separated list (expand=account,assignee) or repeat the key (expand=account&expand=assignee). Values are exact and case-sensitive. An unknown value is rejected with 400 (Invalid expand value: …).

Each endpoint accepts only the values listed on it. expand=assignee is valid on a ticket and rejected on a conversation — assignee lives on tickets, not conversations.

Two shapes are used:

Replace the id. On tickets and conversations, the id field is omitted and a related object takes its place.

GET /v1/tickets?ticketId=<id>
# { "accountId": "<id>", "assigneeUserId": "<id>" }

GET /v1/tickets?ticketId=<id>&expand=account,assignee
# { "account": { "id": "<id>", "name": "Line Shop", "channel": "line" },
#   "assignee": { "id": "<id>", "name": "Nadia Prasert" } }

Add a sibling, or replace a nested id. On messages, accountId and conversationId stay on the record and account / conversation / sentBy are added beside them. On an internal comment, expand=createdBy replaces noteData.createdBy in place. On a team, expand=users turns each member id into { id, name } when that user exists on the store — otherwise the raw id is left as-is. On a user, expand=role adds role { id, name } and omits roleId.

If a related record cannot be resolved, the expand is skipped for that field and the original id remains.

Allowed expand values:

Endpoint Values Effect
Ticket reads and writes account, conversation, assignee, handledBy Replaces accountId, conversationId, assigneeUserId, handledBy
GET /tickets/fields accounts Adds accounts (name, accountId, channel)
GET /conversations account Replaces accountId
GET /messages sentBy, conversation, account Adds those objects; ids stay
GET /messages/internal-comments createdBy, conversation, account Replaces noteData.createdBy; adds conversation and account
GET /users role Adds role; omits roleId
GET /teams users Each member becomes { id, name } when known

Related channel objects are { id, name, channel }. Related users are { id, name }, except message sentBy / createdBy, which are { userId, name, roleId }.

Timestamps. Resource timestamps are ISO 8601 in UTC.

Errors. See Handle the common errors above for the shared error shape and the 400, 401, 403, 404, and 409 responses that apply across endpoints.

Webhooks

As well as calling the API, you can have Zaapi notify your systems when something changes in your store. The events we send are:

Messages

  • message.received — a message arrives from a contact
  • message.sent — a message is sent from Zaapi

Tickets

  • ticket.opened — a ticket is opened, including a ticket being reopened
  • ticket.closed — a ticket is closed
  • ticket.assigned — a ticket is assigned to someone
  • ticket.unassigned — a ticket's assignee is removed
  • ticket.ticket_field_updated — a ticket field is updated

Conversations

  • conversation.label_added — a label is added to a conversation
  • conversation.label_removed — a label is removed from a conversation

Contacts

  • contact.contact_field_updated — a contact field is updated

AI

  • ai.escalated — the AI escalates a chat

Payload schemas, endpoint configuration, and signature verification are documented separately.

Tickets

Individual pieces of work raised against a conversation — listing, reading, updating fields, and closing.

Get a ticket by ID

Required scope: tickets:read

Returns a single ticket. Pass expand=account,conversation,assignee,handledBy to replace those ids with names. Unknown expand values return 400.

query Parameters
ticketId
required
string
Example: ticketId=<id>
expand
string
Example: expand=account,assignee

Comma-separated related objects to include. Replaces the matching id field (accountIdaccount, conversationIdconversation, assigneeUserIdassignee, handledByhandledByUser). Unknown values return 400.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Ticket)
id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

Request samples

curl "https://openplatform.zaapi.co/v1/tickets?ticketId=<id>" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "ticketNumber": "<ticketNumber>",
    • "accountId": "<id>",
    • "conversationId": "<id>",
    • "channel": "line",
    • "isOpen": true,
    • "openedAt": "<timestamp>",
    • "assigneeUserId": "<id>",
    • "isFollowUp": false,
    • "isSpam": false,
    • "ticketFields": {
      },
    • "ticketFieldsUpdatedAt": "<timestamp>",
    • "contactId": "<id>",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

List tickets

Required scope: tickets:read

Returns a page of tickets in your store, newest message first. With an empty body this is open, non-spam tickets that are not snoozed.

Paginate with pageSize (max 50) and cursor. Pass expand=account,conversation,assignee,handledBy to replace those ids with names.

Do not send assigneeUserIds together with unassigned: true.

query Parameters
page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 50 ]
Default: 20
Example: pageSize=20

Items per page. Defaults to 20. Maximum 50 on this endpoint.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

expand
string
Example: expand=account,assignee

Comma-separated related objects to include. Replaces the matching id field (accountIdaccount, conversationIdconversation, assigneeUserIdassignee, handledByhandledByUser). Unknown values return 400.

Request Body schema: application/json
optional
statuses
Array of strings
Items Enum: "open" "closed"

Omit to return open tickets only. Send both values for all tickets.

conversationId
string

Restrict to tickets belonging to this conversation.

accountIds
Array of strings
assigneeUserIds
Array of strings
handledByUserIds
Array of strings
resolutionStatuses
Array of strings
Items Enum: "none" "human" "automation" "ai_full_resolution" "ai_partial_resolution"
unassigned
boolean

When true, only tickets with no assignee. Cannot be combined with assigneeUserIds.

isFollowUp
boolean
isSpam
boolean

Defaults to false (non-spam tickets).

object (AdvancedFilters)

Optional extra filters on labels, ticket fields, waiting time, and opened-at.

object (LabelFilter)
Array of objects (TicketFieldFilter) <= 10 items
object (WaitingForReplyFilter)

Tickets where the buyer has been waiting at least this many minutes.

object (OpenedAtFilter)

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Ticket)
Array
id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

Request samples

Content type
application/json
{
  • "statuses": [
    • "open"
    ],
  • "unassigned": true
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

List ticket fields

Required scope: tickets:read

Returns every custom ticket field definition for your store, in display order. This is a full catalog — it is not paginated. Pass expand=accounts to include the accounts each field applies to.

query Parameters
expand
string
Value: "accounts"
Example: expand=accounts

Pass accounts to include the accounts each field applies to.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (TicketField)
Array
id
required
string
name
required
string
displayType
required
string
Enum: "text" "multiline_text" "integer" "date" "datetime" "select" "file" "yes_no" … 3 more
dataType
required
string
Enum: "string" "number" "boolean" "date"
sortOrder
required
integer

Display order among ticket fields.

isRequired
required
boolean
active
required
boolean
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
description
string
Array of objects (SelectOption)

Options for select fields.

regex
string

Validation pattern for free-text values.

Array of objects (ShowCondition)

When set, this field is only shown if these conditions match.

maxItems
integer

Maximum number of values when the field accepts more than one.

Array of objects (TicketFieldAccount)

Included when expand contains accounts.

Request samples

curl "https://openplatform.zaapi.co/v1/tickets/fields?expand=accounts" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Update a ticket field value

Required scope: tickets:write

Sets or clears one field on a ticket. Send null as newValue to unset it.

Send the ticketFieldsUpdatedAt value you last received for the ticket. If someone else has changed the fields since then, the request is rejected with 409 and nothing is written — re-read the ticket and try again. Omit ticketFieldsUpdatedAt when the ticket has never had a field update.

query Parameters
expand
string
Example: expand=account,assignee

Comma-separated related objects to include. Replaces the matching id field (accountIdaccount, conversationIdconversation, assigneeUserIdassignee, handledByhandledByUser). Unknown values return 400.

Request Body schema: application/json
required
ticketId
required
string
ticketFieldId
required
string
newValue
required
any

Type depends on the field's dataType. Send null to unset.

ticketFieldsUpdatedAt
string <date-time>

The ticketFieldsUpdatedAt you currently hold. A mismatch results in 409. Omit if the ticket has never had a field update.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Ticket)
id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

Request samples

Content type
application/json
{
  • "ticketId": "<id>",
  • "ticketFieldId": "<id>",
  • "ticketFieldsUpdatedAt": "<timestamp>",
  • "newValue": "SO-10482"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "ticketNumber": "<ticketNumber>",
    • "accountId": "<id>",
    • "conversationId": "<id>",
    • "channel": "line",
    • "isOpen": true,
    • "openedAt": "<timestamp>",
    • "assigneeUserId": "<id>",
    • "isFollowUp": false,
    • "isSpam": false,
    • "ticketFields": {
      },
    • "ticketFieldsUpdatedAt": "<timestamp>",
    • "contactId": "<id>",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

Close a ticket

Required scope: tickets:write

Closes a ticket. You can record who handled it, conversion details, and ticket field values in the same request.

query Parameters
expand
string
Example: expand=account,assignee

Comma-separated related objects to include. Replaces the matching id field (accountIdaccount, conversationIdconversation, assigneeUserIdassignee, handledByhandledByUser). Unknown values return 400.

Request Body schema: application/json
required
ticketId
required
string
handledBy
string <uuid>

The user who handled the ticket.

isConverted
boolean

Whether the conversation led to a conversion.

totalRevenue
number >= 0

Conversion revenue recorded on close.

currency
string

ISO 4217 code for totalRevenue.

object

Field values to set when closing, keyed by field id.

property name*
additional property
any

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Ticket)
id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

Request samples

Content type
application/json
{
  • "ticketId": "<id>",
  • "handledBy": "<id>",
  • "isConverted": true,
  • "totalRevenue": 1890,
  • "currency": "THB"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "ticketNumber": "<ticketNumber>",
    • "accountId": "<id>",
    • "conversationId": "<id>",
    • "channel": "line",
    • "isOpen": true,
    • "openedAt": "<timestamp>",
    • "assigneeUserId": "<id>",
    • "isFollowUp": false,
    • "isSpam": false,
    • "ticketFields": {
      },
    • "ticketFieldsUpdatedAt": "<timestamp>",
    • "contactId": "<id>",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

Conversations

Channel conversations — finding by conversation or contact, marking read, and applying label changes.

Filter conversations by ID or contact

Required scope: conversations:read

Returns a page of conversations. Send conversationId and/or contactId — at least one is required. A conversationId lookup returns a one-item page, or 404 if that conversation is not in your store. contactId pages through that contact's conversations, most recent last message first.

If both are sent they must refer to the same conversation, otherwise the response is 404.

Paginate with pageSize (max 50) and cursor. Pass expand=account to replace accountId with { id, name, channel }. Assignee is not available on conversations — it lives on tickets.

query Parameters
conversationId
string
Example: conversationId=<id>
contactId
string
Example: contactId=<id>
page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 50 ]
Default: 20
Example: pageSize=20

Items per page. Defaults to 20. Maximum 50 on this endpoint.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

expand
string
Value: "account"
Example: expand=account

Pass account to replace accountId with { id, name, channel }. assignee is not a valid expand on conversations.

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Conversation)
Array
id
required
string
channel
required
string (Channel)
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
displayName
required
string
contactId
required
string
referenceId
required
string

The channel's own conversation id.

labelIds
required
Array of strings
isSpam
required
boolean
unreadMsgCnt
required
integer
allMsgCnt
required
integer
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

emailSubject
string

Present on email channels only.

lastRecipientMsgDate
string <date-time>
object

Request samples

curl "https://openplatform.zaapi.co/v1/conversations?conversationId=<id>&expand=account" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Mark a conversation as read

Required scope: conversations:write

Clears the unread count on the conversation's open ticket. Idempotent — calling it on an already-read conversation is a no-op. A conversation with no open ticket returns 404.

Request Body schema: application/json
required
conversationId
required
string

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object
message
required
string

Request samples

Content type
application/json
{
  • "conversationId": "<id>"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "message": "OK"
    }
}

Update conversation labels

Required scope: conversations:write

Applies a label delta. At least one of addLabels or removeLabels is required. Each array accepts at most 10 ids. Adding a label already present, or removing one that is absent, is a no-op.

Request Body schema: application/json
required
conversationId
required
string
addLabels
Array of strings
removeLabels
Array of strings

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object
message
required
string

Request samples

Content type
application/json
{
  • "conversationId": "<id>",
  • "addLabels": [
    • "<id>"
    ],
  • "removeLabels": [
    • "<id>"
    ]
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "message": "OK"
    }
}

Contacts

Customer contacts — reading, listing with search, creating, and updating custom fields.

Get a contact by ID

Required scope: contacts:read

Returns a single contact. Use POST /contacts/list to search.

query Parameters
contactId
required
string
Example: contactId=<id>

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Contact)
id
required
string
fullName
required
string
firstName
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
lastName
string
email
string <email>
phone
string
secondaryPhones
Array of strings
secondaryEmails
Array of strings <email> [ items <email > ]
addresses
Array of strings
note
string
object

Custom field values keyed by field id.

customFieldsUpdatedAt
string <date-time>

When a custom field was last written. Pass this back as updatedAt when updating a field.

Request samples

curl "https://openplatform.zaapi.co/v1/contacts?contactId=<id>" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "fullName": "Somchai Srisuk",
    • "firstName": "Somchai",
    • "lastName": "Srisuk",
    • "email": "[email protected]",
    • "phone": "+66812345678",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

Create a contact

Required scope: contacts:write

Creates a contact in your store. Rejected if another contact already has the same primary email or phone. Phone must be E.164.

Request Body schema: application/json
required
firstName
required
string <= 50 characters
lastName
string <= 50 characters
email
string <email> <= 100 characters
phone
string <= 15 characters

Primary phone number in E.164 format.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Contact)
id
required
string
fullName
required
string
firstName
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
lastName
string
email
string <email>
phone
string
secondaryPhones
Array of strings
secondaryEmails
Array of strings <email> [ items <email > ]
addresses
Array of strings
note
string
object

Custom field values keyed by field id.

customFieldsUpdatedAt
string <date-time>

When a custom field was last written. Pass this back as updatedAt when updating a field.

Request samples

Content type
application/json
{
  • "firstName": "Somchai",
  • "lastName": "Srisuk",
  • "email": "[email protected]",
  • "phone": "+66812345678"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "fullName": "Somchai Srisuk",
    • "firstName": "Somchai",
    • "lastName": "Srisuk",
    • "email": "[email protected]",
    • "phone": "+66812345678",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

List contacts

Required scope: contacts:read

Returns contacts matching the optional search term and updated-at window, most recently updated first. Paginate with pageSize (max 50) and cursor.

query Parameters
page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 50 ]
Default: 20
Example: pageSize=20

Items per page. Defaults to 20. Maximum 50 on this endpoint.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

Request Body schema: application/json
optional
search
string <= 100 characters

Free-text search across name, email, and phone.

updatedAfter
string <date-time>

Only contacts updated on or after this time.

updatedBefore
string <date-time>

Only contacts updated before this time.

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Contact)
Array
id
required
string
fullName
required
string
firstName
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
lastName
string
email
string <email>
phone
string
secondaryPhones
Array of strings
secondaryEmails
Array of strings <email> [ items <email > ]
addresses
Array of strings
note
string
object

Custom field values keyed by field id.

customFieldsUpdatedAt
string <date-time>

When a custom field was last written. Pass this back as updatedAt when updating a field.

Request samples

Content type
application/json
{
  • "search": "somchai"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

List contact fields

Required scope: contacts:read

Returns every custom contact field definition for your store, in display order. This is a full catalog — it is not paginated. Store limits: 100 fields total, 20 active, and 10 values on a multi-select. selectOptions is a nested tree with a maximum depth of 4.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (ContactField)
Array
id
required
string
name
required
string
displayType
required
string
Enum: "text" "multiline_text" "integer" "date" "datetime" "select" "file" "yes_no" … 1 more
dataType
required
string
Enum: "number" "boolean" "string" "date"
active
required
boolean
sortOrder
required
integer

Display order among contact fields.

description
string
Array of objects (SelectOption)

Nested options for select fields. Maximum depth 4.

regex
string

Validation pattern for free-text values.

maxItems
integer

Maximum number of values when the field accepts more than one.

Request samples

curl "https://openplatform.zaapi.co/v1/contacts/fields" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Update a contact field value

Required scope: contacts:write

Sets or clears one custom field on a contact. Send null as value to unset it. Pass the customFieldsUpdatedAt you last read as updatedAt. If the contact changed in the meantime the write is rejected. Values are validated against the field definition (regex, max items, select options).

Request Body schema: application/json
required
contactId
required
string
contactFieldId
required
string
value
required
any

Type depends on the field's dataType. Send null to unset.

updatedAt
required
string <date-time>

The customFieldsUpdatedAt you currently hold. A mismatch is rejected.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object
message
required
string

Request samples

Content type
application/json
{
  • "contactId": "<id>",
  • "contactFieldId": "<id>",
  • "updatedAt": "<timestamp>",
  • "value": "VIP"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "message": "OK"
    }
}

Messages

Customer messages and internal comments on a conversation or ticket.

List messages

Required scope: messages:read

Returns customer-facing messages, newest first. Events and internal comments are excluded. Send conversationId and/or ticketId — at least one is required. When ticketId is set, results are limited to that ticket's time window (after the previous ticket on the conversation closed, through this ticket's closedAt if it is closed). If both ids are sent and do not belong together, the response is 404.

Paginate with pageSize (required, max 15) and cursor. Pass expand=sentBy,conversation,account to add related names. Those ids stay on the message.

query Parameters
conversationId
string
Example: conversationId=<id>
ticketId
string
Example: ticketId=<id>

Limit results to this ticket's time window.

page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 15 ]
Default: 20
Example: pageSize=15

Items per page. Maximum 15. Required on this endpoint — the global default of 20 exceeds the maximum.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

expand
string
Example: expand=sentBy,account

Comma-separated related objects to add beside the message ids. sentBy is { userId, name, roleId }. conversation and account are { id, name, channel }.

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Message)
Array
id
required
string
conversationId
required
string
accountId
required
string
sentByRecipient
required
boolean
sentAt
required
string <date-time>
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
object

Present when expand includes conversation.

object

Present when expand includes account.

authorUserId
string

User id of the teammate who sent the message.

object

Present when expand includes sentBy.

isSentFromApp
boolean
object

Channel sender metadata.

object

Channel-specific message payload.

Request samples

curl "https://openplatform.zaapi.co/v1/messages?conversationId=<id>&pageSize=15&expand=sentBy,account" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

List internal comments

Required scope: messages:read

Returns seller-private notes written by agents about a customer on a conversation, newest first. These do not reach the customer. Paginate with pageSize (max 50) and cursor. Pass expand=createdBy,conversation,account to resolve related names.

query Parameters
conversationId
required
string
Example: conversationId=<id>
page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 50 ]
Default: 20
Example: pageSize=20

Items per page. Defaults to 20. Maximum 50 on this endpoint.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

expand
string
Example: expand=createdBy,conversation,account

Comma-separated related objects. createdBy replaces noteData.createdBy in place. conversation and account are added beside their ids.

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (InternalComment)
Array
id
required
string
conversationId
required
string
accountId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
object

Present when expand includes conversation.

object

Present when expand includes account.

authorUserId
string
object
sentAt
string <date-time>

Request samples

curl "https://openplatform.zaapi.co/v1/messages/internal-comments?conversationId=<id>&expand=createdBy" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Add an internal comment

Required scope: messages:write

Saves an internal note on a conversation. Does not reach the customer. Plain text only, not HTML.

Request Body schema: application/json
required
conversationId
required
string
text
required
string

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object
message
required
string

Request samples

Content type
application/json
{
  • "conversationId": "<id>",
  • "text": "Follow up tomorrow"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "message": "OK"
    }
}

Send a plain text message

Required scope: messages:write

Sends a plain text message to the customer on their channel. Channel rules apply — for example WhatsApp outside the 24-hour window requires an approved template. Retries send a second message; there is no idempotency key yet.

Request Body schema: application/json
required
conversationId
required
string
text
required
string

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object
message
required
string

Request samples

Content type
application/json
{
  • "conversationId": "<id>",
  • "text": "Thanks for your order!"
}

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "message": "OK"
    }
}

Users

Users who belong to the store.

List users

Required scope: users:read

Returns every user on the store. This is a full list — it is not paginated. Optionally filter to one userId (a UUID). An unknown userId returns an empty array. userId on a user may be absent for invited seats that have not yet been accepted.

Pass expand=role to include { id, name } for the user's role. Without expand, the response keeps roleId.

query Parameters
userId
string <uuid>
Example: userId=<id>

Restrict to this user (UUID).

expand
string
Value: "role"
Example: expand=role

Pass role to include { id, name } and omit roleId.

Responses

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (User)
Array
id
required
string
name
required
string
userId
string

Absent for invited seats that have not yet been accepted.

roleId
string

Present unless expand includes role.

object

Replaces roleId when expand includes role.

Request samples

curl "https://openplatform.zaapi.co/v1/users?expand=role" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Labels

Labels that can be applied to conversations.

List labels

Required scope: labels:read

Returns labels for the store, most recently updated first. Paginate with pageSize (max 50) and cursor. Pass searchTerm (3–100 characters) to search the label text. Whitespace-only searchTerm is treated as omitted.

query Parameters
searchTerm
string [ 3 .. 100 ] characters
Example: searchTerm=vip

Optional case-insensitive search on the label text (3–100 characters).

page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 50 ]
Default: 20
Example: pageSize=20

Items per page. Defaults to 20. Maximum 50 on this endpoint.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Label)
Array
id
required
string
label
required
string
color
required
string
fbAdId
string
whatsAppAdId
string
metaPostId
string
whatsAppBroadcastId
string
isSystemLabel
boolean

Request samples

curl "https://openplatform.zaapi.co/v1/labels?pageSize=20" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Teams

Teams of store users.

List teams

Required scope: teams:read

Returns teams for the store. Paginate with pageSize (max 50) and cursor. Pass userId (a UUID) to return only teams containing that user. Pass expand=users to return member { id, name } instead of raw user ids. A member with no record on the store stays a raw id.

query Parameters
userId
string <uuid>
Example: userId=<id>

Restrict to teams containing this user (UUID).

page
integer >= 1
Default: 1
Example: page=1

Echoed in x-pagination-page. Defaults to 1. Do not use this to walk a collection — pass cursor from the previous page instead.

pageSize
integer [ 1 .. 50 ]
Default: 20
Example: pageSize=20

Items per page. Defaults to 20. Maximum 50 on this endpoint.

cursor
string
Example: cursor=<cursor>

Opaque token from the previous page's x-pagination-next-cursor header. Pass it back verbatim.

expand
string
Value: "users"
Example: expand=users

Pass users to return each member as { id, name } when that user exists on the store. Otherwise the raw user id is left as-is.

Responses

Response Headers
x-pagination-page
integer
Example: "1"

Current page.

x-pagination-page-size
integer
Example: "20"

Page size used for this response.

x-pagination-total
integer
Example: "42"

Total number of matching records.

x-pagination-next-cursor
string
Example: "<cursor>"

Pass as cursor to fetch the next page. Omitted on the last page.

Response Schema: application/json
requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Team)
Array
id
required
string
name
required
string
description
string
Array of strings or RelatedUser (object)

User ids by default. When expand includes users, each member becomes { id, name } if that user exists on the store, otherwise the raw id.

Request samples

curl "https://openplatform.zaapi.co/v1/teams?pageSize=20&expand=users" \
  -H "x-api-key: YOUR_API_KEY"

Response samples

Content type
application/json
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Schemas

Error

requestId
required
string

Gateway request id. Include this when you contact support.

requestReceivedAt
required
string

When the gateway received the request.

storeId
required
string
required
object
message
required
string

Human-readable description of what went wrong.

statusCode
required
integer

HTTP status code.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "error": {
    • "message": "Resource not found",
    • "statusCode": 404
    }
}

AcknowledgementResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object
message
required
string
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "message": "OK"
    }
}

TicketResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Ticket)
id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "ticketNumber": "<ticketNumber>",
    • "accountId": "<id>",
    • "conversationId": "<id>",
    • "channel": "line",
    • "isOpen": true,
    • "openedAt": "<timestamp>",
    • "assigneeUserId": "<id>",
    • "isFollowUp": false,
    • "isSpam": false,
    • "ticketFields": {
      },
    • "ticketFieldsUpdatedAt": "<timestamp>",
    • "contactId": "<id>",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

TicketListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Ticket)
Array
id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

TicketFieldListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (TicketField)
Array
id
required
string
name
required
string
displayType
required
string
Enum: "text" "multiline_text" "integer" "date" "datetime" "select" "file" "yes_no" … 3 more
dataType
required
string
Enum: "string" "number" "boolean" "date"
sortOrder
required
integer

Display order among ticket fields.

isRequired
required
boolean
active
required
boolean
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
description
string
Array of objects (SelectOption)

Options for select fields.

regex
string

Validation pattern for free-text values.

Array of objects (ShowCondition)

When set, this field is only shown if these conditions match.

maxItems
integer

Maximum number of values when the field accepts more than one.

Array of objects (TicketFieldAccount)

Included when expand contains accounts.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Ticket

id
required
string
ticketNumber
required
string

Human-readable ticket number.

channel
required
string
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
isOpen
required
boolean
openedAt
required
string <date-time>
isSpam
required
boolean
contactId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

id
required
string
name
required
string
channel
required
string
conversationId
string

Present unless expand includes conversation.

object

Replaces conversationId when expand includes conversation.

id
required
string
name
required
string
channel
required
string
closedAt
string <date-time>
reopenedAt
string <date-time>
assigneeUserId
string

Present unless expand includes assignee.

object

Replaces assigneeUserId when expand includes assignee.

id
required
string
name
required
string
isFollowUp
boolean
object

Custom field values keyed by field id, plus any of the system keys isConverted, salesRevenue, aiCsat, and aiSummary.

property name*
additional property
any
handledBy
string

Present unless expand includes handledBy.

object

Replaces handledBy when expand includes handledBy.

id
required
string
name
required
string
ticketFieldsUpdatedAt
string <date-time>

Send this back when updating a field so concurrent writes are rejected.

{
  • "id": "<id>",
  • "ticketNumber": "<ticketNumber>",
  • "accountId": "<id>",
  • "conversationId": "<id>",
  • "channel": "line",
  • "isOpen": true,
  • "openedAt": "<timestamp>",
  • "assigneeUserId": "<id>",
  • "isFollowUp": false,
  • "isSpam": false,
  • "ticketFields": {
    • "<id>": "SO-10482",
    • "isConverted": true,
    • "salesRevenue": 1890,
    • "aiCsat": "5",
    • "aiSummary": "Customer asked about shipping"
    },
  • "ticketFieldsUpdatedAt": "<timestamp>",
  • "contactId": "<id>",
  • "createdAt": "<timestamp>",
  • "updatedAt": "<timestamp>"
}

RelatedChannel

id
required
string
name
required
string
channel
required
string
{
  • "id": "string",
  • "name": "Line Shop",
  • "channel": "line"
}

RelatedUser

id
required
string
name
required
string
{
  • "id": "<id>",
  • "name": "Nadia Prasert"
}

TicketField

id
required
string
name
required
string
displayType
required
string
Enum: "text" "multiline_text" "integer" "date" "datetime" "select" "file" "yes_no" … 3 more
dataType
required
string
Enum: "string" "number" "boolean" "date"
sortOrder
required
integer

Display order among ticket fields.

isRequired
required
boolean
active
required
boolean
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
description
string
Array of objects (SelectOption)

Options for select fields.

Array
required
string or number
children
Array of objects (SelectOption)

Nested options for cascading selects.

regex
string

Validation pattern for free-text values.

Array of objects (ShowCondition)

When set, this field is only shown if these conditions match.

Array
ticketFieldId
required
string
operator
required
string
Enum: "equals" "not_equals" "greater_than" "less_than" "greater_than_or_equals" "less_than_or_equals" "contains" "not_contains" … 2 more
value
required
any

Value to compare against. Type depends on the field.

maxItems
integer

Maximum number of values when the field accepts more than one.

Array of objects (TicketFieldAccount)

Included when expand contains accounts.

Array
name
required
string
accountId
required
string
channel
required
string
{
  • "id": "<id>",
  • "name": "Order number",
  • "description": "Customer order reference",
  • "displayType": "text",
  • "dataType": "string",
  • "sortOrder": 0,
  • "isRequired": false,
  • "active": true,
  • "createdAt": "<timestamp>",
  • "updatedAt": "<timestamp>"
}

SelectOption

required
string or number
One of
string
children
Array of objects (SelectOption)

Nested options for cascading selects.

{
  • "value": "apple",
  • "children": [
    • { }
    ]
}

ShowCondition

ticketFieldId
required
string
operator
required
string
Enum: "equals" "not_equals" "greater_than" "less_than" "greater_than_or_equals" "less_than_or_equals" "contains" "not_contains" … 2 more
value
required
any

Value to compare against. Type depends on the field.

{
  • "ticketFieldId": "string",
  • "operator": "equals",
  • "value": null
}

TicketFieldAccount

name
required
string
accountId
required
string
channel
required
string
{
  • "name": "Line Shop",
  • "accountId": "string",
  • "channel": "line"
}

ListTicketsRequest

statuses
Array of strings
Items Enum: "open" "closed"

Omit to return open tickets only. Send both values for all tickets.

conversationId
string

Restrict to tickets belonging to this conversation.

accountIds
Array of strings
assigneeUserIds
Array of strings
handledByUserIds
Array of strings
resolutionStatuses
Array of strings
Items Enum: "none" "human" "automation" "ai_full_resolution" "ai_partial_resolution"
unassigned
boolean

When true, only tickets with no assignee. Cannot be combined with assigneeUserIds.

isFollowUp
boolean
isSpam
boolean

Defaults to false (non-spam tickets).

object (AdvancedFilters)

Optional extra filters on labels, ticket fields, waiting time, and opened-at.

object (LabelFilter)
Array of objects (TicketFieldFilter) <= 10 items
object (WaitingForReplyFilter)

Tickets where the buyer has been waiting at least this many minutes.

object (OpenedAtFilter)
{
  • "statuses": [
    • "open"
    ],
  • "unassigned": true
}

AdvancedFilters

object (LabelFilter)
operator
required
string
Enum: "contains_any" "contains_all" "does_not_contain_any"
labelIds
required
Array of strings [ 1 .. 10 ] items
Array of objects (TicketFieldFilter) <= 10 items
Array (<= 10 items)
ticketFieldId
required
string
operator
required
string
Enum: "equal" "not_equal" "starts_with" "text_contains" "is_one_of" "is_not_one_of" "contains_any" "contains_all" … 6 more
value
any

A single value, or an array for is_one_of / contains_* operators.

min
any

Lower bound for between.

max
any

Upper bound for between.

object (WaitingForReplyFilter)

Tickets where the buyer has been waiting at least this many minutes.

value
required
integer [ 1 .. 43200 ]
object (OpenedAtFilter)
operator
required
string
Enum: "between" "greater_than" "less_than"
value
string <date-time>

Used with greater_than and less_than.

min
string <date-time>

Used with between.

max
string <date-time>

Used with between.

{
  • "labels": {
    • "operator": "contains_any",
    • "labelIds": [
      ]
    },
  • "ticketFields": [
    • {
      }
    ],
  • "waitingForReply": {
    • "value": 30
    },
  • "openedAt": {
    • "operator": "between",
    • "value": "2019-08-24T14:15:22Z",
    • "min": "2019-08-24T14:15:22Z",
    • "max": "2019-08-24T14:15:22Z"
    }
}

LabelFilter

operator
required
string
Enum: "contains_any" "contains_all" "does_not_contain_any"
labelIds
required
Array of strings [ 1 .. 10 ] items
{
  • "operator": "contains_any",
  • "labelIds": [
    • "string"
    ]
}

TicketFieldFilter

ticketFieldId
required
string
operator
required
string
Enum: "equal" "not_equal" "starts_with" "text_contains" "is_one_of" "is_not_one_of" "contains_any" "contains_all" … 6 more
value
any

A single value, or an array for is_one_of / contains_* operators.

min
any

Lower bound for between.

max
any

Upper bound for between.

{
  • "ticketFieldId": "string",
  • "operator": "equal",
  • "value": null,
  • "min": null,
  • "max": null
}

WaitingForReplyFilter

value
required
integer [ 1 .. 43200 ]
{
  • "value": 30
}

OpenedAtFilter

operator
required
string
Enum: "between" "greater_than" "less_than"
value
string <date-time>

Used with greater_than and less_than.

min
string <date-time>

Used with between.

max
string <date-time>

Used with between.

{
  • "operator": "between",
  • "value": "2019-08-24T14:15:22Z",
  • "min": "2019-08-24T14:15:22Z",
  • "max": "2019-08-24T14:15:22Z"
}

UpdateTicketFieldRequest

ticketId
required
string
ticketFieldId
required
string
newValue
required
any

Type depends on the field's dataType. Send null to unset.

ticketFieldsUpdatedAt
string <date-time>

The ticketFieldsUpdatedAt you currently hold. A mismatch results in 409. Omit if the ticket has never had a field update.

{
  • "ticketId": "<id>",
  • "ticketFieldId": "<id>",
  • "ticketFieldsUpdatedAt": "<timestamp>",
  • "newValue": "SO-10482"
}

CloseTicketRequest

ticketId
required
string
handledBy
string <uuid>

The user who handled the ticket.

isConverted
boolean

Whether the conversation led to a conversion.

totalRevenue
number >= 0

Conversion revenue recorded on close.

currency
string

ISO 4217 code for totalRevenue.

object

Field values to set when closing, keyed by field id.

property name*
additional property
any
{
  • "ticketId": "<id>",
  • "handledBy": "<id>",
  • "isConverted": true,
  • "totalRevenue": 1890,
  • "currency": "THB"
}

Channel

string (Channel)
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
"line"

ConversationListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Conversation)
Array
id
required
string
channel
required
string (Channel)
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
displayName
required
string
contactId
required
string
referenceId
required
string

The channel's own conversation id.

labelIds
required
Array of strings
isSpam
required
boolean
unreadMsgCnt
required
integer
allMsgCnt
required
integer
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

emailSubject
string

Present on email channels only.

lastRecipientMsgDate
string <date-time>
object
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Conversation

id
required
string
channel
required
string (Channel)
Enum: "line" "instagram" "facebook" "lazada" "shopee" "tiktok" "whatsapp" "widget" … 2 more
displayName
required
string
contactId
required
string
referenceId
required
string

The channel's own conversation id.

labelIds
required
Array of strings
isSpam
required
boolean
unreadMsgCnt
required
integer
allMsgCnt
required
integer
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
accountId
string

Present unless expand includes account.

object

Replaces accountId when expand includes account.

id
required
string
name
required
string
channel
required
string
emailSubject
string

Present on email channels only.

lastRecipientMsgDate
string <date-time>
object
snippet
string
sentByRecipient
boolean
sentAt
string <date-time>
{
  • "id": "<id>",
  • "accountId": "<id>",
  • "channel": "line",
  • "displayName": "Somchai",
  • "contactId": "<id>",
  • "referenceId": "<channelConversationId>",
  • "labelIds": [
    • "<id>"
    ],
  • "isSpam": false,
  • "unreadMsgCnt": 2,
  • "allMsgCnt": 14,
  • "lastMsg": {
    • "snippet": "Thanks for your help",
    • "sentByRecipient": true,
    • "sentAt": "<timestamp>"
    },
  • "createdAt": "<timestamp>",
  • "updatedAt": "<timestamp>"
}

MarkConversationReadRequest

conversationId
required
string
{
  • "conversationId": "<id>"
}

UpdateConversationLabelsRequest

conversationId
required
string
addLabels
Array of strings
removeLabels
Array of strings
{
  • "conversationId": "<id>",
  • "addLabels": [
    • "<id>"
    ],
  • "removeLabels": [
    • "<id>"
    ]
}

ContactResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
object (Contact)
id
required
string
fullName
required
string
firstName
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
lastName
string
email
string <email>
phone
string
secondaryPhones
Array of strings
secondaryEmails
Array of strings <email> [ items <email > ]
addresses
Array of strings
note
string
object

Custom field values keyed by field id.

customFieldsUpdatedAt
string <date-time>

When a custom field was last written. Pass this back as updatedAt when updating a field.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": {
    • "id": "<id>",
    • "fullName": "Somchai Srisuk",
    • "firstName": "Somchai",
    • "lastName": "Srisuk",
    • "email": "[email protected]",
    • "phone": "+66812345678",
    • "createdAt": "<timestamp>",
    • "updatedAt": "<timestamp>"
    }
}

ContactListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Contact)
Array
id
required
string
fullName
required
string
firstName
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
lastName
string
email
string <email>
phone
string
secondaryPhones
Array of strings
secondaryEmails
Array of strings <email> [ items <email > ]
addresses
Array of strings
note
string
object

Custom field values keyed by field id.

customFieldsUpdatedAt
string <date-time>

When a custom field was last written. Pass this back as updatedAt when updating a field.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

ContactFieldListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (ContactField)
Array
id
required
string
name
required
string
displayType
required
string
Enum: "text" "multiline_text" "integer" "date" "datetime" "select" "file" "yes_no" … 1 more
dataType
required
string
Enum: "number" "boolean" "string" "date"
active
required
boolean
sortOrder
required
integer

Display order among contact fields.

description
string
Array of objects (SelectOption)

Nested options for select fields. Maximum depth 4.

regex
string

Validation pattern for free-text values.

maxItems
integer

Maximum number of values when the field accepts more than one.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Contact

id
required
string
fullName
required
string
firstName
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
lastName
string
email
string <email>
phone
string
secondaryPhones
Array of strings
secondaryEmails
Array of strings <email> [ items <email > ]
addresses
Array of strings
note
string
object

Custom field values keyed by field id.

property name*
additional property
any
customFieldsUpdatedAt
string <date-time>

When a custom field was last written. Pass this back as updatedAt when updating a field.

{
  • "id": "<id>",
  • "fullName": "Somchai Srisuk",
  • "firstName": "Somchai",
  • "lastName": "Srisuk",
  • "email": "[email protected]",
  • "phone": "+66812345678",
  • "createdAt": "<timestamp>",
  • "updatedAt": "<timestamp>"
}

ContactField

id
required
string
name
required
string
displayType
required
string
Enum: "text" "multiline_text" "integer" "date" "datetime" "select" "file" "yes_no" … 1 more
dataType
required
string
Enum: "number" "boolean" "string" "date"
active
required
boolean
sortOrder
required
integer

Display order among contact fields.

description
string
Array of objects (SelectOption)

Nested options for select fields. Maximum depth 4.

Array
required
string or number
children
Array of objects (SelectOption)

Nested options for cascading selects.

regex
string

Validation pattern for free-text values.

maxItems
integer

Maximum number of values when the field accepts more than one.

{
  • "id": "<id>",
  • "name": "Loyalty tier",
  • "displayType": "select",
  • "dataType": "string",
  • "active": true,
  • "sortOrder": 1
}

ListContactsRequest

search
string <= 100 characters

Free-text search across name, email, and phone.

updatedAfter
string <date-time>

Only contacts updated on or after this time.

updatedBefore
string <date-time>

Only contacts updated before this time.

{
  • "search": "somchai"
}

CreateContactRequest

firstName
required
string <= 50 characters
lastName
string <= 50 characters
email
string <email> <= 100 characters
phone
string <= 15 characters

Primary phone number in E.164 format.

{
  • "firstName": "Somchai",
  • "lastName": "Srisuk",
  • "email": "[email protected]",
  • "phone": "+66812345678"
}

UpdateContactFieldRequest

contactId
required
string
contactFieldId
required
string
value
required
any

Type depends on the field's dataType. Send null to unset.

updatedAt
required
string <date-time>

The customFieldsUpdatedAt you currently hold. A mismatch is rejected.

{
  • "contactId": "<id>",
  • "contactFieldId": "<id>",
  • "updatedAt": "<timestamp>",
  • "value": "VIP"
}

MessageListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Message)
Array
id
required
string
conversationId
required
string
accountId
required
string
sentByRecipient
required
boolean
sentAt
required
string <date-time>
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
object

Present when expand includes conversation.

object

Present when expand includes account.

authorUserId
string

User id of the teammate who sent the message.

object

Present when expand includes sentBy.

isSentFromApp
boolean
object

Channel sender metadata.

object

Channel-specific message payload.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Message

id
required
string
conversationId
required
string
accountId
required
string
sentByRecipient
required
boolean
sentAt
required
string <date-time>
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
object

Present when expand includes conversation.

id
required
string
name
required
string
channel
required
string
object

Present when expand includes account.

id
required
string
name
required
string
channel
required
string
authorUserId
string

User id of the teammate who sent the message.

object

Present when expand includes sentBy.

userId
required
string
name
required
string
roleId
string
isSentFromApp
boolean
object

Channel sender metadata.

property name*
additional property
any
object

Channel-specific message payload.

property name*
additional property
any
{
  • "id": "<id>",
  • "conversationId": "<id>",
  • "accountId": "<id>",
  • "sentByRecipient": false,
  • "sentAt": "<timestamp>",
  • "createdAt": "<timestamp>",
  • "updatedAt": "<timestamp>"
}

MessageRelatedSeller

userId
required
string
name
required
string
roleId
string
{
  • "userId": "<id>",
  • "name": "Nadia Prasert",
  • "roleId": "string"
}

InternalCommentListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (InternalComment)
Array
id
required
string
conversationId
required
string
accountId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
object

Present when expand includes conversation.

object

Present when expand includes account.

authorUserId
string
object
sentAt
string <date-time>
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

InternalComment

id
required
string
conversationId
required
string
accountId
required
string
createdAt
required
string <date-time>
updatedAt
required
string <date-time>
object

Present when expand includes conversation.

id
required
string
name
required
string
channel
required
string
object

Present when expand includes account.

id
required
string
name
required
string
channel
required
string
authorUserId
string
object
text
string
string or MessageRelatedSeller (object)

Author user id. When expand includes createdBy this is { userId, name, roleId }, or the raw id if that user has no record on the store.

tagText
string
mediaUrl
string <uri>
sentAt
string <date-time>
{
  • "id": "<id>",
  • "conversationId": "<id>",
  • "accountId": "<id>",
  • "noteData": {
    • "text": "Follow up tomorrow",
    • "createdBy": "<id>"
    },
  • "sentAt": "<timestamp>",
  • "createdAt": "<timestamp>",
  • "updatedAt": "<timestamp>"
}

SendPlainTextMessageRequest

conversationId
required
string
text
required
string
{
  • "conversationId": "<id>",
  • "text": "Thanks for your order!"
}

CreateInternalCommentRequest

conversationId
required
string
text
required
string
{
  • "conversationId": "<id>",
  • "text": "Follow up tomorrow"
}

UserListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (User)
Array
id
required
string
name
required
string
userId
string

Absent for invited seats that have not yet been accepted.

roleId
string

Present unless expand includes role.

object

Replaces roleId when expand includes role.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

User

id
required
string
name
required
string
userId
string

Absent for invited seats that have not yet been accepted.

roleId
string

Present unless expand includes role.

object

Replaces roleId when expand includes role.

id
required
string
name
required
string
Enum: "admin" "owner" "chat-rep" "ai-bot"
{
  • "id": "<id>",
  • "userId": "<id>",
  • "name": "Nadia Prasert",
  • "roleId": "<id>"
}

LabelListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Label)
Array
id
required
string
label
required
string
color
required
string
fbAdId
string
whatsAppAdId
string
metaPostId
string
whatsAppBroadcastId
string
isSystemLabel
boolean
{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Label

id
required
string
label
required
string
color
required
string
fbAdId
string
whatsAppAdId
string
metaPostId
string
whatsAppBroadcastId
string
isSystemLabel
boolean
{
  • "id": "<id>",
  • "label": "VIP",
  • "color": "#09c8ab"
}

TeamListResponse

requestId
required
string
requestReceivedAt
required
string
storeId
required
string
required
Array of objects (Team)
Array
id
required
string
name
required
string
description
string
Array of strings or RelatedUser (object)

User ids by default. When expand includes users, each member becomes { id, name } if that user exists on the store, otherwise the raw id.

{
  • "requestId": "<requestId>",
  • "requestReceivedAt": "<timestamp>",
  • "storeId": "<id>",
  • "data": [
    • {
      }
    ]
}

Team

id
required
string
name
required
string
description
string
Array of strings or RelatedUser (object)

User ids by default. When expand includes users, each member becomes { id, name } if that user exists on the store, otherwise the raw id.

Array
One of
string
{
  • "id": "<id>",
  • "name": "Support",
  • "description": "Customer support team",
  • "users": [
    • "<id>"
    ]
}