openapi: 3.0.3
info:
title: Tidio OpenAPI (REST)
description: >
REST API for managing contacts, conversations, tickets, operators, and Lyro
AI data sources. Requires Plus or Premium plan for full access; Lyro AI plan
grants access to Lyro-specific endpoints. Authentication uses paired
X-Tidio-Openapi-Client-Id and X-Tidio-Openapi-Client-Secret headers.
Rate limits range from 10 requests per minute (entry plans) to 120 requests
per minute (Premium).
version: "1"
contact:
name: Tidio Developer Support
url: https://developers.tidio.com/support
termsOfService: https://www.tidio.com/terms/
license:
name: Proprietary
url: https://www.tidio.com/terms/
servers:
- url: https://api.tidio.co
description: Tidio REST API
security:
- clientId: []
clientSecret: []
tags:
- name: Contacts
description: Manage contacts (website visitors identified by name, email, or phone)
- name: Tickets
description: Manage email tickets and replies
- name: Operators
description: Retrieve operator (chat agent) information
- name: Departments
description: Retrieve department information
- name: Lyro
description: Lyro AI data sources and ticket answering
- name: Products
description: Product catalog for Lyro AI recommendations
- name: Project
description: Retrieve project information
paths:
/contacts:
get:
operationId: getContacts
tags: [Contacts]
summary: Get contacts
description: >
Returns a paginated list of contacts. Contacts are website visitors who
have interacted with the Tidio widget and have been identified by their
name, email address, or phone number.
parameters:
- name: cursor
in: query
required: false
description: Value from the previous page. Use null to fetch the first page.
schema:
type: string
nullable: true
- name: email
in: query
required: false
description: Filter contacts by email address.
schema:
type: string
format: email
responses:
"200":
description: Paginated list of contacts
content:
application/json:
schema:
$ref: "#/components/schemas/ContactList"
"400":
description: Invalid cursor or bad request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
post:
operationId: createContact
tags: [Contacts]
summary: Create contact
description: >
Creates a new contact. At least one of email, first_name, last_name, or
phone must be provided. Always adds a new contact — no deduplication.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ContactCreate"
responses:
"201":
description: Contact created successfully
content:
application/json:
schema:
$ref: "#/components/schemas/UuidResponse"
"400":
description: Bad request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/contacts/batch:
post:
operationId: createContactsBatch
tags: [Contacts]
summary: Create multiple contacts
description: >
Creates up to 100 contacts in a single request using an all-or-nothing
strategy — if any contact is invalid the entire request fails.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [contacts]
properties:
contacts:
type: array
minItems: 1
maxItems: 100
items:
$ref: "#/components/schemas/ContactCreate"
responses:
"201":
description: Contacts created
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
patch:
operationId: updateContactsBatch
tags: [Contacts]
summary: Update multiple contacts
description: >
Updates up to 100 contacts in a single request using an all-or-nothing
strategy.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [contacts]
properties:
contacts:
type: array
minItems: 1
maxItems: 100
items:
$ref: "#/components/schemas/ContactPatch"
responses:
"200":
description: Contacts updated
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/contacts/{contactId}:
get:
operationId: getContact
tags: [Contacts]
summary: Get single contact
parameters:
- $ref: "#/components/parameters/contactId"
responses:
"200":
description: Contact details
content:
application/json:
schema:
$ref: "#/components/schemas/Contact"
"404":
description: Contact not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
patch:
operationId: updateContact
tags: [Contacts]
summary: Update contact properties
parameters:
- $ref: "#/components/parameters/contactId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ContactPatch"
responses:
"200":
description: Contact updated
"404":
description: Contact not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
delete:
operationId: deleteContact
tags: [Contacts]
summary: Delete contact
description: Permanently deletes a contact. This action cannot be undone.
parameters:
- $ref: "#/components/parameters/contactId"
responses:
"204":
description: Contact deleted successfully
"404":
description: Contact not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/contacts/{contactId}/messages:
get:
operationId: getContactMessages
tags: [Contacts]
summary: Get contact messages
description: Returns all messages in a contact's conversation history.
parameters:
- $ref: "#/components/parameters/contactId"
responses:
"200":
description: Contact messages
content:
application/json:
schema:
type: object
properties:
messages:
type: array
items:
$ref: "#/components/schemas/Message"
"404":
description: Contact not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/contacts/{contactId}/viewed-pages:
get:
operationId: getContactViewedPages
tags: [Contacts]
summary: Get viewed pages history
description: >
Returns a list of pages the contact has viewed on your website, covering
the past 30 days.
parameters:
- $ref: "#/components/parameters/contactId"
responses:
"200":
description: Viewed pages
content:
application/json:
schema:
type: object
properties:
pages:
type: array
items:
type: object
properties:
url:
type: string
format: uri
visited_at:
type: string
format: date-time
"404":
description: Contact not found
/contact-properties:
get:
operationId: getContactProperties
tags: [Contacts]
summary: Get contact properties
description: >
Returns the complete list of contact property definitions (default and
custom) configured in the Tidio panel.
responses:
"200":
description: Contact properties list
content:
application/json:
schema:
type: object
properties:
properties:
type: array
items:
$ref: "#/components/schemas/ContactPropertyDefinition"
/tickets:
get:
operationId: getTickets
tags: [Tickets]
summary: Get tickets
description: Returns a paginated list of tickets without messages.
parameters:
- name: cursor
in: query
required: false
description: Value from the previous page. Use null to fetch the first page.
schema:
type: string
nullable: true
responses:
"200":
description: Paginated list of tickets
content:
application/json:
schema:
$ref: "#/components/schemas/TicketList"
"400":
description: Invalid cursor
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/tickets/as-contact:
post:
operationId: createTicketAsContact
tags: [Tickets]
summary: Create ticket (as Contact)
description: Creates a ticket on behalf of a contact.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/TicketCreateAsContact"
responses:
"201":
description: Ticket created
content:
application/json:
schema:
$ref: "#/components/schemas/UuidResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/tickets/{ticketId}:
get:
operationId: getTicket
tags: [Tickets]
summary: Get ticket details
description: Returns full details of a single ticket including all messages.
parameters:
- $ref: "#/components/parameters/ticketId"
responses:
"200":
description: Ticket with messages
content:
application/json:
schema:
$ref: "#/components/schemas/TicketWithMessages"
"400":
description: Bad request
"404":
description: Ticket not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
patch:
operationId: updateTicket
tags: [Tickets]
summary: Update ticket
description: Updates status, priority, or assignment of a ticket.
parameters:
- $ref: "#/components/parameters/ticketId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/TicketUpdate"
responses:
"204":
description: Ticket updated successfully
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
delete:
operationId: deleteTicket
tags: [Tickets]
summary: Delete ticket
description: Permanently deletes a ticket. This action cannot be undone.
parameters:
- $ref: "#/components/parameters/ticketId"
responses:
"204":
description: Ticket deleted
"404":
description: Ticket not found
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/tickets/{ticketId}/reply:
post:
operationId: replyToTicket
tags: [Tickets]
summary: Reply to a ticket
description: Adds a reply message to an existing ticket from an operator or contact.
parameters:
- $ref: "#/components/parameters/ticketId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/TicketReply"
responses:
"201":
description: Reply created
content:
application/json:
schema:
type: object
properties:
id:
type: string
description: ULID identifier of the created message
example: "01HAVMVKF90KH3EC0HK2T6QYP6"
"400":
description: Bad request
"404":
description: Ticket not found
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/operators:
get:
operationId: getOperators
tags: [Operators]
summary: Get operators
description: Returns a paginated list of operators (chat agents).
parameters:
- name: cursor
in: query
required: false
schema:
type: string
nullable: true
responses:
"200":
description: Paginated list of operators
content:
application/json:
schema:
$ref: "#/components/schemas/OperatorList"
"400":
description: Bad request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/departments:
get:
operationId: getDepartments
tags: [Departments]
summary: Get departments
description: Returns all departments including the default General department.
responses:
"200":
description: List of departments
content:
application/json:
schema:
type: object
properties:
departments:
type: array
items:
$ref: "#/components/schemas/Department"
/project:
get:
operationId: getProject
tags: [Project]
summary: Get project info
description: Returns information about the authenticated project.
responses:
"200":
description: Project information
content:
application/json:
schema:
$ref: "#/components/schemas/Project"
/lyro/data-sources:
get:
operationId: getLyroDataSources
tags: [Lyro]
summary: Get Lyro data sources
description: >
Returns a paginated list of data sources used by the Lyro AI Agent.
Supports filtering by kind (qa/folder) and parent_id.
parameters:
- name: cursor
in: query
required: false
schema:
type: string
nullable: true
- name: kind
in: query
required: false
description: Filter by kind (qa or folder).
schema:
type: array
items:
type: string
enum: [qa, folder]
- name: parent_id
in: query
required: false
description: Filter by parent data source UUID.
schema:
type: string
format: uuid
- name: order
in: query
required: false
description: Sort direction (asc or desc, defaults to desc).
schema:
type: string
enum: [asc, desc]
default: desc
responses:
"200":
description: Paginated list of Lyro data sources
content:
application/json:
schema:
$ref: "#/components/schemas/LyroDataSourceList"
"400":
description: Bad request
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/lyro/data-sources/qa:
post:
operationId: createLyroQaDataSource
tags: [Lyro]
summary: Create Lyro QA data source
description: Creates a QA (question-answer) data source for the Lyro AI Agent.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LyroQaCreate"
responses:
"201":
description: QA data source created
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/lyro/data-sources/website:
put:
operationId: upsertLyroWebsiteDataSource
tags: [Lyro]
summary: Upsert Lyro data source
description: >
Uploads or updates an HTML-based data source for the Lyro AI Agent. If a
source with the same URL exists, it is updated; otherwise a new one is
created.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LyroWebsiteUpsert"
responses:
"200":
description: Data source upserted
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/lyro/data-sources/website/scrape:
post:
operationId: scrapeWebsiteLyroDataSource
tags: [Lyro]
summary: Add website as Lyro data source (scraping)
description: >
Submits a website URL to be scraped and used as a knowledge data source
for the Lyro AI Agent. Each URL must be unique per project.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [url]
properties:
url:
type: string
format: uri
description: Website URL to scrape.
responses:
"201":
description: Website scraping initiated
"409":
description: URL already exists as a data source
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/lyro/tickets:
post:
operationId: askLyroToAnswerTicket
tags: [Lyro]
summary: Ask Lyro to answer ticket
description: >
Asks Lyro AI to generate an answer for a ticket. Processing can take up
to 40 seconds. Currently supports only the first message of a ticket.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LyroTicketRequest"
responses:
"200":
description: Lyro answer generated (may be null if Lyro cannot answer)
content:
application/json:
schema:
type: object
properties:
message_content:
type: string
nullable: true
description: Answer generated by Lyro, or null if unable to answer.
"409":
description: Quota exceeded or Lyro disabled
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/products/batch:
put:
operationId: upsertProducts
tags: [Products]
summary: Upsert products
description: >
Upload or update up to 100 products for Lyro AI recommendations using
batch processing. Products are processed all-or-nothing. Processing is
asynchronous.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [products]
properties:
products:
type: array
minItems: 1
maxItems: 100
items:
$ref: "#/components/schemas/ProductUpsert"
responses:
"204":
description: Products accepted for processing
"400":
description: Bad request
"409":
description: Products import already initialized from e-commerce platform
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"422":
description: Validation error
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/products/{productId}:
delete:
operationId: deleteProduct
tags: [Products]
summary: Delete product
description: >
Permanently removes a product from Lyro AI recommendations. Deletion is
irreversible and processed asynchronously.
parameters:
- name: productId
in: path
required: true
schema:
type: integer
responses:
"204":
description: Product deletion accepted
"404":
description: Product not found
components:
securitySchemes:
clientId:
type: apiKey
in: header
name: X-Tidio-Openapi-Client-Id
clientSecret:
type: apiKey
in: header
name: X-Tidio-Openapi-Client-Secret
parameters:
contactId:
name: contactId
in: path
required: true
description: UUID identifying the contact.
schema:
type: string
format: uuid
example: "a1b4ca4c-1108-4432-b256-1e4cf2bf6f9e"
ticketId:
name: ticketId
in: path
required: true
description: Integer identifying the ticket.
schema:
type: integer
example: 10000
schemas:
ErrorItem:
type: object
properties:
code:
type: string
message:
type: string
ErrorResponse:
type: object
properties:
errors:
type: array
items:
$ref: "#/components/schemas/ErrorItem"
UuidResponse:
type: object
properties:
id:
type: string
format: uuid
PaginationMeta:
type: object
properties:
cursor:
type: string
nullable: true
description: Token for the next page; null when on the last page.
limit:
type: integer
ContactProperty:
type: object
properties:
name:
type: string
maxLength: 128
value:
type: string
maxLength: 1000
Contact:
type: object
properties:
id:
type: string
format: uuid
distinct_id:
type: string
nullable: true
first_name:
type: string
nullable: true
last_name:
type: string
nullable: true
email:
type: string
format: email
nullable: true
phone:
type: string
nullable: true
language:
type: string
nullable: true
description: ISO 639-1 language code.
country:
type: string
nullable: true
description: ISO 3166 Alpha-2 country code.
city:
type: string
nullable: true
created_at:
type: string
format: date-time
email_consent:
type: string
enum: [subscribed, unsubscribed]
properties:
type: array
items:
$ref: "#/components/schemas/ContactProperty"
ContactList:
type: object
properties:
contacts:
type: array
items:
$ref: "#/components/schemas/Contact"
meta:
$ref: "#/components/schemas/PaginationMeta"
ContactCreate:
type: object
description: At least one of email, first_name, last_name, or phone is required.
properties:
email:
type: string
format: email
first_name:
type: string
maxLength: 127
last_name:
type: string
maxLength: 127
phone:
type: string
maxLength: 155
email_consent:
type: string
enum: [subscribed, unsubscribed]
distinct_id:
type: string
maxLength: 55
properties:
type: array
items:
$ref: "#/components/schemas/ContactProperty"
ContactPatch:
type: object
properties:
email:
type: string
format: email
nullable: true
first_name:
type: string
maxLength: 127
nullable: true
last_name:
type: string
maxLength: 127
nullable: true
phone:
type: string
maxLength: 155
nullable: true
email_consent:
type: string
enum: [subscribed, unsubscribed]
distinct_id:
type: string
maxLength: 55
nullable: true
properties:
type: array
items:
$ref: "#/components/schemas/ContactProperty"
ContactPropertyDefinition:
type: object
properties:
name:
type: string
type:
type: string
enum: [text, email, number, phone, url]
Ticket:
type: object
properties:
id:
type: integer
link:
type: string
format: uri
subject:
type: string
contact_id:
type: string
format: uuid
contact_email:
type: string
nullable: true
priority:
type: string
enum: [low, normal, urgent]
status:
type: string
enum: [open, pending, solved]
assigned_operator_id:
type: string
format: uuid
nullable: true
assigned_department_id:
type: string
format: uuid
custom_channel_id:
type: string
nullable: true
TicketList:
type: object
properties:
tickets:
type: array
items:
$ref: "#/components/schemas/Ticket"
meta:
$ref: "#/components/schemas/PaginationMeta"
TicketMessage:
type: object
properties:
message_id:
type: string
description: ULID format identifier.
created_at:
type: string
format: date-time
author_type:
type: string
enum: [operator, contact]
author_id:
type: string
format: uuid
message_type:
type: string
enum: [internal, public]
attachments:
type: array
items:
type: string
format: uri
TicketWithMessages:
allOf:
- $ref: "#/components/schemas/Ticket"
- type: object
properties:
messages:
type: array
items:
$ref: "#/components/schemas/TicketMessage"
TicketUpdate:
type: object
properties:
status:
type: string
enum: [open, pending, solved]
priority:
type: string
enum: [low, normal, urgent]
assigned:
type: object
nullable: true
properties:
type:
type: string
enum: [department, operator]
id:
type: string
format: uuid
TicketReply:
type: object
required: [author_type, content]
properties:
author_type:
type: string
enum: [contact, operator]
content:
type: string
operator_id:
type: string
format: uuid
description: Required when author_type is operator.
message_type:
type: string
enum: [public, internal]
TicketCreateAsContact:
type: object
properties:
subject:
type: string
contact_id:
type: string
format: uuid
content:
type: string
Operator:
type: object
properties:
id:
type: string
format: uuid
active:
type: boolean
email:
type: string
format: email
name:
type: string
nullable: true
role:
type: string
enum: [owner, admin, chat_agent, moderator, custom]
picture:
type: string
format: uri
nullable: true
last_seen:
type: string
format: date-time
nullable: true
OperatorList:
type: object
properties:
operators:
type: array
items:
$ref: "#/components/schemas/Operator"
meta:
$ref: "#/components/schemas/PaginationMeta"
Department:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
Project:
type: object
properties:
id:
type: string
name:
type: string
Message:
type: object
properties:
message_id:
type: string
created_at:
type: string
format: date-time
author_type:
type: string
enum: [operator, contact, bot]
content:
type: string
LyroDataSource:
type: object
properties:
id:
type: string
format: uuid
parent_id:
type: string
format: uuid
nullable: true
title:
type: string
type:
type: string
enum: [qa, website, zendesk_hc, external_html, pdf_file]
kind:
type: string
enum: [qa, folder]
origin:
type: string
enum: [manual, inbox, industry, website, csv_file, pdf_file, zendesk_hc, external_html]
status:
type: string
enum: [in progress, error, used]
used_by_lyro:
type: boolean
used_by_copilot:
type: boolean
sync_status:
type: string
enum: [in progress, error, success]
nullable: true
# --- truncated at 32 KB (35 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/tidio/refs/heads/main/openapi/tidio-openapi-openapi.yml