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 content: type: string nullable: true source_url: type: string format: uri nullable: true skip_auto_sync: type: boolean nullable: true manual_sync_available_at: type: string format: date-time nullable: true next_auto_sync_at: type: string format: date-time nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time LyroDataSourceList: type: object properties: data_sources: type: array items: $ref: "#/components/schemas/LyroDataSource" meta: $ref: "#/components/schemas/PaginationMeta" LyroQaCreate: type: object required: [title, content] properties: title: type: string content: type: string LyroWebsiteUpsert: type: object required: [url, title, content] properties: url: type: string format: uri title: type: string content: type: string description: HTML content to be processed by Lyro. LyroTicketMessage: type: object required: [created_at, message_id, author_type, message_type, message_content] properties: created_at: type: string format: date-time message_id: type: string author_type: type: string enum: [contact] message_type: type: string enum: [public] attachments: type: array items: type: string format: uri message_content: type: string LyroTicketRequest: type: object required: [ticket_id, subject, contact_email, contact_name, recipient_email, messages] properties: ticket_id: type: integer subject: type: string contact_email: type: string format: email contact_name: type: string recipient_email: type: string format: email messages: type: array items: $ref: "#/components/schemas/LyroTicketMessage" ProductUpsert: type: object required: [id, url, title, description, default_currency, status, updated_at] properties: id: type: integer url: type: string maxLength: 512 format: uri image_url: type: string maxLength: 512 format: uri title: type: string maxLength: 512 description: type: string vendor: type: string maxLength: 255 product_type: type: string maxLength: 255 sku: type: string maxLength: 255 barcode: type: string maxLength: 255 default_currency: type: string status: type: string enum: [visible, hidden] price: type: number nullable: true features: type: object additionalProperties: type: string maxLength: 255 updated_at: type: string format: date-time description: ISO 8601 timestamp (e.g., 2023-06-01T10:00:00+00:00).