پرش به محتوا

راهنمای توسعه‌دهنده · مرجع API

مرجع API پیکسول‌چت

سرور سایت شما با این API مشتریان و سفارش‌هایشان را برای پیکسول‌چت می‌فرستد، بخش پشتیبانی سایت خودتان را روی میز پشتیبانی ما می‌سازد و تاریخچه گفت‌وگوها را از سامانه قبلی می‌آورد؛ وب‌هوک‌ها هم رویدادهای میز را به سرور شما می‌رسانند.

همه چیز این صفحه از سند OpenAPI عمومی ساخته می‌شود؛ همان سند را برای ساختن کلاینت یا وارد کردن در ابزارهایی مثل Postman بردارید: openapi.json (نسخه 0.51.0).

احراز هویت

هر درخواست کلید API کسب‌وکار را در سرآیند Authorization: Bearer sk_… می‌فرستد. کلید را مسئول یا مدیر کسب‌وکار در پنل از «تنظیمات کسب‌وکار ← اتصال به سایت ← کلید API» می‌سازد و فقط همان لحظه یک‌بار نشان داده می‌شود. کلید خودِ کسب‌وکار است: در هیچ نشانی شناسه کسب‌وکار نمی‌آید. این API را فقط از سرور صدا بزنید، هرگز از مرورگر مشتری. کلید نادرست، چرخانده‌شده یا کلید کسب‌وکار حذف‌شده پاسخ 401 UNAUTHORIZED می‌گیرد.

curl https://pixevel.chat/api/v1/me \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

پاسخ‌ها و خطاها

هر پاسخ JSON در یک پوشش می‌آید: موفق با ok: true و داده در data؛ ناموفق با ok: false و error.code (ثابت، برای کد شما) و error.message (انگلیسی، برای توسعه‌دهنده؛ ممکن است عوض شود). جریان رویدادها و دریافت پیوست‌ها پوشش ندارند.

{ "ok": true, "data": { … } }
{ "ok": false, "error": { "code": "VALIDATION", "message": "orders[2].amount: …" } }
کد خطاوضعیت HTTP
VALIDATION400
UNAUTHORIZED401
DESK_UNAVAILABLE403
PLAN_LIMIT403
NOT_FOUND404
CONTACT_LIMIT409
CONVERSATION_CLOSED409
NOT_RESOLVED409
ATTACHMENT_TOO_LARGE413
PAYLOAD_TOO_LARGE413
IDEMPOTENCY_KEY_REUSED422
RATE_LIMITED429
ATTACHMENTS_UNAVAILABLE503
STREAM_UNAVAILABLE503

سقف‌ها

هر کلید دو شمارنده جدا دارد: مسیرهای مشتریان و انتقال تاریخچه حداکثر 600 درخواست در دقیقه، و مسیرهای گفت‌وگو (تیکت‌ها، پیام‌ها، امتیاز، بارگذاری، دسته‌ها، جریان رویدادها) حداکثر 1200 درخواست در دقیقه؛ پس یک همگام‌سازی بزرگ مشتریان صفحه‌های پشتیبانی شما را کند نمی‌کند. بیشتر از آن پاسخ 429 RATE_LIMITED با سرآیند Retry-After است. بدنه هر درخواست حداکثر 1 مگابایت است (413 PAYLOAD_TOO_LARGE).

تکرار امن

درخواست‌هایی که چیزی می‌سازند (گفت‌وگوی تازه، پیام، امتیاز) سرآیند اختیاری Idempotency-Key می‌گیرند: همان کلید و همان درخواست تا 24 ساعت همان پاسخ ثبت‌شده را با Idempotent-Replayed: true برمی‌گرداند؛ همان کلید با درخواستی دیگر 422 IDEMPOTENCY_KEY_REUSED است. مسیرهای PUT خودشان تکرارپذیرند: همان شناسه، همان نتیجه.

صفحه‌بندی

فهرست‌های بلند با limit و cursor صفحه می‌شوند: هر صفحه nextCursor دارد و صفحه بعد را با فرستادن همان مقدار در cursor می‌گیرید؛ نبودن آن یعنی صفحه آخر.

کلید و کسب‌وکار

Which business an API key belongs to.

get/api/v1/me

Which business the API key is for, and how many customers it has. `lastUsedAt` moves at most once a minute.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

پاسخ‌ها

  • 200IngestMe
    شکل data
    • workspaceobjectrequired
      فیلدها
      • idstringrequired
      • namestringrequired
      • siteUrlstringrequired
      • accountIdstringrequired

        The business's billing account (#190): the company's id, else the owner's user id. With id it addresses the dashboard: /dashboard/{accountId}/business/{id}/….

    • contactsintegerrequired
  • 401UNAUTHORIZED (wrong, rotated, or a deleted business's key)
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/me" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/me", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

مشتریان و سفارش‌ها

Push your customers and their recent orders so the support desk sees who it is talking to.

get/api/v1/staff/{userId}/activity

Staff activity aggregates scoped by the business API key

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

پارامترها

نامجانوعتوضیح
userId*مسیرstring (uuid)
from*کوئریstring (date)
to*کوئریstring (date)

پاسخ‌ها

  • 200Staff activity
    شکل data
    • workspaceIdstringrequired
    • userIdstringrequired
    • fromstring (date)required
    • tostring (date)required
    • repliesintegerrequired
    • conversationsintegerrequired
    • resolvedintegerrequired
    • openAssignedintegerrequired
    • answeredCallsintegerrequired
    • talkSecondsintegerrequired
  • 400VALIDATION (UUID or date window)
  • 401UNAUTHORIZED (business API key)
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/staff/userId/activity" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/staff/userId/activity", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

post/api/v1/contacts/batch

Up to 100 customers in one call, upserted like PUT. One result per row, in the order sent: a bad row (VALIDATION, CONTACT_LIMIT) fails only itself. A body that is not `{ contacts: [...] }`, holds more than 100 rows, or is over 1 MB fails as a whole.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

بدنه درخواست (JSON)

  • contactsContactInput & object[]required

    Each row is a ContactInput plus its `externalId`. Each is judged on its own.

پاسخ‌ها

  • 200BatchResponse
    شکل data
    • resultsobject[]required

      One result per row sent, in the order sent. A bad row does not fail the others.

      فیلدها
      • externalIdstringrequired

        Empty when the row carried no readable one.

      • okbooleanrequired
      • errorobject
        فیلدها
        • codestringrequired
        • messagestringrequired
  • 400VALIDATION (the body as a whole)
  • 401UNAUTHORIZED
  • 413PAYLOAD_TOO_LARGE
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/contacts/batch" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contacts":[{"externalId":"string"}]}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/batch", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "contacts": [
      {
        "externalId": "string"
      }
    ]
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

put/api/v1/contacts/{externalId}

Create or fully replace one customer (missing = empty). `orders` upserts those orders and never deletes others. Idempotent on externalId. Afterwards the business's unlinked conversations with this customer's phone (else email) are linked to them, at most 500.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).

بدنه درخواست (JSON)

  • namestring | null
  • phonestring | null

    An Iranian mobile in any usual spelling; stored as 09…. One that is sent but is not a mobile number is VALIDATION.

  • emailstring | null

    Lowercased on the way in.

  • urlstring | null

    Absolute https URL.

  • telegramIdstring | null

    The customer's Telegram user id as the business knows it (its own Telegram login). A Telegram chat with one of the business's bots is linked to the ONE contact with it, whichever came first (#158). Never shown back.

  • Full replace. Each flag is a key, a short label, and a tone. A reason is VALIDATION.

  • attributesobject | null

    Full replace. At most 30 facts; each value is at most 200 characters.

  • ordersarray | null

    Upserts these orders; never deletes the ones it leaves out.

پاسخ‌ها

  • 200ContactResponse
    شکل data
  • 400VALIDATION (the message names the field, like orders[2].amount)
  • 401UNAUTHORIZED
  • 409CONTACT_LIMIT (customers it already has can still be updated)
  • 413PAYLOAD_TOO_LARGE
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X PUT "https://pixevel.chat/api/v1/contacts/u_123" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

delete/api/v1/contacts/{externalId}

Remove one customer and their orders; their conversations are unlinked, never deleted — and one they started signed in leaves the widget for good (no visitor token reaches it again). The only way a customer leaves pixevel.chat.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).

پاسخ‌ها

  • 200Deleted
    شکل data
    • deletedbooleanrequired

      false when there was nothing to delete (a delete is idempotent).

  • 401UNAUTHORIZED
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X DELETE "https://pixevel.chat/api/v1/contacts/u_123" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

put/api/v1/contacts/{externalId}/orders/{orderExternalId}

Create or fully replace one order of a customer. The customer keeps their 20 newest orders by placedAt (older ones are dropped in the same transaction). Idempotent.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
orderExternalId*مسیرstringThe business's own id for the order (up to 120 characters), percent-encoded.

بدنه درخواست (JSON)

  • numberstring | null

    Defaults to the order's externalId (required when that is longer than 60).

  • titlestring | null
  • statusstring | null
  • amountstringrequired

    A decimal string (the service also reads a bare JSON number by its digits; the public door and SDK take a string).

  • currencystringrequired
  • urlstring | null

    Absolute https URL.

  • placedAtstring (date-time)required

    ISO 8601 with a time zone.

پاسخ‌ها

  • 200OrderResponse
    شکل data
  • 400VALIDATION
  • 401UNAUTHORIZED
  • 404NOT_FOUND (the customer has not been pushed)
  • 413PAYLOAD_TOO_LARGE
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X PUT "https://pixevel.chat/api/v1/contacts/u_123/orders/o_456" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":"string","currency":"string","placedAt":"2026-01-01T00:00:00Z"}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/orders/o_456", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "amount": "string",
    "currency": "string",
    "placedAt": "2026-01-01T00:00:00Z"
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

delete/api/v1/contacts/{externalId}/orders/{orderExternalId}

Remove one order of a customer.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
orderExternalId*مسیرstringThe business's own id for the order (up to 120 characters), percent-encoded.

پاسخ‌ها

  • 200Deleted
    شکل data
    • deletedbooleanrequired

      false when there was nothing to delete (a delete is idempotent).

  • 401UNAUTHORIZED
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X DELETE "https://pixevel.chat/api/v1/contacts/u_123/orders/o_456" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/orders/o_456", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

تیکت‌ها و گفت‌وگوها

Build your own support pages: list, read, open, answer, resolve and rate a customer's conversations.

get/api/v1/orders/{orderExternalId}/conversations

Conversations about one order, newest activity first (API key).

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
orderExternalId*مسیرstringThe business's own id for the order (up to 120 characters), percent-encoded.

پاسخ‌ها

  • 200OrderConversationList
    شکل data
  • 400VALIDATION
  • 401UNAUTHORIZED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/orders/o_456/conversations" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/orders/o_456/conversations", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

get/api/v1/categories

The business's live categories, for the customer's form (tickets API).

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پاسخ‌ها

  • 200TicketsCategoryList
    شکل data
  • 401UNAUTHORIZED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/categories" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/categories", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

get/api/v1/contacts/{externalId}/conversations

The contact's conversations the tickets API shows them — signed in (the widget's, or this API's) or staff-linked and held by no widget visitor's token — the most recently active first. An unknown contact has an empty page.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
kindکوئری"ticket" | "live"
statusکوئریstringComma-separated: open, pending, resolved, closed.
cursorکوئریstringA page's nextCursor.
limitکوئریinteger

پاسخ‌ها

  • 200TicketsConversationPage
    شکل data
  • 400VALIDATION (names the query parameter)
  • 401UNAUTHORIZED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/contacts/u_123/conversations" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

post/api/v1/contacts/{externalId}/conversations

Open a NEW conversation for the contact (live or ticket), signed in, channel api: auto-assigned by category, staff alerted, conversation.created emitted. An unknown externalId gets a contact made from `contact`. Answers its thread, marked read.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
Idempotency-KeyسرآیندstringOptional, 1–255 visible ASCII characters (else VALIDATION `Idempotency-Key: …`; the public door refuses one sent blank, which reaches this service as none). Per business, for 24 hours: the same key with the same request (method, path and body bytes) is done once — a repeat answers 201 rebuilt from what the first one made (the thread as it is now; a reply's own message; a rating) with `Idempotent-Replayed: true`, and NOT_FOUND if staff unlinked the conversation since. The same key with another request is IDEMPOTENCY_KEY_REUSED (422). A refused or failed request keeps no key.

بدنه درخواست (JSON)

  • kind"ticket" | "live"required
  • subjectstring

    Required for a ticket.

  • bodystring
  • categoryIdstring | null
  • orderExternalIdstring | null
  • attachmentsstring[]

    Upload ids from POST /api/v1/uploads, not sent yet; with any, body may be empty.

  • contactobject

    Used only when the business has no contact with this externalId: the contact is made from it (counted against the contact ceiling). Judged like a push on every request — a malformed one is VALIDATION even for an existing contact, which is never changed by it.

    فیلدها
    • namestring | null
    • phonestring | null
    • emailstring | null

پاسخ‌ها

  • 201TicketsThread
    شکل data
  • 400VALIDATION (names the field: contact.phone, attachments: unknown upload id, categoryId: the category is archived, …)
  • 401UNAUTHORIZED
  • 403DESK_UNAVAILABLE (the business is off or suspended)
  • 404NOT_FOUND (categoryId: no such category)
  • 409CONTACT_LIMIT
  • 413PAYLOAD_TOO_LARGE
  • 422IDEMPOTENCY_KEY_REUSED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/contacts/u_123/conversations" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"kind":"ticket"}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "kind": "ticket"
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

get/api/v1/contacts/{externalId}/conversations/{number}

One conversation with its public messages (after `after`, a message id, for a poll), marked read up to the newest returned.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
number*مسیرstringThe conversation's per-business number (#42 is `42`). Anything but a positive integer, or a conversation the API does not show this contact, is NOT_FOUND.
afterکوئریstringA message id; an unknown one returns every message.

پاسخ‌ها

  • 200TicketsThread
    شکل data
  • 400VALIDATION (`after: …` — not text, or longer than an id)
  • 401UNAUTHORIZED
  • 404NOT_FOUND (another contact's or business's, hidden, or none)
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/contacts/u_123/conversations/number" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations/number", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

patch/api/v1/contacts/{externalId}/conversations/{number}

The customer resolves (`resolved`: open/pending → resolved; resolved or closed: no-op) or reopens (`open`: resolved → open, staff alerted; open/pending: no-op; closed: CONVERSATION_CLOSED). Allowed while suspended.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
number*مسیرstringThe conversation's per-business number (#42 is `42`). Anything but a positive integer, or a conversation the API does not show this contact, is NOT_FOUND.

بدنه درخواست (JSON)

  • status"resolved" | "open"required

پاسخ‌ها

  • 200TicketsConversationResult
    شکل data
  • 400VALIDATION
  • 401UNAUTHORIZED
  • 404NOT_FOUND
  • 409CONVERSATION_CLOSED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X PATCH "https://pixevel.chat/api/v1/contacts/u_123/conversations/number" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"resolved"}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations/number", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "status": "resolved"
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

post/api/v1/contacts/{externalId}/conversations/{number}/messages

The customer's message: the conversation needs staff again, a resolved one reopens. `message` is the one this request wrote.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
number*مسیرstringThe conversation's per-business number (#42 is `42`). Anything but a positive integer, or a conversation the API does not show this contact, is NOT_FOUND.
Idempotency-KeyسرآیندstringOptional, 1–255 visible ASCII characters (else VALIDATION `Idempotency-Key: …`; the public door refuses one sent blank, which reaches this service as none). Per business, for 24 hours: the same key with the same request (method, path and body bytes) is done once — a repeat answers 201 rebuilt from what the first one made (the thread as it is now; a reply's own message; a rating) with `Idempotent-Replayed: true`, and NOT_FOUND if staff unlinked the conversation since. The same key with another request is IDEMPOTENCY_KEY_REUSED (422). A refused or failed request keeps no key.

بدنه درخواست (JSON)

  • bodystring

    Required unless attachments are sent.

  • attachmentsstring[]

    Upload ids from POST /api/v1/uploads, not sent yet.

پاسخ‌ها

  • 201TicketsReplyResult
    شکل data
  • 400VALIDATION
  • 401UNAUTHORIZED
  • 403DESK_UNAVAILABLE
  • 404NOT_FOUND
  • 409CONVERSATION_CLOSED (start a new one)
  • 413PAYLOAD_TOO_LARGE
  • 422IDEMPOTENCY_KEY_REUSED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/contacts/u_123/conversations/number/messages" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations/number/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

get/api/v1/contacts/{externalId}/stream

Live event stream of the conversations the tickets API shows this contact (never a note); an unknown contact NOT_FOUND

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
Last-Event-IDسرآیندstringThe id of the last stream event the client got (EventSource sends it on a reconnect). When it can be resumed — this process's, and still within stream.replay — every matching event after it is replayed and `ready` says resumed true; otherwise resumed false: refetch.

پاسخ‌ها

  • 200text/event-stream: `retry: 3000`, `event: ready` ({resumed}), then `id: <boot>-<seq>` / `event: conversation.updated | message.created | message.updated` / `data: <json>` frames (CustomerStreamConversation, CustomerStreamMessage). message.created includes `message` (TicketsMessage); message.updated does not. `message.delta` (StreamDelta) and `message.aborted` (StreamAborted) have no id, are never replayed, and never carry a note. A `: ping` comment every stream.heartbeat. It ends on shutdown, after stream.max_age, or when it falls 64 events behind — reconnect with Last-Event-ID.

    text/event-stream

  • 401UNAUTHORIZED
  • 404NOT_FOUND
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)
  • 503STREAM_UNAVAILABLE — shutting down or too many open streams; keep polling

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/contacts/u_123/stream" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/stream", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
// Not JSON: read response.body as an event stream / file.

get/api/v1/contacts/{externalId}/conversations/{number}/attachments/{aid}

A file of a public message in this conversation of this contact; anything else NOT_FOUND

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
number*مسیرstringThe conversation's per-business number (#42 is `42`). Anything but a positive integer, or a conversation the API does not show this contact, is NOT_FOUND.
aid*مسیرstringThe attachment id.
downloadکوئریstring1 = always an attachment disposition.

پاسخ‌ها

  • 200The bytes, Content-Type as sniffed, X-Content-Type-Options nosniff, a sandbox Content-Security-Policy, Cache-Control private no-store, Content-Disposition attachment (filename and RFC 5987 filename*) unless the type may show inline (JPEG, PNG, GIF, WebP, BMP, audio, MP4, WebM, PDF) and download=1 was not asked.

    */*

  • 401UNAUTHORIZED
  • 404NOT_FOUND
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)
  • 503ATTACHMENTS_UNAVAILABLE

نمونه با curl

curl -X GET "https://pixevel.chat/api/v1/contacts/u_123/conversations/number/attachments/aid" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY"

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations/number/attachments/aid", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
  },
});
// Not JSON: read response.body as an event stream / file.

post/api/v1/uploads

An upload for a customer's message through the tickets API; PUT the file to uploadUrl, then name uploadId in attachments

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

بدنه درخواست (JSON)

  • namestring

    Kept (cleaned, at most 200 characters) as the file's display and download name.

  • contentTypestring
  • sizeBytesinteger
  • durationMsinteger

    Optional client-measured recording length in milliseconds.

پاسخ‌ها

  • 201Upload
    شکل data
    • uploadIdstringrequired
    • uploadUrlstringrequired
    • expiresAtstring (date-time)required
    • maxBytesintegerrequired
    • visitorTokenstring

      Widget only: present when this call minted the visitor's token.

  • 400VALIDATION
  • 401UNAUTHORIZED
  • 403PLAN_LIMIT (limit storage: the plan's file storage is used)
  • 413ATTACHMENT_TOO_LARGE
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)
  • 503ATTACHMENTS_UNAVAILABLE (media is not configured or did not answer)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/uploads" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/uploads", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

post/api/v1/contacts/{externalId}/conversations/{number}/rating

Rate the conversation's current resolution — once per resolution (reopened and resolved again, it may be rated again). Emits conversation.rated. Allowed while suspended.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

پارامترها

نامجانوعتوضیح
externalId*مسیرstringThe business's own id for the customer: any text up to 120 characters, percent-encoded in the URL (spaces, slashes and Persian letters are fine).
number*مسیرstringThe conversation's per-business number (#42 is `42`). Anything but a positive integer, or a conversation the API does not show this contact, is NOT_FOUND.
Idempotency-KeyسرآیندstringOptional, 1–255 visible ASCII characters (else VALIDATION `Idempotency-Key: …`; the public door refuses one sent blank, which reaches this service as none). Per business, for 24 hours: the same key with the same request (method, path and body bytes) is done once — a repeat answers 201 rebuilt from what the first one made (the thread as it is now; a reply's own message; a rating) with `Idempotent-Replayed: true`, and NOT_FOUND if staff unlinked the conversation since. The same key with another request is IDEMPOTENCY_KEY_REUSED (422). A refused or failed request keeps no key.

بدنه درخواست (JSON)

  • scoreintegerrequired
  • commentstring | null

پاسخ‌ها

  • 201TicketsRatingResult
    شکل data
  • 400VALIDATION (score: must be an integer from 1 to 5)
  • 401UNAUTHORIZED
  • 404NOT_FOUND
  • 409NOT_RESOLVED (open or pending) or ALREADY_RATED
  • 422IDEMPOTENCY_KEY_REUSED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/contacts/u_123/conversations/number/rating" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"score":1}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/contacts/u_123/conversations/number/rating", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "score": 1
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

انتقال تاریخچه

Bring conversations over from a previous support system.

post/api/v1/import/conversations

The import API (#189): up to 50 conversations of the business's old support history. Idempotent on sourceId — a re-sent conversation gains only the messages it lacks (by message sourceId) and its status is never changed again. History fires nothing: no webhook, staff alert, assistant turn, customer notice, channel delivery or live event. `dryRun` judges every row and writes nothing (not even a contact). One result per row, in the order sent: a bad row is `refused` alone.

سقف: 600 درخواست در دقیقه برای هر کلید (شمارنده مشتریان)

بدنه درخواست (JSON)

پاسخ‌ها

  • 200ImportResponse
    شکل data
    • dryRunbooleanrequired
    • staffPhonesobjectrequired

      The request's distinct staff phones: on the team (written as that person) or not («کارمند قبلی»). On a dry run too.

      فیلدها
      • knownintegerrequired
      • unknownintegerrequired
    • resultsobject[]required

      One per row, in the order sent.

      فیلدها
      • sourceIdstringrequired
      • status"created" | "appended" | "unchanged" | "skipped" | "refused"required

        On a dry run, what would happen. skipped: imported before, erased or merged away since.

      • conversationIdstring | nullrequired
      • numberinteger | nullrequired
      • newMessagesstring[]required

        The source ids of the messages written (would be).

      • errorobject | nullrequired
        فیلدها
        • codestringrequired
        • messagestringrequired
  • 400VALIDATION (the body as a whole: not an object, no conversations, more than 50)
  • 401UNAUTHORIZED
  • 413PAYLOAD_TOO_LARGE
  • 429RATE_LIMITED (more than 600 requests a minute on this API key's ingest budget)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/import/conversations" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"conversations":[{"sourceId":"string","kind":"ticket","channel":"widget","status":"open","createdAt":"2026-01-01T00:00:00Z","messages":[{"sourceId":null,"author":null,"createdAt":null}]}]}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/import/conversations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "conversations": [
      {
        "sourceId": "string",
        "kind": "ticket",
        "channel": "widget",
        "status": "open",
        "createdAt": "2026-01-01T00:00:00Z",
        "messages": [
          {
            "sourceId": null,
            "author": null,
            "createdAt": null
          }
        ]
      }
    ]
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

post/api/v1/import/aliases/lookup

What each old name (an import's sourceId, the old system's number) names now — the conversation it was merged into, when it was. Only the aliases that name a conversation still there are answered.

سقف: 1200 درخواست در دقیقه برای هر کلید (شمارنده گفت‌وگوها)

بدنه درخواست (JSON)

  • aliasesstring[]required

پاسخ‌ها

  • 200ImportAliasList
    شکل data
    • itemsobject[]required
      فیلدها
      • aliasstringrequired
      • conversationIdstringrequired
      • numberintegerrequired
      • kind"ticket" | "live"required
      • status"open" | "pending" | "resolved" | "closed"required
      • channelstringrequired
      • contactExternalIdstring | nullrequired
      • messageCountintegerrequired

        Every message, internal notes and deleted ones included.

  • 400VALIDATION
  • 401UNAUTHORIZED
  • 429RATE_LIMITED (more than 1200 requests a minute on this API key's conversations budget)

نمونه با curl

curl -X POST "https://pixevel.chat/api/v1/import/aliases/lookup" \
  -H "Authorization: Bearer $PIXEVEL_CHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"aliases":["string"]}'

نمونه با TypeScript

const response = await fetch("https://pixevel.chat/api/v1/import/aliases/lookup", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PIXEVEL_CHAT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "aliases": [
      "string"
    ]
  }),
});
const answer = await response.json();
if (!answer.ok) throw new Error(`${answer.error.code}: ${answer.error.message}`);

وب‌هوک‌ها

پیکسول‌چت برای هر رویدادی که در پنل انتخاب کرده‌اید یک درخواست POST به نشانی شما می‌فرستد. امضای X-Pixevel-Signature را پیش از هر کاری بررسی کنید؛ کد بررسی به چند زبان، فهرست رویدادها و قاعده تلاش دوباره در راهنمای وب‌هوک‌ها است.

postdeskEvent

What pixevel.chat sends to a business's endpoint for each event it subscribed to (and for «send test»). At least once: dedupe on X-Pixevel-Delivery. Answer 2xx fast and do the work afterwards.

Signature: `X-Pixevel-Signature: v1=` + lowercase hex of HMAC-SHA256(secret, `<X-Pixevel-Timestamp>` + "." + the raw body), over the exact bytes received. Recompute it, compare in constant time, and refuse a timestamp more than 300 seconds from your clock. Each attempt is stamped and signed anew; the body and X-Pixevel-Delivery never change. Within one endpoint rows go out in order of when they are due; nothing is ordered across endpoints or per conversation — order by `occurredAt` / `conversation.updatedAt` when it matters. Only https on port 443, to a public address. Verification code in several languages: https://pixevel.chat/docs/webhooks

سرآیندنوعتوضیح
X-Pixevel-Eventstring
X-Pixevel-DeliverystringThe delivery's id (UUIDv7): the same on every retry and redeliver.
X-Pixevel-TimestampstringUnix seconds of this attempt.
X-Pixevel-Signaturestring

بدنه

یکی از این شکل‌ها: WebhookConversationPayload · WebhookTestPayload

مدل‌ها

شکل هر شیئی که در درخواست‌ها، پاسخ‌ها و وب‌هوک‌ها می‌آید؛ نام هر مدل در بخش‌های بالا به همین‌جا پیوند دارد.

Attachment

One file of a message. contentType is sniffed from the stored bytes, never the uploader's claim; kind follows from it. Download through the surface's attachments route — never by id alone.

  • idstringrequired
  • namestringrequired

    The uploader's file name (display and download name).

  • contentTypestringrequired
  • kind"image" | "audio" | "video" | "file"required
  • sizeBytesintegerrequired
  • widthinteger | nullrequired

    An image's width when it could be read.

  • heightinteger | nullrequired
  • durationMsinteger | nullrequired

    Client-measured recording length; null when absent.

BatchRequest

  • contactsContactInput & object[]required

    Each row is a ContactInput plus its `externalId`. Each is judged on its own.

BatchResponse

  • resultsobject[]required

    One result per row sent, in the order sent. A bad row does not fail the others.

    فیلدها
    • externalIdstringrequired

      Empty when the row carried no readable one.

    • okbooleanrequired
    • errorobject
      فیلدها
      • codestringrequired
      • messagestringrequired

CallStatus

"queued" | "ringing" | "connecting" | "answered" | "completed" | "no_answer" | "busy" | "failed" | "canceled" | "missed"Outbound: queued → ringing → answered → completed; a call never answered ends no_answer (no pickup), busy (rejected), failed (trunk or LiveKit), or canceled (the staff member hung up first). Inbound (0.45.0): ringing (the caller holds, the desk rings) → connecting (a staff member answered; the voice gateway puts the caller through) → answered → completed; one nobody talked to ends missed, one that could not be put through failed. Only ever moves forward.

Contact

One customer of a business, as the business's server pushed it. Every field is a string; "" when there is none.

  • idstringrequired
  • externalIdstringrequired

    The business's own id for the customer; unique per business.

  • namestringrequired
  • phonestringrequired

    09… (11 digits), or empty.

  • emailstringrequired

    Lowercase, or empty.

  • urlstringrequired

    This customer in the business's own admin (absolute https), or empty.

  • Labels the business pushed. Omitted when none. A flag has no reason.

  • attributesobject

    Short facts the business pushed. Omitted when none.

  • createdAtstring (date-time)required
  • updatedAtstring (date-time)required

    When the business last pushed the customer.

ContactFlag

  • keystringrequired

    A short key such as aml. Not a sentence.

  • labelstringrequired

    What staff read. Not a case narrative.

  • tone"info" | "warning" | "danger"required

ContactInput

One customer. A PUT is a full replace of the customer's own fields (missing or null = empty). Lengths are counted in code points after trimming; a `null` reads as not sent.

  • namestring | null
  • phonestring | null

    An Iranian mobile in any usual spelling; stored as 09…. One that is sent but is not a mobile number is VALIDATION.

  • emailstring | null

    Lowercased on the way in.

  • urlstring | null

    Absolute https URL.

  • telegramIdstring | null

    The customer's Telegram user id as the business knows it (its own Telegram login). A Telegram chat with one of the business's bots is linked to the ONE contact with it, whichever came first (#158). Never shown back.

  • Full replace. Each flag is a key, a short label, and a tone. A reason is VALIDATION.

  • attributesobject | null

    Full replace. At most 30 facts; each value is at most 200 characters.

  • ordersarray | null

    Upserts these orders; never deletes the ones it leaves out.

ContactResponse

ConversationAssistant

  • state"active" | "paused" | "handoff"required

    active — it answers; paused — staff stopped it; handoff — it handed the conversation to staff.

  • repliesintegerrequired

    Replies it wrote in this conversation.

  • handoffReason"" | "customer_asked" | "no_knowledge" | "sensitive" | "unsure" | "limit" | "budget" | "hours" | "error"required

    Why it handed off ("" otherwise). budget also covers a plan that no longer allows the assistant (grace, suspended).

CustomerStreamConversation

A business server's conversation.updated; number is what the tickets API's routes take.

  • idstringrequired
  • numberintegerrequired
  • status"open" | "pending" | "resolved" | "closed"required

CustomerStreamMessage

A business server's message.created or message.updated (0.32.0 — read the whole thread again; never a note). `message` is present on every message.created (TicketsMessage) and absent on message.updated.

  • conversationIdstringrequired
  • numberintegerrequired
  • messageIdstringrequired
  • author"customer" | "agent" | "assistant" | "system"required
  • The tickets-API public message. Present on every message.created and absent on message.updated. Never a note.

Deleted

  • deletedbooleanrequired

    false when there was nothing to delete (a delete is idempotent).

ErrorEnvelope

  • okfalserequired
  • errorobjectrequired
    فیلدها
    • codestringrequired

      Machine-readable, e.g. VALIDATION.

    • messagestringrequired

      English, for the developer; may change.

ImportAliasList

  • itemsobject[]required
    فیلدها
    • aliasstringrequired
    • conversationIdstringrequired
    • numberintegerrequired
    • kind"ticket" | "live"required
    • status"open" | "pending" | "resolved" | "closed"required
    • channelstringrequired
    • contactExternalIdstring | nullrequired
    • messageCountintegerrequired

      Every message, internal notes and deleted ones included.

ImportConversation

  • sourceIdstringrequired

    The old system's id; the import's idempotency key and an alias.

  • aliasesstring[]

    Other old names («PX-123»).

  • kind"ticket" | "live"required
  • channel"widget" | "api" | "email" | "telegram" | "bale" | "phone" | "manual"required
  • status"open" | "pending" | "resolved" | "closed"required
  • subjectstring
  • createdAtstring (date-time)required
  • resolvedAtstring (date-time)

    Defaults to the last activity for a resolved or closed one.

  • orderExternalIdstring
  • assigneePhonestring

    A staff member's mobile; anyone not on the team is left unassigned.

  • contactobject

    The customer by the business's own id — made from the stub when missing, never changed. A ticket with one is shown to that customer through the tickets API; a live chat never is.

    فیلدها
    • externalIdstringrequired
    • namestring
    • phonestring
    • emailstring
  • customerobject

    A guest's own details (no contact).

    فیلدها
    • namestring
    • phonestring
    • emailstring
  • channelIdentityobject

    Live only: the chat the conversation continues on — the customer's next message there joins it while it is not closed.

    فیلدها
    • channel"telegram" | "bale"required
    • externalChatIdstringrequired
    • externalUserIdstring

      Defaults to externalChatId (a one-to-one chat).

    • usernamestring
    • connectionIdstring

      One of the business's connections on that channel; none = its own channel (the API key).

  • messagesobject[]required
    فیلدها
    • sourceIdstringrequired
    • author"customer" | "agent" | "system"required
    • staffPhonestring

      An agent's mobile; anyone not on the team is written with no author id («کارمند قبلی»).

    • bodystring

      Required unless the message carries attachments.

    • internalboolean

      A staff-only note (agent only).

    • createdAtstring (date-time)required
    • editedAtstring (date-time)
    • deletedAtstring (date-time)
    • attachmentsstring[]

      Upload ids (POST /api/v1/uploads).

    • revisionsobject[]
      فیلدها
      • bodystringrequired
      • staffPhonestring
      • createdAtstring (date-time)required
  • ratingobject
    فیلدها
    • scoreintegerrequired
    • commentstring
    • createdAtstring (date-time)required

ImportRequest

ImportResponse

  • dryRunbooleanrequired
  • staffPhonesobjectrequired

    The request's distinct staff phones: on the team (written as that person) or not («کارمند قبلی»). On a dry run too.

    فیلدها
    • knownintegerrequired
    • unknownintegerrequired
  • resultsobject[]required

    One per row, in the order sent.

    فیلدها
    • sourceIdstringrequired
    • status"created" | "appended" | "unchanged" | "skipped" | "refused"required

      On a dry run, what would happen. skipped: imported before, erased or merged away since.

    • conversationIdstring | nullrequired
    • numberinteger | nullrequired
    • newMessagesstring[]required

      The source ids of the messages written (would be).

    • errorobject | nullrequired
      فیلدها
      • codestringrequired
      • messagestringrequired

IngestMe

  • workspaceobjectrequired
    فیلدها
    • idstringrequired
    • namestringrequired
    • siteUrlstringrequired
    • accountIdstringrequired

      The business's billing account (#190): the company's id, else the owner's user id. With id it addresses the dashboard: /dashboard/{accountId}/business/{id}/….

  • contactsintegerrequired

MessageBlock

یکی از این شکل‌ها: object · object · object · object · object

MessageButton

یکی از این شکل‌ها: object · object

MessageReplyTo

  • idstringrequired
  • author"customer" | "agent" | "assistant" | "system"required
  • excerptstringrequired
  • deletedbooleanrequired

Order

One order of a contact as the business describes it — a summary, no line items. A contact keeps its 20 newest by placedAt.

  • idstringrequired
  • externalIdstringrequired
  • numberstringrequired

    What the business calls it on screen; defaults to externalId.

  • titlestringrequired
  • statusstringrequired

    The business's own label, free text.

  • amountstringrequired

    A decimal string in `currency`.

  • currencystringrequired

    IRT, IRR, USD, USDT, …

  • urlstringrequired

    This order in the business's own admin (absolute https), or empty.

  • placedAtstring (date-time)required
  • createdAtstring (date-time)required
  • updatedAtstring (date-time)required

OrderConversation

One conversation about an order, for the business's admin.

  • idstringrequired
  • numberintegerrequired
  • kind"live" | "ticket"required
  • status"open" | "pending" | "resolved" | "closed"required
  • subjectstringrequired
  • orderExternalIdstringrequired
  • contactIdstring | nullrequired
  • contactExternalIdstring | nullrequired

    The business's own id for the customer (#190), for reading the thread through the customer's routes; null with no contact or one staff made at the desk.

  • assistantConversationAssistant | nullrequired

    The AI assistant on it (#190); null when it never answered.

  • lastActivityAtstring (date-time)required
  • createdAtstring (date-time)required

OrderInput

  • numberstring | null

    Defaults to the order's externalId (required when that is longer than 60).

  • titlestring | null
  • statusstring | null
  • amountstringrequired

    A decimal string (the service also reads a bare JSON number by its digits; the public door and SDK take a string).

  • currencystringrequired
  • urlstring | null

    Absolute https URL.

  • placedAtstring (date-time)required

    ISO 8601 with a time zone.

OrderResponse

Role

"OWNER" | "ADMIN" | "MEMBER"The VIEWER's role — OWNER on their own workspace, OWNER / ADMIN as a company's representative, ADMIN / MEMBER as a member of the business's team.

Staff

  • userIdstring (uuid)required
  • roleRolerequired

StreamAborted

message.aborted, the same JSON on every audience that may see it. A signal: no id, never replayed, never stored. That reply will not be stored. The stored reply, when one is written, is an ordinary message.created. A note's abort never leaves the staff stream.

  • conversationIdstringrequired
  • messageIdstringrequired

StreamDelta

message.delta, the same JSON on every audience that may see it. A signal: no id, never replayed, never stored, never sent to a channel or webhook. seq is 1, 2, 3… for this messageId and is contiguous. chunk is decoded reply text, never the model's JSON. A visitor hears it only on that conversation's own stream. A note's delta never leaves the staff stream.

  • conversationIdstringrequired
  • messageIdstringrequired
  • seqintegerrequired
  • chunkstringrequired

TicketsCategory

  • idstringrequired
  • namestringrequired
  • descriptionstringrequired

TicketsCategoryList

TicketsConversation

A conversation as the customer's support UI shows it. Never a staff id, an internal note, the assignee, the priority, or the customer's phone and email.

  • idstringrequired
  • numberintegerrequired
  • kind"live" | "ticket"required
  • status"open" | "pending" | "resolved" | "closed"required
  • channel"widget" | "phone" | "email" | "manual" | "api"required
  • openedByStaffbooleanrequired

    Staff opened it at the desk (channel phone, email or manual).

  • subjectstringrequired
  • categoryobject | nullrequired
    فیلدها
    • idstringrequired
    • namestringrequired
  • orderExternalIdstring | nullrequired

    The business's order it is about, as sent.

  • lastMessagestringrequired
  • lastAuthor"customer" | "agent" | "assistant" | "system"required
  • messageCountintegerrequired

    Public messages.

  • unreadCountintegerrequired

    Staff / assistant messages after the customer's last read through this API.

  • awaitingCustomerbooleanrequired

    status pending: staff answered.

  • canRatebooleanrequired

    Resolved or closed, and that resolution not rated yet.

  • ratingTicketsRating | nullrequired
  • assistantConversationAssistant | nullrequired

    The AI assistant on it (#190), for the business's own staff — its state, replies and why it handed off; null when it never answered.

  • lastActivityAtstring (date-time)required
  • resolvedAtstring | null (date-time)required
  • createdAtstring (date-time)required

TicketsConversationPage

TicketsCreateRequest

  • kind"ticket" | "live"required
  • subjectstring

    Required for a ticket.

  • bodystring
  • categoryIdstring | null
  • orderExternalIdstring | null
  • attachmentsstring[]

    Upload ids from POST /api/v1/uploads, not sent yet; with any, body may be empty.

  • contactobject

    Used only when the business has no contact with this externalId: the contact is made from it (counted against the contact ceiling). Judged like a push on every request — a malformed one is VALIDATION even for an existing contact, which is never changed by it.

    فیلدها
    • namestring | null
    • phonestring | null
    • emailstring | null

TicketsMessage

A public message; one staff deleted is never listed (0.32.0).

  • replyToMessageReplyTo | nullrequired
  • idstringrequired
  • author"customer" | "agent" | "assistant" | "system"required
  • senderWidgetTeamMember | null

    Public first name and opaque avatar URL only; omitted without consent or for non-agent messages.

  • bodystringrequired
  • blocksMessageBlock[]required

    Rich staff/assistant content; [] for customer messages or none.

  • attachmentsAttachment[]required
  • createdAtstring (date-time)required
  • editedAtstring | null (date-time)required

    When staff last edited it (0.32.0); null when never.

TicketsRating

  • idstringrequired
  • scoreintegerrequired
  • commentstringrequired
  • createdAtstring (date-time)required

TicketsRatingRequest

  • scoreintegerrequired
  • commentstring | null

TicketsReplyRequest

  • bodystring

    Required unless attachments are sent.

  • attachmentsstring[]

    Upload ids from POST /api/v1/uploads, not sent yet.

TicketsStatusRequest

  • status"resolved" | "open"required

Upload

PUT the file's bytes to uploadUrl (any Content-Type; at most maxBytes) before expiresAt (5 minutes), then name uploadId in a message's attachments within a day. Media answers 413 over the cap and 415 for a type it does not take.

  • uploadIdstringrequired
  • uploadUrlstringrequired
  • expiresAtstring (date-time)required
  • maxBytesintegerrequired
  • visitorTokenstring

    Widget only: present when this call minted the visitor's token.

UploadRequest

The file about to be PUT. contentType and sizeBytes only pick the cap (a video's or a file's) and refuse an obviously too large file early; the stored bytes decide the type and size.

  • namestring

    Kept (cleaned, at most 200 characters) as the file's display and download name.

  • contentTypestring
  • sizeBytesinteger
  • durationMsinteger

    Optional client-measured recording length in milliseconds.

WebhookChange

  • field"status" | "kind" | "assignee"required

    kind: a live chat staff turned into a ticket (0.33.0) — from live, to ticket.

  • fromstring | nullrequired
  • tostring | nullrequired

WebhookConversation

The conversation after the change. Never the customer's name, phone, email, page or visitor token.

  • idstringrequired
  • numberintegerrequired
  • kind"live" | "ticket"required
  • channelstringrequired
  • status"open" | "pending" | "resolved" | "closed"required
  • priority"low" | "normal" | "high" | "urgent"required
  • subjectstringrequired
  • categoryIdstring | nullrequired
  • assigneeUserIdstring | nullrequired
  • contactobject | nullrequired

    The business's customer the conversation is linked to — our id, theirs, and whether the link is proven.

    فیلدها
    • idstringrequired
    • externalIdstringrequired
    • verifiedbooleanrequired

      true only when the conversation was started by a visitor the business's page signed in as this customer (a signed widget identity), or by the business's own server through the tickets API, and is still linked to them; then every customer-authored event in it (created, customer_replied) was written by that customer. false for every other link — a phone or email someone typed into the widget, a channel, or staff (a staff-linked ticket is shown to its customer by the tickets API, but is not verified) — which proves nothing about who is writing: a receiver must never treat it as the customer's identity.

  • createdAtstring (date-time)required
  • updatedAtstring (date-time)required
  • lastActivityAtstring (date-time)required
  • mergedIntoobject

    The conversation staff merged this one into (0.33.0, #171) — its messages are there now. The last key, absent when never merged.

    فیلدها
    • idstringrequired
    • numberintegerrequired

WebhookConversationPayload

Every conversation event. `message` is set on created (the first message, when public) and the two *_replied events; `change` on status_changed and assigned; each null otherwise. conversation.rated has both null and adds `rating` — the last key, absent from every other event.

  • event"conversation.created" | "conversation.customer_replied" | "conversation.staff_replied" | "conversation.status_changed" | "conversation.assigned" | "conversation.rated" | "conversation.message_edited" | "conversation.message_deleted" | "conversation.merged"required
  • occurredAtstring (date-time)required

    UTC, milliseconds.

  • workspaceIdstringrequired
  • conversationWebhookConversationrequired
  • messageWebhookMessage | nullrequired
  • changeWebhookChange | nullrequired
  • conversation.rated only.

WebhookMessage

A public message (never an internal note).

  • idstringrequired
  • author"customer" | "agent" | "assistant"required
  • authorUserIdstring | nullrequired
  • bodystringrequired
  • blocksMessageBlock[]required

    Rich staff/assistant content; [] for customer messages or none.

  • attachmentsAttachment[]required

    Its files; download one through the tickets API (GET …/conversations/{number}/attachments/{id}).

  • createdAtstring (date-time)required
  • editedAtstring (date-time)

    message_edited only (absent otherwise): when staff edited it; body is the new text.

  • deletedAtstring (date-time)

    message_deleted only (absent otherwise): when staff deleted it; body is empty and blocks and attachments [] — the customer no longer sees it.

WebhookRating

The rating a conversation.rated is about.

  • idstringrequired
  • scoreintegerrequired
  • commentstringrequired

    "" for none.

  • source"api" | "widget"required

    api: the tickets API; widget: the widget on the site (0.29.0)

  • resolvedAtstring (date-time)required

    The resolution rated.

  • createdAtstring (date-time)required

WebhookTestPayload

  • event"webhook.test"required
  • occurredAtstring (date-time)required
  • workspaceIdstringrequired
  • webhookIdstringrequired

WidgetTeamMember

  • firstNamestringrequired
  • avatarUrlstringrequired
مرجع API | پیکسول‌چت