API reference

Every v1 method. Each one names the scope it needs.

Me

GET/v1/meNo scope required

Who am I

Key, company and limits. No scope required.

Response · 200 · MeDto
curl -X GET "https://api.tg-desk.com/v1/me" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Conversations

GET/v1/conversationsScope: conversations:read

List conversations

Newest activity first. Scope: `conversations:read`.

Parameters
FieldTypeDescription
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
statusstring query · optional
assignee_idstring query · optionalUser id of the assigned operator
contact_idstring query · optional
tagstring query · optionalTag id
channelstring query · optionalChannel the conversation came in on
updated_sincestring query · optionalOnly conversations changed at or after this ISO-8601 instant — for polling
Response · 200 · ConversationPageDto
curl -X GET "https://api.tg-desk.com/v1/conversations" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/conversationsScope: conversations:start

Start a conversation with a contact

Writes first, the way «Write first» in the inbox does: reuses the contact’s open conversation on the same channel or opens a new one, and sends `body` as the first message, attributed to the key. A channel that cannot initiate (a Telegram, VK or MAX bot to someone who never wrote to it) answers 409. Emits `conversation.created` for a new conversation. Scope: `conversations:start` (+ `conversations:write` for `assignee_id`).

Request body
FieldTypeDescription
contact_idstring requiredAn existing contact of the project
bodystring requiredThe first message, plain text
channelstring optionalDefaults to the channel of the contact’s latest conversation that can start one. Telegram, VK and MAX reach only a customer who wrote to the bot before. email, whatsapp, telegram, vk, max
subjectstring optionalSubject line, for `email` only
assignee_idstring optionalUser to assign the conversation to; needs `conversations:write` as well
Response · 201 · StartConversationResultDto
curl -X POST "https://api.tg-desk.com/v1/conversations" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contact_id": "…", "body": "…"}'
GET/v1/conversations/{id}Scope: conversations:read

Get a conversation

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · ConversationDto
curl -X GET "https://api.tg-desk.com/v1/conversations/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PATCH/v1/conversations/{id}Scope: conversations:write

Update a conversation

Status, assignee and team. Goes through the same transitions the inbox uses — audit line, notifications and scenarios fire as for an operator. Scope: `conversations:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
statusstring optional`open` reopens a closed/spam dialog, wakes a snoozed one or unassigns an assigned one; `snoozed` needs `snoozed_until`; to assign, set `assignee_id` instead. open, closed, snoozed, spam
assignee_idstring | null optionalUser id, or null to unassign
team_idstring | null optionalTeam id, or null to clear
snoozed_untilstring optionalRequired with `status: snoozed`
Response · 200 · ConversationDto
curl -X PATCH "https://api.tg-desk.com/v1/conversations/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
GET/v1/conversations/{id}/messagesScope: conversations:read

List messages of a conversation

Oldest first by default. Internal notes (`type: note`) are returned only to keys holding `notes:write`.

Parameters
FieldTypeDescription
idstring path · required
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
orderstring query · optionalOldest first by default
includestring query · optionalWith `calls:read`: `transcript` adds each call’s full transcript to its card. Left out, `call.transcript` is null to keep the page light — the summary and recordings still come.
Response · 200 · MessagePageDto
curl -X GET "https://api.tg-desk.com/v1/conversations/<id>/messages" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/conversations/{id}/messagesScope: messages:send

Send a reply or leave a note

Attributed to the key («API · <name>» in the inbox). `type: reply` needs `messages:send` and is delivered on the conversation’s channel; `type: note` needs `notes:write` and stays internal.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
bodystring requiredPlain text; Markdown is rendered where the channel supports it
typestring optional`reply` reaches the customer (scope `messages:send`); `note` stays internal (scope `notes:write`) reply, note
Response · 201 · MessageDto
curl -X POST "https://api.tg-desk.com/v1/conversations/<id>/messages" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body": "…"}'
POST/v1/conversations/{id}/tagsScope: conversations:write

Add a tag to a conversation

Idempotent.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
tag_idstring required
Response · 200 · ConversationDto
curl -X POST "https://api.tg-desk.com/v1/conversations/<id>/tags" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag_id": "…"}'
DELETE/v1/conversations/{id}/tags/{tagId}Scope: conversations:write

Remove a tag from a conversation

Idempotent.

Parameters
FieldTypeDescription
idstring path · required
tagIdstring path · required
Response · 200 · ConversationDto
curl -X DELETE "https://api.tg-desk.com/v1/conversations/<id>/tags/<tagId>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/conversations/{id}/meetingsScope: meetings:write

Offer the customer a video meeting

Creates a meeting hosted by `operator_id` and posts its link into the conversation as a reply — what «Offer a meeting» does in the inbox. Scope: `meetings:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
operator_idstring optionalUser who hosts the meeting. Required for an API key — a meeting needs a person to run it.
messagestring optionalInvitation text. `{join_url}` is replaced with the link; without it the link is appended. Defaults to the cabinet’s invitation in the project’s language.
Response · 201 · ProposeMeetingResultDto
curl -X POST "https://api.tg-desk.com/v1/conversations/<id>/meetings" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Contacts

GET/v1/contactsScope: contacts:read

List contacts

Most recently updated first. Scope: `contacts:read`.

Parameters
FieldTypeDescription
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
qstring query · optionalCase-insensitive substring of the name
emailstring query · optionalExact e-mail (any identifier)
phonestring query · optionalExact phone (any identifier)
organization_idstring query · optional
updated_sincestring query · optional
Response · 200 · ContactPageDto
curl -X GET "https://api.tg-desk.com/v1/contacts" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/contactsScope: contacts:write

Create a contact

An e-mail / phone / Telegram username already known in the project answers 409 with the existing id — the same address never creates a second person. Scope: `contacts:write`.

Request body
FieldTypeDescription
namestring required
emailstring optional
phonestring optionalE.164 preferred; national formats are normalised
telegram_usernamestring optional
organization_idstring optionalClient organization to link the contact to
attributesobject optionalCustom attribute values by key (see `GET /v1/contacts/attributes`). Merged: keys you leave out stay, `null` clears one. The widget's rule (ADR-0028): an unknown key is kept (shown under «Другое»), a value of the wrong type is dropped, a long one is cut — each reported in `attribute_warnings` of the response, status 200. A non-object is a 422.
Response · 201 · ContactDto
curl -X POST "https://api.tg-desk.com/v1/contacts" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "…"}'
GET/v1/contacts/attributesScope: contacts:read

List custom contact attributes

The project’s attribute schema: what `attributes` on a contact may hold and of which type. Scope: `contacts:read`.

Response · 200 · ContactAttributeDefinitionListDto
curl -X GET "https://api.tg-desk.com/v1/contacts/attributes" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/contacts/{id}Scope: contacts:read

Get a contact

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · ContactDto
curl -X GET "https://api.tg-desk.com/v1/contacts/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PATCH/v1/contacts/{id}Scope: contacts:write

Update a contact

Absent fields stay; null clears.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
namestring | null optional
emailstring | null optionalReplaces the primary e-mail; null removes it
phonestring | null optional
telegram_usernamestring | null optional
organization_idstring | null optionalnull unlinks
attributesobject optionalCustom attribute values by key (see `GET /v1/contacts/attributes`). Merged: keys you leave out stay, `null` clears one. The widget's rule (ADR-0028): an unknown key is kept (shown under «Другое»), a value of the wrong type is dropped, a long one is cut — each reported in `attribute_warnings` of the response, status 200. A non-object is a 422.
Response · 200 · ContactDto
curl -X PATCH "https://api.tg-desk.com/v1/contacts/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
POST/v1/contacts/{id}/identifiersScope: contacts:write

Add an e-mail / phone / Telegram username to a contact

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
typestring requiredemail, phone, telegram
valuestring required
Response · 200 · ContactDto
curl -X POST "https://api.tg-desk.com/v1/contacts/<id>/identifiers" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "email", "value": "…"}'
DELETE/v1/contacts/{id}/identifiers/{identifierId}Scope: contacts:write

Remove an identifier from a contact

Parameters
FieldTypeDescription
idstring path · required
identifierIdstring path · required
Response · 200 · ContactDto
curl -X DELETE "https://api.tg-desk.com/v1/contacts/<id>/identifiers/<identifierId>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/contacts/{id}/tagsScope: contacts:write

Add a tag to a contact

Idempotent.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
tag_idstring required
Response · 200 · ContactDto
curl -X POST "https://api.tg-desk.com/v1/contacts/<id>/tags" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag_id": "…"}'
DELETE/v1/contacts/{id}/tags/{tagId}Scope: contacts:write

Remove a tag from a contact

Idempotent.

Parameters
FieldTypeDescription
idstring path · required
tagIdstring path · required
Response · 200 · ContactDto
curl -X DELETE "https://api.tg-desk.com/v1/contacts/<id>/tags/<tagId>" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Organizations

GET/v1/organizationsScope: contacts:read

List client organizations

The B2B accounts contacts work for. Scope: `contacts:read`.

Parameters
FieldTypeDescription
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
qstring query · optionalCase-insensitive substring of the name
updated_sincestring query · optional
Response · 200 · OrganizationPageDto
curl -X GET "https://api.tg-desk.com/v1/organizations" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/organizationsScope: contacts:write

Create a client organization

Scope: `contacts:write`.

Request body
FieldTypeDescription
namestring required
emailstring optional
phonestring optional
websitestring optional
Response · 201 · OrganizationDto
curl -X POST "https://api.tg-desk.com/v1/organizations" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "…"}'
GET/v1/organizations/{id}Scope: contacts:read

Get a client organization

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · OrganizationDto
curl -X GET "https://api.tg-desk.com/v1/organizations/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PATCH/v1/organizations/{id}Scope: contacts:write

Rename a client organization

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
namestring optional
Response · 200 · OrganizationDto
curl -X PATCH "https://api.tg-desk.com/v1/organizations/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
POST/v1/organizations/{id}/tagsScope: contacts:write

Add a tag to a client organization

Idempotent.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
tag_idstring required
Response · 200 · OrganizationDto
curl -X POST "https://api.tg-desk.com/v1/organizations/<id>/tags" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag_id": "…"}'
DELETE/v1/organizations/{id}/tags/{tagId}Scope: contacts:write

Remove a tag from a client organization

Idempotent.

Parameters
FieldTypeDescription
idstring path · required
tagIdstring path · required
Response · 200 · OrganizationDto
curl -X DELETE "https://api.tg-desk.com/v1/organizations/<id>/tags/<tagId>" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Tags

GET/v1/tagsScope: tags:read

List tags

Scope: `tags:read`.

Parameters
FieldTypeDescription
scopestring query · optional
Response · 200 · TagListDto
curl -X GET "https://api.tg-desk.com/v1/tags" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/tagsScope: tags:write

Create a tag

A name already used in the same scope answers 409. Scope: `tags:write`. There is no delete: removing a tag strips it everywhere at once, which is for a person.

Request body
FieldTypeDescription
scopestring requiredWhat the tag can be attached to; fixed for life conversation, contact, organization, conference
namestring requiredUp to 40 characters, unique within the scope
colorstring optionalOne of the fixed palette; defaults to the first #ff4747, #ff55a5, #b459c9, #0080ff, #00b8e9, #00b3be, #00bc97, #00be3b, #8ebe00, #baad0e, #e7b500, #ff8200, #ff5f00, #353d43, #75818b, #9ca5ad
Response · 201 · TagDto
curl -X POST "https://api.tg-desk.com/v1/tags" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scope": "conversation", "name": "…"}'
PATCH/v1/tags/{id}Scope: tags:write

Rename or recolor a tag

Every dialog and contact that carries it shows the change. Absent fields stay.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
namestring optional
colorstring optional#ff4747, #ff55a5, #b459c9, #0080ff, #00b8e9, #00b3be, #00bc97, #00be3b, #8ebe00, #baad0e, #e7b500, #ff8200, #ff5f00, #353d43, #75818b, #9ca5ad
Response · 200 · TagDto
curl -X PATCH "https://api.tg-desk.com/v1/tags/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Team

GET/v1/usersScope: team:read

List users (operators)

Active members only. Scope: `team:read`.

Response · 200 · UserListDto
curl -X GET "https://api.tg-desk.com/v1/users" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/teamsScope: team:read

List teams

Scope: `team:read`.

Response · 200 · TeamListDto
curl -X GET "https://api.tg-desk.com/v1/teams" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Help center

GET/v1/kb/handbooksScope: kb:read

List handbooks

Active help centers of the project. Scope: `kb:read`.

Response · 200 · HandbookListDto
curl -X GET "https://api.tg-desk.com/v1/kb/handbooks" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/kb/handbooks/{id}/categoriesScope: kb:read

List categories of a handbook

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · CategoryListDto
curl -X GET "https://api.tg-desk.com/v1/kb/handbooks/<id>/categories" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/kb/articlesScope: kb:read

List articles

Published articles, titles only; fetch one article for its body. A key that also holds `kb:write` may pass `status=draft|archived|all` to see unpublished ones. Scope: `kb:read`.

Parameters
FieldTypeDescription
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
qstring query · optionalSearch words. Matches the article title and its short description, case-insensitively. The body is not searched — ask for the article to read it.
handbook_idstring query · optionalRestrict to one handbook
category_idstring query · optionalRestrict to one category
updated_sincestring query · optional
statusstring query · optionalWhich articles to list. Anything but `published` needs `kb:write` as well — a writer must see the drafts it made; a reader sees only what customers see.
Response · 200 · ArticlePageDto
curl -X GET "https://api.tg-desk.com/v1/kb/articles" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/kb/articlesScope: kb:write

Create an article

The body is Markdown. Creates a DRAFT unless `status` says otherwise — a sync that goes wrong should not publish. Publishing is also what re-indexes the article for the AI operator. Scope: `kb:write`.

Request body
FieldTypeDescription
handbook_idstring requiredWhich handbook the article belongs to
titlestring requiredTitle of the article in this locale
markdownstring requiredThe body, as Markdown. Headings, paragraphs, lists and tables are understood; the same reader the file import uses converts it, so the result is identical to a typed article.
localestring optionalDefaults to the handbook's own locale
category_idstring | null optional
slugstring optionalDerived from the title when omitted
statusstring optionalDefaults to `draft`. Publishing is what re-indexes it for the AI operator. draft, published, archived
Response · 201 · ArticleDto
curl -X POST "https://api.tg-desk.com/v1/kb/articles" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"handbook_id": "…", "title": "…", "markdown": "…"}'
GET/v1/kb/articles/{id}Scope: kb:read

Get an article with its body

A published article. A key that also holds `kb:write` gets drafts and archived articles too; to any other key they are 404, like a missing id. Scope: `kb:read`.

Parameters
FieldTypeDescription
idstring path · required
localestring query · optionalReturn only this locale’s body (all locales by default)
Response · 200 · ArticleDto
curl -X GET "https://api.tg-desk.com/v1/kb/articles/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PATCH/v1/kb/articles/{id}Scope: kb:write

Update an article

Every field is optional. Sending `markdown` replaces the body for that locale and requires `title` alongside it, because a translation carries both. Scope: `kb:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
titlestring optional
markdownstring optionalRequires `title` alongside it
localestring optional
category_idstring | null optional
slugstring optional
statusstring optionaldraft, published, archived
Response · 200 · ArticleDto
curl -X PATCH "https://api.tg-desk.com/v1/kb/articles/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
POST/v1/kb/categoriesScope: kb:write

Create a category

Scope: `kb:write`.

Request body
FieldTypeDescription
handbook_idstring required
slugstring required
translationsCategoryTranslationInputDto[] required
parent_idstring | null optionalNest under another category
Response · 201 · CategoryDto
curl -X POST "https://api.tg-desk.com/v1/kb/categories" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"handbook_id": "…", "slug": "…", "translations": "…"}'
PATCH/v1/kb/categories/{id}Scope: kb:write

Update a category

Scope: `kb:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
slugstring optional
parent_idstring | null optional
translationsCategoryTranslationInputDto[] optional
Response · 200 · CategoryDto
curl -X PATCH "https://api.tg-desk.com/v1/kb/categories/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
POST/v1/kb/mediaScope: kb:write

Upload an image or video for an article

Multipart form: `file` and `handbook_id`. Images (PNG, JPEG, WebP, GIF, AVIF) and video (MP4, WebM, MOV, M4V), up to 50 MB — the same limits as the editor. Put the returned `url` on a line of its own in article Markdown: `![caption](url)`. Scope: `kb:write`.

Response · 201 · MediaDto
curl -X POST "https://api.tg-desk.com/v1/kb/media" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/kb/articles/{id}/translateScope: kb:translate

Translate an article with AI

Starts the same AI translation as the editor, from the article’s own language into each locale in `locales`, and answers 202 at once. Translations land with `source: "ai"`; read the article to see them. A locale a person has edited is skipped unless `overwrite_human` is true. On a published article the new translation is live as soon as it is written. Spends the project’s AI tokens — 402 `ai_budget_exhausted` when they are used up. Scope: `kb:translate`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
localesstring[] requiredTarget locales. Each must be one of the handbook's locales, not its primary.
overwrite_humanboolean optionalRe-translate locales a person has edited too. Off by default: a human translation is never overwritten unless you ask.
Response · 202 · TranslationJobDto
curl -X POST "https://api.tg-desk.com/v1/kb/articles/<id>/translate" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"locales": ["…"]}'

Analytics

GET/v1/analytics/overviewScope: analytics:read

Overview

Headline numbers, the daily series and when the load actually lands. Scope: `analytics:read`.

Parameters
FieldTypeDescription
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · OverviewReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/overview" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/channelsScope: analytics:read

By channel

Volume, share, resolved share and resolution speed per channel. Scope: `analytics:read`.

Parameters
FieldTypeDescription
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · ChannelsReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/channels" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/teamsScope: analytics:read

By team

The same numbers per team, plus the team × channel breakdown. Scope: `analytics:read`.

Parameters
FieldTypeDescription
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · TeamsReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/teams" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/operatorsScope: analytics:read

By operator

Taken, closed and replies per operator. Scope: `analytics:read`.

Parameters
FieldTypeDescription
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · OperatorsReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/operators" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/revenueScope: analytics:read

Revenue

Won revenue, conversion and the split by channel and operator. Scope: `analytics:read`.

Parameters
FieldTypeDescription
recognitionstring query · optionalWhich date the money counts on. Default: `won`.
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · RevenueReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/revenue" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/qualityScope: analytics:read

Dialog quality

AI evaluation of dialogs: average, distribution and the weekly trend. Scope: `analytics:read`.

Parameters
FieldTypeDescription
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · QualityReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/quality" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/botScope: analytics:read

AI operator

How often the agent was used, and how those dialogs ended. Scope: `analytics:read`.

Parameters
FieldTypeDescription
fromstring query · optionalISO-8601 start. Default: 30 days back.
tostring query · optionalISO-8601 end. Default: now. The period must not exceed 366 days.
channelstring query · optionalNarrow to channels. Comma-separated, or repeat the parameter.
teamstring query · optionalTeam ids, comma-separated or repeated.
operatorstring query · optionalUser ids, comma-separated or repeated.
Response · 200 · BotReportDto
curl -X GET "https://api.tg-desk.com/v1/analytics/bot" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/analytics/filtersScope: analytics:read

Filter values

The channels, teams and operators that actually appear in this project — so a caller filters by real values instead of guessing. Scope: `analytics:read`.

Response · 200 · AnalyticsFiltersDto
curl -X GET "https://api.tg-desk.com/v1/analytics/filters" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Meetings

GET/v1/meetingsScope: conferences:read

List meetings

Newest first. Scope: `conferences:read`.

Parameters
FieldTypeDescription
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
Response · 200 · MeetingPageDto
curl -X GET "https://api.tg-desk.com/v1/meetings" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/meetings/{id}Scope: conferences:read

Get a meeting with its summary and transcript

The summary and the transcript are present once the meeting reaches `ready`; before that they are null. Scope: `conferences:read`.

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · MeetingDetailDto
curl -X GET "https://api.tg-desk.com/v1/meetings/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Webhooks

GET/v1/webhooksScope: webhooks:manage

List webhook subscriptions

Scope: `webhooks:manage`.

Response · 200 · WebhookListDto
curl -X GET "https://api.tg-desk.com/v1/webhooks" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/webhooksScope: webhooks:manage

Create a webhook subscription

The signing secret is returned once, here. Verify a delivery as `HMAC-SHA256("<X-Webhook-Timestamp>.<raw body>", secret)` against `X-Webhook-Signature`.

Request body
FieldTypeDescription
namestring requiredHow the subscription is labelled in the settings list
urlstring requiredhttps:// endpoint (http:// allowed for localhost only)
eventsstring[] required
Response · 201 · WebhookWithSecretDto
curl -X POST "https://api.tg-desk.com/v1/webhooks" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "…", "url": "…", "events": ["…"]}'
GET/v1/webhooks/{id}Scope: webhooks:manage

Get a webhook subscription

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · WebhookDto
curl -X GET "https://api.tg-desk.com/v1/webhooks/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PATCH/v1/webhooks/{id}Scope: webhooks:manage

Update a webhook subscription

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
namestring optional
urlstring optional
eventsstring[] optional
activeboolean optionalfalse pauses deliveries; true clears a pause
Response · 200 · WebhookDto
curl -X PATCH "https://api.tg-desk.com/v1/webhooks/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE/v1/webhooks/{id}Scope: webhooks:manage

Delete a webhook subscription

Parameters
FieldTypeDescription
idstring path · required
Response · 204
curl -X DELETE "https://api.tg-desk.com/v1/webhooks/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/webhooks/{id}/rotate-secretScope: webhooks:manage

Rotate the signing secret

The new secret is returned once. Deliveries in flight are signed with the new one.

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · WebhookWithSecretDto
curl -X POST "https://api.tg-desk.com/v1/webhooks/<id>/rotate-secret" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/webhooks/{id}/testScope: webhooks:manage

Send a test event

Queues a `webhook.test` delivery with a sample body; watch it in the log. The delivery is asynchronous, so the answer is `202` — it says the event was queued, not that the endpoint replied.

Parameters
FieldTypeDescription
idstring path · required
Response · 202 · WebhookTestResultDto
curl -X POST "https://api.tg-desk.com/v1/webhooks/<id>/test" \
  -H "Authorization: Bearer $TYGY_API_KEY"
GET/v1/webhooks/{id}/deliveriesScope: webhooks:manage

Delivery log of a subscription

Newest first, kept for 7 days.

Parameters
FieldTypeDescription
idstring path · required
limitstring query · required
Response · 200 · WebhookDeliveryListDto
curl -X GET "https://api.tg-desk.com/v1/webhooks/<id>/deliveries" \
  -H "Authorization: Bearer $TYGY_API_KEY"

Contact notes

GET/v1/contacts/{id}/notesScope: notes:read

List the notes on a contact

The notes on the contact card, newest first. Scope: `notes:read`.

Parameters
FieldTypeDescription
idstring path · required
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
Response · 200 · ContactNotePageDto
curl -X GET "https://api.tg-desk.com/v1/contacts/<id>/notes" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/contacts/{id}/notesScope: notes:write

Add a note to a contact

Shown on the contact card as written by «API · <key name>». Scope: `notes:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
bodystring requiredPlain text, up to 5000 characters
Response · 201 · ContactNoteDto
curl -X POST "https://api.tg-desk.com/v1/contacts/<id>/notes" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body": "…"}'

Macros

GET/v1/macrosScope: macros:read

List shared macros

The project’s shared saved replies, newest first, a page at a time; `q` finds text in the title or the shortcut. Operators’ personal macros are not included. Scope: `macros:read`.

Parameters
FieldTypeDescription
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
qstring query · optionalFinds the text in the title or the shortcut
Response · 200 · MacroListDto
curl -X GET "https://api.tg-desk.com/v1/macros" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/macrosScope: macros:write

Create a shared macro

Scope: `macros:write`. There is no delete: removing a macro is for a person.

Request body
FieldTypeDescription
titlestring requiredUp to 120 characters
bodystring requiredUp to 8000 characters; `{{placeholders}}` allowed
shortcutstring | null optionalA leading «/» is dropped
Response · 201 · MacroDto
curl -X POST "https://api.tg-desk.com/v1/macros" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "…", "body": "…"}'
GET/v1/macros/{id}Scope: macros:read

Get a shared macro

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · MacroDto
curl -X GET "https://api.tg-desk.com/v1/macros/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PATCH/v1/macros/{id}Scope: macros:write

Edit a shared macro

Absent fields stay.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
titlestring optional
bodystring optional
shortcutstring | null optionalnull removes it
Response · 200 · MacroDto
curl -X PATCH "https://api.tg-desk.com/v1/macros/<id>" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Calls

POST/v1/conversations/{id}/callsScope: calls:make

Call the customer (click-to-call)

Asks the connected telephony to ring `operator_id`’s extension first and dial the customer when they pick up — what «Call» does in the inbox. 202 means the provider accepted the request; the call itself appears as a card in the conversation. One attempt per operator at a time; an unclear outcome is never retried for you. Scope: `calls:make`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
operator_idstring optionalUser whose extension rings first; the customer is dialled when they pick up. Required for an API key — a key has no phone of its own.
phonestring optionalOne of the contact's own numbers (any spelling). Defaults to the contact's primary phone; a number not on the contact is a 422 — add it to the contact first.
Response · 202 · CallAttemptDto
curl -X POST "https://api.tg-desk.com/v1/conversations/<id>/calls" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Quality

GET/v1/conversations/{id}/qualityScope: quality:read

Get the quality marks of a conversation

The AI score, the customer’s rating and the reviewer’s verdict. Scope: `quality:read`.

Parameters
FieldTypeDescription
idstring path · required
Response · 200 · ConversationQualityDto
curl -X GET "https://api.tg-desk.com/v1/conversations/<id>/quality" \
  -H "Authorization: Bearer $TYGY_API_KEY"
PUT/v1/conversations/{id}/qualityScope: quality:write

Set the reviewer’s verdict

Rates a CLOSED conversation 1–5; a score of 1–3 needs a `comment`. Replaces the previous verdict, notifies the responsible operator, and a disagreement with the AI score teaches the AI judge — exactly as a review in the inbox. Scope: `quality:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
scorenumber requiredInteger 1–5
commentstring | null optionalRequired for scores 1–3: a low mark without a reason teaches nobody
Response · 200 · ConversationQualityDto
curl -X PUT "https://api.tg-desk.com/v1/conversations/<id>/quality" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"score": 1}'

Organization notes

GET/v1/organizations/{id}/notesScope: notes:read

List the notes on a company

The notes on the client company card, newest first. Scope: `notes:read`.

Parameters
FieldTypeDescription
idstring path · required
limitstring query · optionalPage size, 1…100
starting_afterstring query · optionalCursor from the previous page’s `next_cursor`
Response · 200 · OrganizationNotePageDto
curl -X GET "https://api.tg-desk.com/v1/organizations/<id>/notes" \
  -H "Authorization: Bearer $TYGY_API_KEY"
POST/v1/organizations/{id}/notesScope: notes:write

Add a note to a company

Only for a key that acts on behalf of an employee («Действует от имени»): the note is that person’s, shown as «<employee> · API · <key name>». An integration key with no author gets 409 `author_required`. Scope: `notes:write`.

Parameters
FieldTypeDescription
idstring path · required
Request body
FieldTypeDescription
bodystring requiredPlain text, up to 5000 characters
Response · 201 · OrganizationNoteDto
curl -X POST "https://api.tg-desk.com/v1/organizations/<id>/notes" \
  -H "Authorization: Bearer $TYGY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body": "…"}'