{
  "components" : {
    "examples" : {
      "problem-account_inactive" : {
        "summary" : "account_inactive",
        "value" : {
          "code" : "account_inactive",
          "detail" : "A empresa associada a esta chave de API está inativa.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 403,
          "title" : "Empresa inativa",
          "type" : "https://developers.mspdesk.com.br/erros/#account_inactive"
        }
      },
      "problem-api_key_expired" : {
        "summary" : "api_key_expired",
        "value" : {
          "code" : "api_key_expired",
          "detail" : "Esta chave de API expirou e não pode mais ser usada.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 401,
          "title" : "Chave de API expirada",
          "type" : "https://developers.mspdesk.com.br/erros/#api_key_expired"
        }
      },
      "problem-api_key_inactive" : {
        "summary" : "api_key_inactive",
        "value" : {
          "code" : "api_key_inactive",
          "detail" : "Esta chave de API está desativada e não pode ser usada.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 401,
          "title" : "Chave de API inativa",
          "type" : "https://developers.mspdesk.com.br/erros/#api_key_inactive"
        }
      },
      "problem-api_key_revoked" : {
        "summary" : "api_key_revoked",
        "value" : {
          "code" : "api_key_revoked",
          "detail" : "Esta chave de API foi revogada e não pode mais ser usada.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 401,
          "title" : "Chave de API revogada",
          "type" : "https://developers.mspdesk.com.br/erros/#api_key_revoked"
        }
      },
      "problem-idempotency_key_reused" : {
        "summary" : "idempotency_key_reused",
        "value" : {
          "code" : "idempotency_key_reused",
          "detail" : "A chave de idempotência foi usada com um corpo de requisição diferente.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 422,
          "title" : "Chave de idempotência reutilizada",
          "type" : "https://developers.mspdesk.com.br/erros/#idempotency_key_reused"
        }
      },
      "problem-idempotency_request_in_progress" : {
        "summary" : "idempotency_request_in_progress",
        "value" : {
          "code" : "idempotency_request_in_progress",
          "detail" : "Uma requisição com a mesma chave de idempotência ainda está em execução.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 409,
          "title" : "Requisição em andamento",
          "type" : "https://developers.mspdesk.com.br/erros/#idempotency_request_in_progress"
        }
      },
      "problem-idempotency_unavailable" : {
        "summary" : "idempotency_unavailable",
        "value" : {
          "code" : "idempotency_unavailable",
          "detail" : "Não foi possível garantir a idempotência da requisição neste momento. Tente novamente.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 503,
          "title" : "Idempotência indisponível",
          "type" : "https://developers.mspdesk.com.br/erros/#idempotency_unavailable"
        }
      },
      "problem-insufficient_scope" : {
        "summary" : "insufficient_scope",
        "value" : {
          "code" : "insufficient_scope",
          "detail" : "Esta chave de API não tem o escopo necessário para executar esta operação.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "requiredScope" : "tickets:write",
          "status" : 403,
          "title" : "Escopo insuficiente",
          "type" : "https://developers.mspdesk.com.br/erros/#insufficient_scope"
        }
      },
      "problem-invalid_api_key" : {
        "summary" : "invalid_api_key",
        "value" : {
          "code" : "invalid_api_key",
          "detail" : "A chave de API apresentada é inválida, desconhecida ou está ausente.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 401,
          "title" : "Chave de API inválida",
          "type" : "https://developers.mspdesk.com.br/erros/#invalid_api_key"
        }
      },
      "problem-invalid_cursor" : {
        "summary" : "invalid_cursor",
        "value" : {
          "code" : "invalid_cursor",
          "detail" : "O cursor informado é inválido ou pertence a outra consulta.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 400,
          "title" : "Cursor de paginação inválido",
          "type" : "https://developers.mspdesk.com.br/erros/#invalid_cursor"
        }
      },
      "problem-invalid_idempotency_key" : {
        "summary" : "invalid_idempotency_key",
        "value" : {
          "code" : "invalid_idempotency_key",
          "detail" : "O cabeçalho Idempotency-Key tem um formato inválido.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 400,
          "title" : "Chave de idempotência inválida",
          "type" : "https://developers.mspdesk.com.br/erros/#invalid_idempotency_key"
        }
      },
      "problem-invalid_query" : {
        "summary" : "invalid_query",
        "value" : {
          "code" : "invalid_query",
          "detail" : "Um ou mais parâmetros de consulta são inválidos.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 400,
          "title" : "Parâmetros de consulta inválidos",
          "type" : "https://developers.mspdesk.com.br/erros/#invalid_query"
        }
      },
      "problem-malformed_request" : {
        "summary" : "malformed_request",
        "value" : {
          "code" : "malformed_request",
          "detail" : "A requisição foi recusada antes de ser interpretada: linha de requisição, caminho ou parâmetros de consulta com caracteres inválidos.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 400,
          "title" : "Requisição malformada",
          "type" : "https://developers.mspdesk.com.br/erros/#malformed_request"
        }
      },
      "problem-not_found" : {
        "summary" : "not_found",
        "value" : {
          "code" : "not_found",
          "detail" : "O recurso solicitado não foi encontrado.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 404,
          "title" : "Recurso não encontrado",
          "type" : "https://developers.mspdesk.com.br/erros/#not_found"
        }
      },
      "problem-public_api_disabled" : {
        "summary" : "public_api_disabled",
        "value" : {
          "code" : "public_api_disabled",
          "detail" : "A API pública não está habilitada para esta empresa. Fale com a MSP Works para habilitá-la. As chaves de API existentes continuam guardadas e voltam a funcionar quando ela for habilitada.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 403,
          "title" : "API pública desabilitada",
          "type" : "https://developers.mspdesk.com.br/erros/#public_api_disabled"
        }
      },
      "problem-rate_limited" : {
        "summary" : "rate_limited",
        "value" : {
          "code" : "rate_limited",
          "detail" : "O limite de uso da API foi atingido. Aguarde o tempo indicado em Retry-After e tente novamente.",
          "layer" : "key",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 429,
          "title" : "Limite de requisições atingido",
          "type" : "https://developers.mspdesk.com.br/erros/#rate_limited"
        }
      },
      "problem-scope_requires_public_api" : {
        "summary" : "scope_requires_public_api",
        "value" : {
          "code" : "scope_requires_public_api",
          "detail" : "A API pública não está habilitada para esta empresa, e este escopo não está entre os liberados por concessão. Marcar o escopo na chave não resolve: fale com a MSP Works para contratar a API pública.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "requiredScope" : "tickets:write",
          "status" : 403,
          "title" : "Escopo não liberado sem a API pública",
          "type" : "https://developers.mspdesk.com.br/erros/#scope_requires_public_api"
        }
      },
      "problem-validation_failed" : {
        "summary" : "validation_failed",
        "value" : {
          "code" : "validation_failed",
          "detail" : "Um ou mais campos são inválidos. Veja \"errors\" para detalhes.",
          "requestId" : "7f3c2a9e-1b4d-4c8e-9a51-2e6f0d8b3c47",
          "status" : 422,
          "title" : "Falha de validação",
          "type" : "https://developers.mspdesk.com.br/erros/#validation_failed"
        }
      }
    },
    "headers" : {
      "RateLimit-Limit" : {
        "description" : "Capacidade do balde mais restritivo consumido nesta requisição",
        "schema" : {
          "format" : "int32",
          "type" : "integer"
        }
      },
      "RateLimit-Remaining" : {
        "description" : "Requisições restantes nesse balde",
        "schema" : {
          "format" : "int32",
          "type" : "integer"
        }
      },
      "RateLimit-Reset" : {
        "description" : "Segundos até o balde encher de novo",
        "schema" : {
          "format" : "int32",
          "type" : "integer"
        }
      },
      "Retry-After" : {
        "description" : "Segundos até poder repetir",
        "schema" : {
          "format" : "int32",
          "type" : "integer"
        }
      }
    },
    "schemas" : {
      "Problem" : {
        "description" : "Erro no formato RFC 9457 (application/problem+json).",
        "properties" : {
          "code" : {
            "description" : "Código estável do erro, para tratamento programático.",
            "example" : "not_found",
            "type" : "string"
          },
          "detail" : {
            "description" : "Explicação legível deste erro específico.",
            "example" : "O recurso solicitado não foi encontrado.",
            "type" : "string"
          },
          "errors" : {
            "description" : "Erros de campo — presente quando a falha vem de validação de campo.",
            "items" : {
              "properties" : {
                "code" : {
                  "description" : "Código estável do erro de campo.",
                  "enum" : [
                    "required",
                    "too_long",
                    "too_short",
                    "invalid_value",
                    "invalid_format",
                    "unknown_field",
                    "unsupported_operator",
                    "unsupported_field",
                    "out_of_range",
                    "not_found",
                    "inactive",
                    "inconsistent_reference",
                    "not_applicable"
                  ],
                  "type" : "string"
                },
                "field" : {
                  "description" : "Campo com erro, em notação de ponto/colchete. Ausente quando o erro não é de um campo específico.",
                  "nullable" : true,
                  "type" : "string"
                },
                "message" : {
                  "description" : "Mensagem traduzida no locale da requisição.",
                  "type" : "string"
                }
              },
              "type" : "object"
            },
            "type" : "array"
          },
          "layer" : {
            "description" : "Presente só no 429",
            "enum" : [
              "ip",
              "company",
              "key",
              "operation",
              "concurrency"
            ],
            "type" : "string"
          },
          "operation" : {
            "description" : "Presente só quando `layer=operation`",
            "enum" : [
              "report",
              "pdf",
              "upload"
            ],
            "type" : "string"
          },
          "requestId" : {
            "description" : "Identificador da requisição — informe-o ao suporte ao reportar um erro.",
            "example" : "7f3a9c2e-4b1d-4f7a-9e0c-2b8d6a1f3c55",
            "type" : "string"
          },
          "requiredScope" : {
            "description" : "Presente só no 403 `insufficient_scope`",
            "type" : "string"
          },
          "status" : {
            "description" : "Status HTTP da resposta.",
            "example" : 404,
            "format" : "int32",
            "type" : "integer"
          },
          "title" : {
            "description" : "Título curto e legível do erro.",
            "example" : "Recurso não encontrado",
            "type" : "string"
          },
          "type" : {
            "description" : "URI que identifica o tipo do erro.",
            "example" : "https://developers.mspdesk.com.br/erros/#not_found",
            "type" : "string"
          }
        },
        "required" : [
          "type",
          "title",
          "status",
          "code",
          "detail"
        ],
        "type" : "object"
      },
      "PublicAgentSummary" : {
        "description" : "Resumo do agente, com `expand=agent` (exige o escopo `agents:read`). `name` é nome e sobrenome.",
        "properties" : {
          "email" : {
            "description" : "E-mail do agente.",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "ID do agente.",
            "example" : 1,
            "format" : "int64",
            "type" : "integer"
          },
          "name" : {
            "description" : "Nome e sobrenome do agente.",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicContactSummary" : {
        "description" : "Resumo do contato, com `expand=contact` (exige o escopo `contacts:read`).",
        "properties" : {
          "email" : {
            "description" : "E-mail do contato; `null` se não cadastrado.",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "ID do contato.",
            "example" : 1,
            "format" : "int64",
            "type" : "integer"
          },
          "name" : {
            "description" : "Nome do contato.",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicCustomerSummary" : {
        "description" : "Resumo do cliente, com `expand=customer` (exige o escopo `customers:read`).",
        "properties" : {
          "fantasyName" : {
            "description" : "Nome fantasia do cliente; `null` se não cadastrado.",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "ID do cliente.",
            "example" : 1,
            "format" : "int64",
            "type" : "integer"
          },
          "name" : {
            "description" : "Razão social do cliente.",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicEmptyInput" : {
        "description" : "Ação sem dados: aceita corpo ausente ou `{}`.",
        "type" : "object"
      },
      "PublicFieldChange" : {
        "description" : "Um campo alterado por um evento do histórico.",
        "properties" : {
          "field" : {
            "description" : "Nome do campo alterado.",
            "example" : "subject",
            "nullable" : true,
            "type" : "string"
          },
          "newValue" : {
            "description" : "Valor depois da alteração. Nulo quando o campo foi esvaziado.",
            "example" : "Impressora sem toner",
            "nullable" : true,
            "type" : "string"
          },
          "oldValue" : {
            "description" : "Valor antes da alteração. Nulo quando o campo estava vazio.",
            "example" : "Impressora sem tinta",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicMessageTemplateApplication" : {
        "description" : "Modelo de mensagem com os placeholders já resolvidos para o ticket.",
        "properties" : {
          "body" : {
            "description" : "Texto do modelo com os placeholders já trocados pelos dados deste ticket, em HTML. É o mesmo texto que a tela insere no editor.",
            "nullable" : true,
            "type" : "string"
          },
          "name" : {
            "description" : "Nome do modelo.",
            "example" : "Solicitação de acesso remoto",
            "nullable" : true,
            "type" : "string"
          },
          "templateId" : {
            "description" : "Identificador do modelo aplicado.",
            "example" : 7,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PublicReport" : {
        "description" : "Relatório personalizado e as colunas do resultado",
        "properties" : {
          "columns" : {
            "description" : "Colunas, na ordem do relatório",
            "items" : {
              "$ref" : "#/components/schemas/PublicReportColumn"
            },
            "nullable" : true,
            "type" : "array"
          },
          "id" : {
            "description" : "UUID do relatório, o mesmo da tela de Relatórios",
            "example" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "format" : "uuid",
            "type" : "string"
          },
          "name" : {
            "description" : "Nome do relatório",
            "example" : "Tickets por SLA",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicReportColumn" : {
        "description" : "Coluna do resultado",
        "properties" : {
          "key" : {
            "description" : "Chave da coluna em cada linha de `execute`. Campo fixo: nome em camelCase (`ticketCode`); campo personalizado: `customFields.<id>` — o valor fica na lista `customFields` da linha, no item de `id` igual a `<id>`, na mesma forma de `customFields` de `/v1/tickets` (e o mesmo nome do filtro de tickets).",
            "example" : "ticketCode",
            "nullable" : true,
            "type" : "string"
          },
          "label" : {
            "description" : "Nome de exibição da coluna, como na tela de Relatórios",
            "example" : "Código do Ticket",
            "nullable" : true,
            "type" : "string"
          },
          "type" : {
            "description" : "Tipo do valor: `STRING`, `INTEGER`, `DECIMAL`, `BOOLEAN`, `DATETIME` (ISO-8601 como em `/v1/tickets`: campo fixo em UTC; campo personalizado com o offset da empresa), `DURATION_MINUTES` (inteiro, minutos), `ENUM` (código, como em `/v1/tickets`), `TAG_LIST` (lista de `{id, name, color}`) ou `OPTION` (campo personalizado de lista: a opção `{id, label}`, como em `/v1/tickets`)",
            "example" : "INTEGER",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicReportRow" : {
        "additionalProperties" : true,
        "description" : "Uma linha do relatório: `ticketId` e uma chave por coluna (`GET /v1/reports/{id}` lista as chaves e os tipos). Campos personalizados ficam em `customFields`, na mesma forma de `/v1/tickets`.",
        "properties" : {
          "customFields" : {
            "description" : "Só quando o relatório tem coluna de campo personalizado: os valores do ticket nesses campos, na forma de `customFields` de `/v1/tickets` — ordem por id do campo, só campos preenchidos (lista vazia quando nenhum está).",
            "items" : {
              "$ref" : "#/components/schemas/PublicTicketCustomField"
            },
            "nullable" : true,
            "type" : "array"
          },
          "ticketId" : {
            "description" : "ID do ticket da linha — use com `/v1/tickets/{id}` e os sub-recursos",
            "example" : 1042,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PublicServiceGroupSummary" : {
        "description" : "Resumo do grupo de serviço, com `expand=serviceGroup` (exige o escopo `settings:read`).",
        "properties" : {
          "id" : {
            "description" : "ID do grupo de serviço.",
            "example" : 1,
            "format" : "int64",
            "type" : "integer"
          },
          "name" : {
            "description" : "Nome do grupo de serviço.",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTag" : {
        "properties" : {
          "color" : {
            "enum" : [
              "GRAY",
              "RED",
              "ORANGE",
              "YELLOW",
              "GREEN",
              "BLUE",
              "INDIGO",
              "PURPLE",
              "PINK"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "format" : "int64",
            "type" : "integer"
          },
          "name" : {
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTagInput" : {
        "properties" : {
          "color" : {
            "enum" : [
              "GRAY",
              "RED",
              "ORANGE",
              "YELLOW",
              "GREEN",
              "BLUE",
              "INDIGO",
              "PURPLE",
              "PINK"
            ],
            "type" : "string"
          },
          "name" : {
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          }
        },
        "required" : [
          "color",
          "name"
        ],
        "type" : "object"
      },
      "PublicTicket" : {
        "description" : "Ticket da empresa da chave.",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente responsável pelo ticket; `null` se não atribuído.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "answered" : {
            "description" : "Indica se o ticket já foi respondido ao menos uma vez.",
            "nullable" : true,
            "type" : "boolean"
          },
          "assetId" : {
            "description" : "ID do ativo vinculado ao ticket; `null` se não vinculado a um ativo.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "businessUnitId" : {
            "description" : "ID da unidade de negócio do cliente; `null` se o ticket não está vinculado a uma unidade.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "categoryId" : {
            "description" : "ID da categoria do ticket; `null` se não categorizado.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "closedAt" : {
            "description" : "Data e hora do fechamento do ticket, em UTC; `null` se ainda não fechado.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "code" : {
            "description" : "Número do ticket, visível ao agente e ao cliente (diferente do `id`).",
            "example" : 1042,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "contactId" : {
            "description" : "ID do contato que abriu ou representa o ticket; `null` se não houver contato.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "createdAt" : {
            "description" : "Data e hora de criação do ticket, em UTC.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "createdById" : {
            "description" : "ID do usuário que criou o ticket; `null` se criado sem um usuário (ex.: por e-mail).",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "customFields" : {
            "description" : "Valores dos campos personalizados do ticket. Só entra um item por campo com valor preenchido; campo sem valor não aparece na lista.",
            "items" : {
              "$ref" : "#/components/schemas/PublicTicketCustomField"
            },
            "nullable" : true,
            "type" : "array"
          },
          "customerId" : {
            "description" : "ID do cliente do ticket; `null` se não vinculado a um cliente.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "deleted" : {
            "description" : "Indica se o ticket foi excluído. Sem `filter[deleted][eq]`, a listagem só traz `false`; `GET /v1/tickets/{id}` devolve também o excluído, com `deleted: true`.",
            "nullable" : true,
            "type" : "boolean"
          },
          "deletedAt" : {
            "description" : "Data e hora da exclusão do ticket, em UTC; `null` se não excluído.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição da abertura do ticket.",
            "nullable" : true,
            "type" : "string"
          },
          "followUpOfId" : {
            "description" : "ID do ticket original, quando este é um desdobramento (follow-up); `null` caso contrário.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "id" : {
            "description" : "Identificador interno do ticket.",
            "example" : 1,
            "format" : "int64",
            "type" : "integer"
          },
          "lastActivityAt" : {
            "description" : "Última atividade no ticket: mudança na linha do ticket ou escrita em nota, resposta, encaminhamento, apontamento, tarefa, item faturável, anexo, seguidor, conversa do MSP Talks, pausa de SLA, campo personalizado ou tags. Precisão de segundo. Pode vir nulo por alguns milissegundos logo após a criação do ticket.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "mergedIntoId" : {
            "description" : "ID do ticket no qual este foi mesclado; `null` se não foi mesclado.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "origin" : {
            "description" : "Canal de origem do ticket (e-mail, portal, telefone etc.).",
            "enum" : [
              "EMAIL",
              "RMM",
              "MSP_TALKS",
              "INTERNAL",
              "PORTAL",
              "EXTERNAL_FORM",
              "API"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "priority" : {
            "description" : "Prioridade do ticket.",
            "enum" : [
              "PLANNED",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "reopened" : {
            "description" : "Indica se o ticket já foi reaberto.",
            "nullable" : true,
            "type" : "boolean"
          },
          "respondedAt" : {
            "description" : "Data e hora da primeira resposta ao ticket, em UTC; `null` se ainda não respondido.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "serviceCatalogId" : {
            "description" : "ID do serviço do catálogo vinculado ao ticket; `null` se não vinculado.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "serviceGroupId" : {
            "description" : "ID do grupo de atendimento do ticket; `null` se não vinculado a um grupo.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "slaResponseDueAt" : {
            "description" : "Prazo do SLA de resposta, em UTC; `null` se o ticket não tem SLA de resposta.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "slaResponseStatus" : {
            "description" : "Status do SLA de resposta; `null` se o ticket não tem SLA de resposta.",
            "enum" : [
              "WITHOUT",
              "WITHIN",
              "APPROACHING_BREACH",
              "BREACHED",
              "FULLFILLED",
              "PAUSED"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "slaSolutionDueAt" : {
            "description" : "Prazo do SLA de solução, em UTC; `null` se o ticket não tem SLA de solução.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "slaSolutionStatus" : {
            "description" : "Status do SLA de solução; `null` se o ticket não tem SLA de solução.",
            "enum" : [
              "WITHOUT",
              "WITHIN",
              "APPROACHING_BREACH",
              "BREACHED",
              "FULLFILLED",
              "PAUSED"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "solvedAt" : {
            "description" : "Data e hora da solução do ticket, em UTC; `null` se ainda não solucionado.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "stageId" : {
            "description" : "ID da etapa atual do ticket dentro do fluxo; `null` se o ticket não estiver em um fluxo.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "status" : {
            "description" : "Status atual do ticket.",
            "enum" : [
              "TO_DO",
              "IN_PROGRESS",
              "PENDING",
              "COMPLETED",
              "CLOSED",
              "DELETED"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "subcategoryId" : {
            "description" : "ID da subcategoria do ticket; `null` se não vinculado a uma subcategoria.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "subject" : {
            "description" : "Assunto do ticket.",
            "nullable" : true,
            "type" : "string"
          },
          "tagIds" : {
            "description" : "IDs das tags aplicadas ao ticket.",
            "items" : {
              "description" : "IDs das tags aplicadas ao ticket.",
              "format" : "int64",
              "type" : "integer"
            },
            "nullable" : true,
            "type" : "array"
          },
          "ticketTypeId" : {
            "description" : "ID do tipo do ticket; `null` se não definido.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "updatedAt" : {
            "description" : "Data e hora da última atualização da linha do ticket, em UTC.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "workflowId" : {
            "description" : "ID do fluxo de trabalho aplicado ao ticket; `null` se nenhum fluxo estiver aplicado.",
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PublicTicketActivity" : {
        "description" : "Uma entrada do histórico de um ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que provocou o evento. Nulo em evento do sistema, de contato ou escrito pela API sem agente no corpo.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "apiKeyId" : {
            "description" : "Chave de API que gravou o evento. Nulo quando a origem não é `API`.",
            "example" : 8,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "apiKeyName" : {
            "description" : "Nome **atual** da chave que gravou o evento — não é uma cópia do nome no momento da escrita. Nulo quando a chave foi excluída.",
            "example" : "Integração ERP",
            "nullable" : true,
            "type" : "string"
          },
          "category" : {
            "description" : "Categoria do evento, a mesma que a aba oferece. É **nula** em seis tipos, que hoje não pertencem a categoria nenhuma — `GROUPING`, `UNGROUPING`, `MERGE`, `AUTOMATION`, `FOLLOWER_ADDED` e `FOLLOWER_REMOVED` —, e por isso `filter[category]` não os alcança. Vale o mesmo na aba do produto.",
            "enum" : [
              "INTERACTIONS",
              "ATTACHMENTS",
              "SLA",
              "COMMUNICATIONS",
              "APPOINTMENTS",
              "INTEGRATIONS",
              "TASKS",
              "ITEMS",
              "WORKFLOW"
            ],
            "example" : "INTERACTIONS",
            "nullable" : true,
            "type" : "string"
          },
          "contactId" : {
            "description" : "Contato do cliente que provocou o evento (portal ou e-mail). Nulo nos demais.",
            "example" : 17,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "createdAt" : {
            "description" : "Instante do evento. Nunca é nulo.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "description" : {
            "description" : "Texto do evento, como foi gravado. **Sempre em português**, qualquer que seja o `Accept-Language` da requisição: o texto é carimbado na coluna no momento da escrita, e não traduzido na leitura — a tela é que o re-renderiza no idioma do usuário. Pode trazer **HTML** embutido (`<br>`, `<strong>`): trate o valor como marcação, não como texto puro. O HTML é servido pela mesma allowlist da escrita (sem `<script>`, atributos `on*` ou URL fora de `http`/`https`/`mailto`/`tel`), inclusive nas entradas antigas. Para tratamento programático, use `type` e `fieldChanges`, que não dependem de idioma.",
            "example" : "Assunto: [Antigo] para [Novo]",
            "nullable" : true,
            "type" : "string"
          },
          "fieldChanges" : {
            "description" : "Mudanças estruturadas do evento, quando houver. Lista vazia nos eventos que não gravam mudança campo a campo.",
            "items" : {
              "$ref" : "#/components/schemas/PublicFieldChange"
            },
            "nullable" : true,
            "type" : "array"
          },
          "id" : {
            "description" : "Identificador da entrada do histórico.",
            "example" : 9120,
            "format" : "int64",
            "type" : "integer"
          },
          "origin" : {
            "description" : "Origem da escrita. `API` é o que esta API gravou.",
            "enum" : [
              "USER",
              "CONTACT_CUSTOMER",
              "EMAIL_INBOUND",
              "NINJA_RMM",
              "DATTO_RMM",
              "SYSTEM",
              "API"
            ],
            "example" : "API",
            "nullable" : true,
            "type" : "string"
          },
          "type" : {
            "description" : "Tipo do evento registrado.",
            "enum" : [
              "CREATION",
              "UPDATE",
              "START",
              "PAUSE",
              "APPOINTMENT_FINISH",
              "DELETE",
              "ANSWERED",
              "PAUSE_SLA",
              "RESUME_SLA",
              "CONCLUSION",
              "CLOSE",
              "REOPENING",
              "ATTACHMENT",
              "REMOVE_ATTACHMENT",
              "CREATION_APPOINTMENT",
              "UPDATE_APPOINTMENT",
              "DELETE_APPOINTMENT",
              "NOTE_ADDED",
              "NOTE_EDITED",
              "NOTE_REMOVED",
              "REPLY_ADDED",
              "FORWARD_ADDED",
              "ALERT_ASSOCIATED",
              "TASK_ADDED",
              "TASK_COMPLETED",
              "TASK_REMOVED",
              "ITEM_ADDED",
              "ITEM_UPDATED",
              "ITEM_REMOVED",
              "FOLLOWER_ADDED",
              "FOLLOWER_REMOVED",
              "GROUPING",
              "UNGROUPING",
              "MERGE",
              "CUSTOMER_CHANGED",
              "AUTOMATION",
              "STAGE_CHANGED",
              "CSAT_DELIVERY"
            ],
            "example" : "UPDATE",
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Igual a `createdAt`: o histórico não é editado.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketAlert" : {
        "description" : "Alerta de RMM vinculado a um ticket.",
        "properties" : {
          "alertCategory" : {
            "description" : "Categoria do alerta. **Só Datto** — nula na origem Ninja.",
            "example" : "Disco",
            "nullable" : true,
            "type" : "string"
          },
          "alertDescription" : {
            "description" : "Descrição do alerta. No Ninja é a mensagem do evento.",
            "example" : "Espaço em disco abaixo de 10%",
            "nullable" : true,
            "type" : "string"
          },
          "alertDiagnostic" : {
            "description" : "Diagnóstico do alerta. **Só Datto** — nulo na origem Ninja.",
            "example" : "Disco C: com 5% livre",
            "nullable" : true,
            "type" : "string"
          },
          "alertPriority" : {
            "description" : "Prioridade do alerta. **Só Datto** — nula na origem Ninja.",
            "enum" : [
              "CRITICAL",
              "HIGH",
              "MODERATE",
              "LOW",
              "INFORMATION"
            ],
            "example" : "CRITICAL",
            "nullable" : true,
            "type" : "string"
          },
          "alertType" : {
            "description" : "Tipo do alerta. **Só Datto** — nulo na origem Ninja.",
            "example" : "disk_usage",
            "nullable" : true,
            "type" : "string"
          },
          "alertUid" : {
            "description" : "Identificador do alerta no Datto RMM. **Só Datto** — nulo na origem Ninja.",
            "example" : "abc123",
            "nullable" : true,
            "type" : "string"
          },
          "conditionLabel" : {
            "description" : "Rótulo do mapeamento de condição, com o `jobCode` como alternativa. **Só Ninja** — nulo na origem Datto.",
            "example" : "Espaço em disco baixo",
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "description" : "Instante do alerta: a criação no Datto, o disparo no Ninja.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "deviceName" : {
            "description" : "Nome do dispositivo monitorado. No Ninja é o nome de sistema, com o nome de exibição como alternativa.",
            "example" : "DESKTOP-01",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "Identificador do alerta, na tabela da origem.",
            "example" : 3312,
            "format" : "int64",
            "type" : "integer"
          },
          "jobCode" : {
            "description" : "Código do job no Ninja. **Só Ninja** — nulo na origem Datto.",
            "example" : "diskSpace",
            "nullable" : true,
            "type" : "string"
          },
          "resolved" : {
            "description" : "Se o alerta já foi baixado. No Ninja é derivado de `resolvedAt`.",
            "example" : false,
            "nullable" : true,
            "type" : "boolean"
          },
          "resolvedAt" : {
            "description" : "Instante da baixa. **Só Ninja** — nulo na origem Datto, que não guarda essa data.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "severity" : {
            "description" : "Severidade do alerta. **Só Ninja** — nula na origem Datto.",
            "example" : "CRITICAL",
            "nullable" : true,
            "type" : "string"
          },
          "siteName" : {
            "description" : "Nome do site no Datto RMM. **Só Datto** — nulo na origem Ninja.",
            "example" : "Matriz",
            "nullable" : true,
            "type" : "string"
          },
          "source" : {
            "description" : "Origem do alerta.",
            "enum" : [
              "DATTO_RMM",
              "NINJA_RMM"
            ],
            "example" : "DATTO_RMM",
            "nullable" : true,
            "type" : "string"
          },
          "statusCode" : {
            "description" : "Situação do alerta no Ninja (`TRIGGERED`, `RESET`, `OTHER`). **Só Ninja** — nula na origem Datto.",
            "example" : "TRIGGERED",
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Última alteração: a data de atualização no Datto; no Ninja, a baixa — ou o próprio disparo, enquanto o alerta estiver aberto.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketAppointment" : {
        "description" : "Apontamento (atendimento registrado) de um ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que assina o apontamento.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "attachmentIds" : {
            "description" : "Anexos do ticket vinculados a este apontamento. Somente leitura: quem vincula arquivo é o envio de anexo, não a criação do apontamento.",
            "items" : {
              "description" : "Anexos do ticket vinculados a este apontamento. Somente leitura: quem vincula arquivo é o envio de anexo, não a criação do apontamento.",
              "format" : "int64",
              "type" : "integer"
            },
            "nullable" : true,
            "type" : "array"
          },
          "backdateReason" : {
            "description" : "Justificativa do lançamento retroativo, quando houve.",
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "description" : "Instante de criação do registro. Nulo em apontamento anterior a esta API.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "date" : {
            "description" : "Data e hora do apontamento, sem fuso, em `yyyy-MM-ddTHH:mm:ss` — os segundos saem sempre, mesmo zerados. Enquanto o atendimento está em andamento, é o instante em que ele começou. Nulo apenas em registro antigo que não tem data nenhuma gravada; ele existe, é listado e ordena antes de todos os outros.",
            "example" : "2026-09-23T14:30:00",
            "nullable" : true,
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição do atendimento, em HTML.",
            "nullable" : true,
            "type" : "string"
          },
          "endTime" : {
            "description" : "Hora de término, sem fuso.",
            "example" : "10:00",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "Identificador do apontamento.",
            "example" : 3021,
            "format" : "int64",
            "type" : "integer"
          },
          "open" : {
            "description" : "O atendimento ainda está em andamento: `true` enquanto ninguém o encerrou. Um apontamento em andamento não entra no resumo de horas.",
            "nullable" : true,
            "type" : "boolean"
          },
          "serviceType" : {
            "description" : "Tipo de serviço do atendimento.",
            "enum" : [
              "INTERNAL",
              "EXTERNAL"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "slaEligible" : {
            "description" : "O apontamento conta para o SLA de resposta.",
            "nullable" : true,
            "type" : "boolean"
          },
          "startTime" : {
            "description" : "Hora de início, sem fuso.",
            "example" : "09:00",
            "nullable" : true,
            "type" : "string"
          },
          "timeSpent" : {
            "description" : "Tempo gasto no formato `HH:mm`.",
            "example" : "01:00",
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Instante da última alteração do registro. Nulo em apontamento anterior a esta API que nunca foi alterado desde então.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketAppointmentInput" : {
        "description" : "Apontamento a registrar no ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que assina o apontamento. Precisa existir, estar ativo e ser da empresa da chave.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "backdateReason" : {
            "description" : "Justificativa do lançamento retroativo. Obrigatória quando o apontamento é anterior ao prazo de um SLA de resposta já violado.",
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string"
          },
          "date" : {
            "description" : "Data e hora do apontamento, **sem fuso**, no formato `yyyy-MM-ddTHH:mm` (os segundos são opcionais).",
            "example" : "2026-09-23T14:30",
            "pattern" : "^\\d{4}-\\d{2}-\\d{2}T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$",
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição do atendimento. Aceita HTML; imagens embutidas em base64 são enviadas para os anexos do ticket e substituídas pela URL.",
            "example" : "<p>Serviço reiniciado.</p>",
            "type" : "string"
          },
          "endTime" : {
            "description" : "Hora de término no formato `HH:mm`. Padrão: a hora de `date`.",
            "example" : "10:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "pauseReasonId" : {
            "description" : "Motivo da pausa de SLA. Obrigatório quando `pauseSla` é `true`.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          },
          "pauseSla" : {
            "description" : "Pausa também o SLA do ticket. Padrão `false`.",
            "type" : "boolean"
          },
          "serviceType" : {
            "description" : "Tipo de serviço do atendimento.",
            "enum" : [
              "INTERNAL",
              "EXTERNAL"
            ],
            "type" : "string"
          },
          "slaEligible" : {
            "description" : "O apontamento conta para o SLA de resposta. Padrão `false`.",
            "type" : "boolean"
          },
          "startTime" : {
            "description" : "Hora de início no formato `HH:mm`.",
            "example" : "09:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "then" : {
            "description" : "Efeito do apontamento sobre o ticket.",
            "enum" : [
              "PAUSE"
            ],
            "type" : "string"
          },
          "timeSpent" : {
            "description" : "Tempo gasto no formato `HH:mm`. Padrão `01:00`.",
            "example" : "01:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          }
        },
        "required" : [
          "agentId",
          "date",
          "description",
          "serviceType"
        ],
        "type" : "object"
      },
      "PublicTicketAppointmentPatchInput" : {
        "description" : "Campos alteráveis de um apontamento (JSON Merge Patch).",
        "properties" : {
          "backdateReason" : {
            "description" : "Justificativa do lançamento retroativo.",
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string"
          },
          "date" : {
            "description" : "Data e hora do apontamento, sem fuso, no formato `yyyy-MM-ddTHH:mm`.",
            "example" : "2026-09-23T14:30",
            "pattern" : "^\\d{4}-\\d{2}-\\d{2}T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$",
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição do atendimento, em HTML.",
            "example" : "<p>Serviço reiniciado.</p>",
            "type" : "string"
          },
          "endTime" : {
            "description" : "Hora de término no formato `HH:mm`.",
            "example" : "10:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "pauseReasonId" : {
            "description" : "Motivo da pausa de SLA. Obrigatório quando `pauseSla` é `true`.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          },
          "pauseSla" : {
            "description" : "Pausa o SLA do ticket agora. Não é um estado do apontamento: mandar `false` não retoma o SLA — para isso existe `POST /v1/tickets/{id}/sla-resume`.",
            "type" : "boolean"
          },
          "serviceType" : {
            "description" : "Tipo de serviço do atendimento.",
            "enum" : [
              "INTERNAL",
              "EXTERNAL"
            ],
            "type" : "string"
          },
          "slaEligible" : {
            "description" : "O apontamento conta para o SLA de resposta.",
            "type" : "boolean"
          },
          "startTime" : {
            "description" : "Hora de início no formato `HH:mm`.",
            "example" : "09:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "timeSpent" : {
            "description" : "Tempo gasto no formato `HH:mm`.",
            "example" : "01:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketAppointmentSummary" : {
        "description" : "Totais de horas e contagem dos apontamentos encerrados do ticket.",
        "properties" : {
          "count" : {
            "description" : "Quantidade de apontamentos já encerrados; os em andamento não entram.",
            "example" : 4,
            "format" : "int32",
            "type" : "integer"
          },
          "externalHours" : {
            "description" : "Soma das horas de atendimento externo, no formato `HH:mm`.",
            "example" : "01:00",
            "nullable" : true,
            "type" : "string"
          },
          "internalHours" : {
            "description" : "Soma das horas de atendimento interno, no formato `HH:mm`.",
            "example" : "02:30",
            "nullable" : true,
            "type" : "string"
          },
          "totalHours" : {
            "description" : "Soma de todas as horas, no formato `HH:mm`.",
            "example" : "03:30",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketAttachment" : {
        "description" : "Arquivo anexado a um ticket.",
        "properties" : {
          "appointmentId" : {
            "description" : "Apontamento a que o anexo está preso. Nulo num anexo solto da aba.",
            "example" : 31,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "contentType" : {
            "description" : "Tipo de mídia declarado no envio.",
            "example" : "application/pdf",
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "description" : "Instante de criação do registro. Nulo em anexo anterior a esta API.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "fileName" : {
            "description" : "Nome do arquivo como a tela o mostra.",
            "example" : "contrato-assinado.pdf",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "Identificador do anexo.",
            "example" : 912,
            "format" : "int64",
            "type" : "integer"
          },
          "inline" : {
            "description" : "O arquivo é uma imagem que o remetente do e-mail declarou embutida no corpo (assinatura, papel de carta). Sempre `false` no que a listagem devolve.",
            "nullable" : true,
            "type" : "boolean"
          },
          "linkedToDescription" : {
            "description" : "O arquivo é uma imagem colada no editor da **descrição** do ticket. Sempre `false` no que a listagem devolve.",
            "nullable" : true,
            "type" : "boolean"
          },
          "noteId" : {
            "description" : "Nota a que o anexo está preso. Nulo num anexo solto da aba.",
            "example" : 77,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "size" : {
            "description" : "Tamanho em bytes.",
            "example" : 184320,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "updatedAt" : {
            "description" : "Instante da última alteração do registro. Nulo em anexo anterior a esta API que nunca foi alterado desde então.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketBillableItem" : {
        "description" : "Item faturável lançado em um ticket.",
        "properties" : {
          "billingStatus" : {
            "description" : "Situação de faturamento do item.",
            "enum" : [
              "PENDING",
              "INVOICED",
              "COMPLETED",
              "CANCELED"
            ],
            "example" : "PENDING",
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "description" : "Instante do lançamento. Nunca é nulo.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "customerId" : {
            "description" : "Cliente do ticket no momento do lançamento — é por ele que a fatura agrupa.",
            "example" : 15,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "description" : {
            "description" : "Descrição do item. Quando o lançamento não a informa, é o nome do produto/serviço no momento do lançamento.",
            "example" : "Hora técnica",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "Identificador do item.",
            "example" : 512,
            "format" : "int64",
            "type" : "integer"
          },
          "invoiceId" : {
            "description" : "Fatura em que o item entrou. Enquanto for nulo, o item se edita e se exclui por esta aba; preenchido, só pela fatura.",
            "example" : 77,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "launchedByAgentId" : {
            "description" : "Agente que lançou o item. Nunca é nulo, e **não muda** numa edição.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "productServiceId" : {
            "description" : "Produto/serviço do catálogo. Nulo quando o produto foi excluído do catálogo depois do lançamento: o item preserva descrição e preço, mas perde o vínculo.",
            "example" : 8,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "quantity" : {
            "description" : "Quantidade lançada. Sempre maior que zero.",
            "example" : 2.0,
            "nullable" : true,
            "type" : "number"
          },
          "totalPrice" : {
            "description" : "`quantity × unitPrice`, com duas casas.",
            "example" : 61.0,
            "nullable" : true,
            "type" : "number"
          },
          "unitPrice" : {
            "description" : "Preço unitário **travado no lançamento** — não acompanha o catálogo.",
            "example" : 30.5,
            "nullable" : true,
            "type" : "number"
          },
          "updatedAt" : {
            "description" : "Instante da última alteração do registro. Nulo em item anterior a esta API que nunca foi alterado desde então.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketBillableItemInput" : {
        "description" : "Produto/serviço a lançar no ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que lança o item. Precisa existir, estar ativo e ser da empresa da chave. Fica registrado como quem lançou, e **não muda** em edições posteriores.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "description" : {
            "description" : "Descrição do item. Ausente, é o nome do produto/serviço no momento do lançamento; presente, não pode ser vazia. Até 255 caracteres.",
            "example" : "Hora técnica",
            "maxLength" : 255,
            "minLength" : 0,
            "pattern" : ".*\\S.*",
            "type" : "string"
          },
          "productServiceId" : {
            "description" : "Produto/serviço do catálogo da empresa da chave.",
            "example" : 8,
            "format" : "int64",
            "type" : "integer"
          },
          "quantity" : {
            "description" : "Quantidade lançada. Maior que zero, com **no máximo 2 casas decimais** e 8 dígitos inteiros — é a precisão da coluna.",
            "example" : 2,
            "exclusiveMinimum" : true,
            "maximum" : 9.999999999E7,
            "minimum" : 0,
            "multipleOf" : 0.01,
            "type" : "number"
          },
          "unitPrice" : {
            "description" : "Preço unitário do item, com **no máximo 2 casas decimais** e 8 dígitos inteiros. Zero é aceito; negativo, não. Ausente, é o preço do produto no catálogo no momento do lançamento — e ele fica travado no item: mudar o catálogo depois não mexe neste lançamento.",
            "example" : 30.5,
            "maximum" : 9.999999999E7,
            "minimum" : 0,
            "multipleOf" : 0.01,
            "type" : "number"
          }
        },
        "required" : [
          "agentId",
          "productServiceId",
          "quantity"
        ],
        "type" : "object"
      },
      "PublicTicketBillableItemPatchInput" : {
        "description" : "Campos alteráveis de um item faturável (JSON Merge Patch).",
        "properties" : {
          "description" : {
            "description" : "Descrição do item. Até 255 caracteres.",
            "example" : "Hora técnica",
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "productServiceId" : {
            "description" : "Produto/serviço do catálogo da empresa da chave.",
            "example" : 8,
            "format" : "int64",
            "type" : "integer"
          },
          "quantity" : {
            "description" : "Quantidade lançada. Maior que zero, com **no máximo 2 casas decimais** e 8 dígitos inteiros — é a precisão da coluna.",
            "example" : 2,
            "exclusiveMinimum" : true,
            "maximum" : 9.999999999E7,
            "minimum" : 0,
            "multipleOf" : 0.01,
            "type" : "number"
          },
          "unitPrice" : {
            "description" : "Preço unitário do item, com **no máximo 2 casas decimais** e 8 dígitos inteiros. Zero é aceito; negativo, não. Trocar o produto **não** retraz o preço do catálogo: o preço é o que estiver aqui.",
            "example" : 30.5,
            "maximum" : 9.999999999E7,
            "minimum" : 0,
            "multipleOf" : 0.01,
            "type" : "number"
          }
        },
        "type" : "object"
      },
      "PublicTicketChatConversationInput" : {
        "description" : "Conversa a iniciar no MSP Talks a partir do ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que fica registrado como quem abriu a conversa. Precisa existir, estar ativo e ser da empresa da chave — é o e-mail dele que o MSP Talks recebe como atendente.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "channelId" : {
            "description" : "Canal por onde falar, entre os da conta do MSP Talks da empresa.",
            "example" : "c1",
            "type" : "string"
          },
          "departmentId" : {
            "description" : "Equipe a quem atribuir a conversa. Opcional.",
            "example" : "d1",
            "type" : "string"
          },
          "parameters" : {
            "additionalProperties" : {
              "description" : "Valor final de cada parâmetro do modelo.",
              "type" : "string"
            },
            "description" : "Valor final de cada parâmetro do modelo.",
            "type" : "object"
          },
          "primary" : {
            "description" : "Se a conversa aberta vira a principal do ticket. Ausente decide sozinho.",
            "example" : true,
            "type" : "boolean"
          },
          "templateId" : {
            "description" : "Modelo aprovado no canal. É ele que define o texto que o cliente recebe.",
            "example" : "t1",
            "maxLength" : 36,
            "minLength" : 0,
            "type" : "string"
          }
        },
        "required" : [
          "agentId",
          "channelId",
          "templateId"
        ],
        "type" : "object"
      },
      "PublicTicketChatNoteInput" : {
        "description" : "Texto da anotação a escrever na conversa do MSP Talks.",
        "properties" : {
          "text" : {
            "description" : "Texto da anotação. Ausente ou em branco, vale o modelo configurado na integração — ou o texto padrão, com código, assunto e link do ticket.",
            "example" : "Chamado em análise pelo time de infraestrutura.",
            "maxLength" : 4000,
            "minLength" : 0,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketChatSession" : {
        "description" : "Conversa do MSP Talks vinculada a um ticket.",
        "properties" : {
          "alsoLinkedToTicketId" : {
            "description" : "Outro ticket da mesma empresa que já usa esta conversa. Só vem preenchido na resposta de `POST /chat-sessions`, e é aviso, não erro: a mesma conversa pode estar em mais de um ticket. Nas demais respostas — inclusive a de iniciar conversa, que também cria um vínculo — vem sempre nulo, porque a conversa é nova e não havia o que comparar.",
            "example" : 1024,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "channelLabel" : {
            "description" : "Canal por onde a conversa acontece, como o catálogo do MSP Talks o nomeia. Decorativo: nulo não impede nada.",
            "example" : "Suporte — (15) 2018-4600",
            "nullable" : true,
            "type" : "string"
          },
          "contactName" : {
            "description" : "Quem está do outro lado da conversa.",
            "example" : "Beltrano",
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "description" : "Instante em que a conversa foi vinculada ao ticket.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "ID do vínculo entre a conversa e o ticket. É o id da rota.",
            "example" : 77,
            "format" : "int64",
            "type" : "integer"
          },
          "lastNoteAt" : {
            "description" : "Instante da última anotação enviada à conversa. Nulo quando nenhuma foi tentada.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "lastNoteStatus" : {
            "description" : "Resultado da última anotação enviada à conversa: `NONE`, `SENT` ou `FAILED`.",
            "example" : "SENT",
            "nullable" : true,
            "type" : "string"
          },
          "linkOrigin" : {
            "description" : "De onde veio o vínculo: `MANUAL` (alguém apontou a conversa), `OUTBOUND` (o Desk abriu a conversa), `WEBHOOK` (a conversa originou o ticket) ou `EMBED` (o ticket foi aberto de dentro da conversa).",
            "example" : "MANUAL",
            "nullable" : true,
            "type" : "string"
          },
          "linkedByAgentId" : {
            "description" : "Agente que vinculou a conversa. Nulo no vínculo automático, que não tem pessoa por trás.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "primarySession" : {
            "description" : "Se esta é a conversa principal do ticket — a que o ticket referencia. No máximo uma por ticket.",
            "example" : true,
            "nullable" : true,
            "type" : "boolean"
          },
          "sessionId" : {
            "description" : "ID da conversa no MSP Talks.",
            "example" : "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "nullable" : true,
            "type" : "string"
          },
          "sessionNumber" : {
            "description" : "Protocolo da conversa no MSP Talks.",
            "example" : "98765",
            "nullable" : true,
            "type" : "string"
          },
          "sessionUrl" : {
            "description" : "Endereço da conversa no MSP Talks. Nulo quando não foi possível derivar o domínio da instalação do cliente.",
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Igual a `lastNoteAt` quando há anotação, e a `createdAt` quando não há: a anotação é a única alteração que o vínculo sofre.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketChatSessionInput" : {
        "description" : "Conversa do MSP Talks a vincular ao ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que fica registrado como quem vinculou a conversa. Precisa existir, estar ativo e ser da empresa da chave.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "primary" : {
            "description" : "Se esta conversa vira a principal do ticket. Ausente decide sozinho — vira principal se o ticket ainda não tiver uma —, e `false` explícito é escolha.",
            "example" : true,
            "type" : "boolean"
          },
          "sessionId" : {
            "description" : "ID da conversa no MSP Talks. Precisa existir lá: o Desk confirma antes de gravar, para não guardar um vínculo que aponta para lugar nenhum.",
            "example" : "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "maxLength" : 36,
            "minLength" : 0,
            "type" : "string"
          }
        },
        "required" : [
          "agentId",
          "sessionId"
        ],
        "type" : "object"
      },
      "PublicTicketChatSessionPatchInput" : {
        "description" : "Campo alterável de um vínculo de conversa (JSON Merge Patch).",
        "properties" : {
          "primary" : {
            "description" : "`true` torna esta a conversa principal do ticket, tirando o posto da que o ocupava. `false` não é aceito.",
            "example" : true,
            "type" : "boolean"
          }
        },
        "type" : "object"
      },
      "PublicTicketCreateInput" : {
        "description" : "Dados de abertura de um ticket.",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente responsável. Precisa estar ativo e ser membro do grupo; exige `serviceGroupId`: agente só é atribuído a ticket com grupo de atendimento.",
            "format" : "int64",
            "type" : "integer"
          },
          "assetId" : {
            "description" : "ID do ativo. Precisa pertencer ao cliente informado.",
            "format" : "int64",
            "type" : "integer"
          },
          "businessUnitId" : {
            "description" : "ID da unidade de negócio. Precisa pertencer ao cliente informado.",
            "format" : "int64",
            "type" : "integer"
          },
          "categoryId" : {
            "description" : "ID da categoria. Precisa pertencer ao serviço do catálogo informado.",
            "format" : "int64",
            "type" : "integer"
          },
          "contactId" : {
            "description" : "ID do contato do ticket. Precisa pertencer ao cliente informado.",
            "format" : "int64",
            "type" : "integer"
          },
          "customFields" : {
            "additionalProperties" : {
              "description" : "Valor JSON livre.",
              "type" : "object"
            },
            "description" : "Valores dos campos personalizados, por ID do campo. O tipo aceito em cada valor é o do campo (texto, número, booleano, data e hora com fuso, ou ID da opção da lista). Campos personalizados de ticket globais e obrigatórios precisam vir preenchidos. Limites: `TEXT` até 255 caracteres e `TEXT_AREA` até 65535 bytes (senão `too_long`); `DECIMAL` entre -99999999.99 e 99999999.99, gravado com duas casas decimais (senão `out_of_range`).",
            "example" : {
              "12" : "valor",
              "15" : 3
            },
            "type" : "object"
          },
          "customerId" : {
            "description" : "ID do cliente do ticket.",
            "format" : "int64",
            "type" : "integer"
          },
          "description" : {
            "description" : "Descrição da abertura. Aceita HTML.",
            "example" : "<p>A impressora do setor parou.</p>",
            "type" : "string"
          },
          "origin" : {
            "description" : "Canal de origem do ticket. Padrão `API` quando o campo não vem no corpo. A autoria da integração fica registrada na linha do tempo do ticket, independentemente do valor escolhido aqui.",
            "enum" : [
              "EMAIL",
              "RMM",
              "MSP_TALKS",
              "INTERNAL",
              "PORTAL",
              "EXTERNAL_FORM",
              "API"
            ],
            "type" : "string"
          },
          "priority" : {
            "description" : "Prioridade do ticket.",
            "enum" : [
              "PLANNED",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL"
            ],
            "type" : "string"
          },
          "resolution" : {
            "$ref" : "#/components/schemas/PublicTicketResolutionInput"
          },
          "serviceCatalogId" : {
            "description" : "ID do serviço do catálogo. Precisa estar vinculado ao grupo informado.",
            "format" : "int64",
            "type" : "integer"
          },
          "serviceGroupId" : {
            "description" : "ID do grupo de atendimento.",
            "format" : "int64",
            "type" : "integer"
          },
          "subcategoryId" : {
            "description" : "ID da subcategoria. Precisa pertencer à categoria informada.",
            "format" : "int64",
            "type" : "integer"
          },
          "subject" : {
            "description" : "Assunto do ticket.",
            "example" : "Impressora não imprime",
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "tagIds" : {
            "description" : "IDs das tags a aplicar ao ticket.",
            "items" : {
              "description" : "IDs das tags a aplicar ao ticket.",
              "format" : "int64",
              "type" : "integer"
            },
            "maxItems" : 200,
            "minItems" : 0,
            "type" : "array"
          },
          "ticketTypeId" : {
            "description" : "ID do tipo do ticket.",
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "contactId",
          "customerId",
          "description",
          "priority",
          "subject"
        ],
        "type" : "object"
      },
      "PublicTicketCustomField" : {
        "description" : "Valor de um campo personalizado do ticket.",
        "properties" : {
          "id" : {
            "description" : "ID do campo personalizado.",
            "example" : 12,
            "format" : "int64",
            "type" : "integer"
          },
          "name" : {
            "description" : "Nome do campo personalizado.",
            "nullable" : true,
            "type" : "string"
          },
          "type" : {
            "description" : "Tipo do campo personalizado — governa o formato de `value`.",
            "enum" : [
              "TEXT",
              "INTEGER",
              "DECIMAL",
              "TEXT_AREA",
              "CHECKBOX",
              "DROPDOWN",
              "DATETIME"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "value" : {
            "description" : "Valor do campo, no formato do tipo (`type`):\n\n| Tipo | Formato de `value` |\n|---|---|\n| `TEXT`, `TEXT_AREA` | string |\n| `INTEGER` | integer |\n| `DECIMAL` | number |\n| `DATETIME` | string date-time, com o offset da empresa no instante do valor |\n| `CHECKBOX` | boolean |\n| `DROPDOWN` | objeto `{id, label}` da opção selecionada; `{id: null, label: <valor gravado>}` quando a opção não existe mais |",
            "nullable" : true,
            "type" : "object"
          }
        },
        "type" : "object"
      },
      "PublicTicketEndAppointmentInput" : {
        "description" : "Agente cuja sessão de atendimento será encerrada.",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente com o atendimento em andamento. Precisa existir e ser da empresa da chave; pode estar inativo.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "agentId"
        ],
        "type" : "object"
      },
      "PublicTicketExpansions" : {
        "description" : "Objetos acrescentados por `expand=` (até 3 por requisição). Cada chave só aparece quando pedida e sai `null` quando a relação está vazia; o `…Id` correspondente continua no ticket.",
        "properties" : {
          "agent" : {
            "allOf" : [
              {
                "$ref" : "#/components/schemas/PublicAgentSummary"
              }
            ],
            "nullable" : true
          },
          "contact" : {
            "allOf" : [
              {
                "$ref" : "#/components/schemas/PublicContactSummary"
              }
            ],
            "nullable" : true
          },
          "customer" : {
            "allOf" : [
              {
                "$ref" : "#/components/schemas/PublicCustomerSummary"
              }
            ],
            "nullable" : true
          },
          "serviceGroup" : {
            "allOf" : [
              {
                "$ref" : "#/components/schemas/PublicServiceGroupSummary"
              }
            ],
            "nullable" : true
          }
        },
        "type" : "object"
      },
      "PublicTicketFollower" : {
        "description" : "Agente que segue um ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que segue o ticket. Identifica o seguidor: é o id da rota de remoção.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "createdAt" : {
            "description" : "Instante em que o agente passou a seguir o ticket. Nulo em vínculo anterior a esta API, que nunca foi carimbado.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "firstName" : {
            "description" : "Primeiro nome do agente.",
            "example" : "Ana",
            "nullable" : true,
            "type" : "string"
          },
          "lastName" : {
            "description" : "Sobrenome do agente.",
            "example" : "Souza",
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Igual a `createdAt`: o vínculo não é editável. Existe para que o filtro por data de alteração funcione em todo sub-recurso, sem exceção.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketFollowerInput" : {
        "description" : "Agente a adicionar como seguidor do ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que passa a seguir o ticket. Precisa existir, estar ativo, ser da empresa da chave e ter acesso ao ticket.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "agentId"
        ],
        "type" : "object"
      },
      "PublicTicketForwardInput" : {
        "description" : "Encaminhamento do ticket para destinatários livres.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que assina o encaminhamento. Opcional: sem ele o encaminhamento fica sem autor humano.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "attachmentIds" : {
            "description" : "Identificadores de anexos já enviados ao ticket que devem seguir no e-mail. Suba o arquivo antes em `POST /v1/tickets/{ticketId}/attachments`. Máximo de 20; um id repetido conta uma vez só. Cada id precisa ser um anexo deste ticket ainda sem nota nem apontamento: id que não está na lista de anexos do ticket responde `404 not_found` e anexo já vinculado responde `422 invalid_value`, os dois em `attachmentIds[i]` e sem gravar nada.",
            "items" : {
              "description" : "Identificadores de anexos já enviados ao ticket que devem seguir no e-mail. Suba o arquivo antes em `POST /v1/tickets/{ticketId}/attachments`. Máximo de 20; um id repetido conta uma vez só. Cada id precisa ser um anexo deste ticket ainda sem nota nem apontamento: id que não está na lista de anexos do ticket responde `404 not_found` e anexo já vinculado responde `422 invalid_value`, os dois em `attachmentIds[i]` e sem gravar nada.",
              "format" : "int64",
              "type" : "integer"
            },
            "maxItems" : 20,
            "minItems" : 0,
            "type" : "array"
          },
          "body" : {
            "description" : "Texto do encaminhamento, em HTML. Alternativo a `messageTemplateId`: informe exatamente um dos dois.",
            "type" : "string"
          },
          "messageTemplateId" : {
            "description" : "Modelo de mensagem a aplicar ao ticket; o texto resolvido vira o corpo do encaminhamento. Alternativo a `body`.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          },
          "recipients" : {
            "description" : "Destinatários do e-mail. Ao menos um, no máximo 20, sem repetições nem elementos vazios. Juntos, separados por `; `, cabem em 4000 caracteres; acima disso a resposta é `422` com `too_long`.",
            "items" : {
              "description" : "Destinatários do e-mail. Ao menos um, no máximo 20, sem repetições nem elementos vazios. Juntos, separados por `; `, cabem em 4000 caracteres; acima disso a resposta é `422` com `too_long`.",
              "type" : "string"
            },
            "maxItems" : 20,
            "minItems" : 0,
            "type" : "array"
          },
          "subject" : {
            "description" : "Assunto do e-mail. Obrigatório mesmo com `messageTemplateId`: o modelo de mensagem não tem assunto.",
            "example" : "Fwd: acesso remoto",
            "type" : "string"
          },
          "visibility" : {
            "description" : "Visibilidade da nota do encaminhamento, obrigatória: `PRIVATE` deixa a conversa só para os agentes e `PUBLIC` a mostra ao contato do cliente no portal. Não tem efeito sobre o e-mail — os destinatários recebem nos dois casos.",
            "enum" : [
              "PUBLIC",
              "PRIVATE"
            ],
            "type" : "string"
          }
        },
        "required" : [
          "recipients",
          "subject",
          "visibility"
        ],
        "type" : "object"
      },
      "PublicTicketMergeInput" : {
        "description" : "Tickets secundários a consolidar no ticket da rota.",
        "properties" : {
          "secondaryTicketIds" : {
            "description" : "IDs dos tickets secundários. Precisam ser do mesmo cliente do principal, distintos entre si, diferentes do ticket da rota e não estar na lixeira. A lista não pode ser vazia: sem nenhum ID a resposta é `422 validation_failed` com `required` neste campo.",
            "example" : [
              101,
              102
            ],
            "items" : {
              "description" : "IDs dos tickets secundários. Precisam ser do mesmo cliente do principal, distintos entre si, diferentes do ticket da rota e não estar na lixeira. A lista não pode ser vazia: sem nenhum ID a resposta é `422 validation_failed` com `required` neste campo.",
              "format" : "int64",
              "type" : "integer"
            },
            "maxItems" : 50,
            "minItems" : 0,
            "type" : "array"
          }
        },
        "required" : [
          "secondaryTicketIds"
        ],
        "type" : "object"
      },
      "PublicTicketNote" : {
        "description" : "Nota, resposta ou encaminhamento registrado no ticket.",
        "properties" : {
          "apiKeyId" : {
            "description" : "Identificador da chave de API que escreveu a nota; nulo quando a nota não veio da API.",
            "example" : 17,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "apiKeyName" : {
            "description" : "Nome atual da chave de API que escreveu a nota; nulo quando a chave não existe mais ou não é desta empresa.",
            "nullable" : true,
            "type" : "string"
          },
          "attachmentIds" : {
            "description" : "Anexos do ticket vinculados a esta nota.",
            "items" : {
              "description" : "Anexos do ticket vinculados a esta nota.",
              "format" : "int64",
              "type" : "integer"
            },
            "nullable" : true,
            "type" : "array"
          },
          "authorAgentId" : {
            "description" : "Agente que assina a nota; nulo nas notas sem autor humano.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "authorContactId" : {
            "description" : "Contato que escreveu a nota pelo portal ou por e-mail; nulo nas demais.",
            "example" : 88,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "body" : {
            "description" : "Texto da nota, em HTML.",
            "nullable" : true,
            "type" : "string"
          },
          "cc" : {
            "description" : "Cópias do e-mail, separadas por `; ` — preenchido na resposta.",
            "nullable" : true,
            "type" : "string"
          },
          "createdAt" : {
            "description" : "Instante de criação da nota.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "id" : {
            "description" : "Identificador da nota.",
            "example" : 1204,
            "format" : "int64",
            "type" : "integer"
          },
          "mentionedAgentIds" : {
            "description" : "Agentes mencionados na nota.",
            "items" : {
              "description" : "Agentes mencionados na nota.",
              "format" : "int64",
              "type" : "integer"
            },
            "nullable" : true,
            "type" : "array"
          },
          "origin" : {
            "description" : "Quem originou a nota: `USER` (tela), `API` (integração), `CONTACT_CUSTOMER` (portal), `EMAIL_INBOUND`, integrações de monitoramento ou `SYSTEM`.",
            "enum" : [
              "USER",
              "CONTACT_CUSTOMER",
              "EMAIL_INBOUND",
              "NINJA_RMM",
              "DATTO_RMM",
              "SYSTEM",
              "API"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "recipients" : {
            "description" : "Destinatários do e-mail, separados por `; ` — preenchido em resposta e encaminhamento.",
            "nullable" : true,
            "type" : "string"
          },
          "sender" : {
            "description" : "Remetente registrado quando a nota veio de um e-mail recebido.",
            "nullable" : true,
            "type" : "string"
          },
          "type" : {
            "description" : "Tipo da nota: nota simples, resposta ao contato ou encaminhamento.",
            "enum" : [
              "FORWARD",
              "REPLY",
              "NOTE"
            ],
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Instante da última alteração da nota; igual a `createdAt` enquanto a nota nunca tiver sido editada.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "visibility" : {
            "description" : "Visibilidade: `PUBLIC` aparece para o solicitante no portal e no e-mail; `PRIVATE` fica só para os agentes.",
            "enum" : [
              "PUBLIC",
              "PRIVATE"
            ],
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketNoteInput" : {
        "description" : "Nota a registrar no ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que assina a nota. Opcional: sem ele a nota fica sem autor humano, como as automáticas — e, sem autor, ela não dispara a automação de fluxo por comentário de agente.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "body" : {
            "description" : "Texto da nota, em HTML. Alternativo a `messageTemplateId`: informe exatamente um dos dois.",
            "type" : "string"
          },
          "mentionedAgentIds" : {
            "description" : "Agentes mencionados na nota. Cada um precisa existir e estar ativo nesta empresa. Máximo de 50; um id repetido conta uma vez só.",
            "items" : {
              "description" : "Agentes mencionados na nota. Cada um precisa existir e estar ativo nesta empresa. Máximo de 50; um id repetido conta uma vez só.",
              "format" : "int64",
              "type" : "integer"
            },
            "maxItems" : 50,
            "minItems" : 0,
            "type" : "array"
          },
          "messageTemplateId" : {
            "description" : "Modelo de mensagem a aplicar ao ticket; o texto resolvido vira o corpo da nota. Alternativo a `body`.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          },
          "then" : {
            "description" : "Efeito da nota sobre o ticket.",
            "enum" : [
              "PAUSE",
              "COMPLETE"
            ],
            "type" : "string"
          },
          "visibility" : {
            "default" : "PRIVATE",
            "description" : "Visibilidade da nota. Ausente, a nota nasce `PRIVATE`.",
            "enum" : [
              "PUBLIC",
              "PRIVATE"
            ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketNotePatchInput" : {
        "description" : "Campos alteráveis de uma nota.",
        "properties" : {
          "body" : {
            "description" : "Texto da nota, em HTML.",
            "type" : "string"
          },
          "visibility" : {
            "description" : "Visibilidade da nota.",
            "enum" : [
              "PUBLIC",
              "PRIVATE"
            ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketPatchInput" : {
        "description" : "Alterações a aplicar no ticket (JSON Merge Patch, RFC 7396).",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente responsável. Precisa estar ativo e ser membro do grupo; agente só é atribuído a ticket com grupo de atendimento (o `serviceGroupId` do corpo ou o já gravado).",
            "format" : "int64",
            "type" : "integer"
          },
          "assetId" : {
            "description" : "ID do ativo. `null` desvincula o ativo.",
            "format" : "int64",
            "type" : "integer"
          },
          "businessUnitId" : {
            "description" : "ID da unidade de negócio. `null` desvincula a unidade.",
            "format" : "int64",
            "type" : "integer"
          },
          "categoryId" : {
            "description" : "ID da categoria. Precisa pertencer ao serviço do catálogo do ticket.",
            "format" : "int64",
            "type" : "integer"
          },
          "contactId" : {
            "description" : "ID do contato do ticket. Sem troca de cliente, precisa pertencer ao cliente atual.",
            "format" : "int64",
            "type" : "integer"
          },
          "customFields" : {
            "additionalProperties" : {
              "description" : "Valor JSON livre.",
              "type" : "object"
            },
            "description" : "Valores dos campos personalizados, por ID do campo. O merge é POR CHAVE: um campo não citado fica intacto, e `null` limpa o valor daquele campo. `customFields: null` limpa TODOS os campos (pela RFC 7396, como `tagIds: null`); um campo obrigatório continua recusando a limpeza. Para manter os campos como estão, não envie `customFields`. Limites: `TEXT` até 255 caracteres e `TEXT_AREA` até 65535 bytes (senão `too_long`); `DECIMAL` entre -99999999.99 e 99999999.99, gravado com duas casas decimais (senão `out_of_range`).",
            "example" : {
              "12" : "valor",
              "15" : null
            },
            "type" : "object"
          },
          "customerId" : {
            "description" : "ID do cliente do ticket. Trocar o cliente passa pelas regras da troca de cliente (escopo, mesclagem, faturamento pendente e coerência de contato, ativo e unidade).",
            "format" : "int64",
            "type" : "integer"
          },
          "description" : {
            "description" : "Descrição da abertura. Aceita HTML.",
            "type" : "string"
          },
          "origin" : {
            "description" : "Canal de origem do ticket.",
            "enum" : [
              "EMAIL",
              "RMM",
              "MSP_TALKS",
              "INTERNAL",
              "PORTAL",
              "EXTERNAL_FORM",
              "API"
            ],
            "type" : "string"
          },
          "priority" : {
            "description" : "Prioridade do ticket. Mudar a prioridade exige `priorityChangeReason`.",
            "enum" : [
              "PLANNED",
              "LOW",
              "MEDIUM",
              "HIGH",
              "CRITICAL"
            ],
            "type" : "string"
          },
          "priorityChangeReason" : {
            "description" : "Justificativa da mudança de prioridade. Só de escrita: nunca aparece na representação do ticket. É exigida quando `priority` muda, e recusada quando não muda — informá-la sozinha é `422 validation_failed` com `not_applicable` neste campo.",
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string"
          },
          "serviceCatalogId" : {
            "description" : "ID do serviço do catálogo. Precisa estar vinculado ao grupo do ticket.",
            "format" : "int64",
            "type" : "integer"
          },
          "serviceGroupId" : {
            "description" : "ID do grupo de atendimento. Trocar o grupo pode reavaliar o fluxo de trabalho do ticket.",
            "format" : "int64",
            "type" : "integer"
          },
          "subcategoryId" : {
            "description" : "ID da subcategoria. Precisa pertencer à categoria do ticket.",
            "format" : "int64",
            "type" : "integer"
          },
          "subject" : {
            "description" : "Assunto do ticket.",
            "example" : "Impressora não imprime",
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          },
          "tagIds" : {
            "description" : "IDs das tags do ticket. A lista SUBSTITUI o conjunto atual; `[]` remove todas, e `null` também — pela RFC 7396 `null` remove o campo, e um ticket sem o campo `tagIds` é um ticket sem tag. Para manter as tags como estão, não envie o campo.",
            "items" : {
              "description" : "IDs das tags do ticket. A lista SUBSTITUI o conjunto atual; `[]` remove todas, e `null` também — pela RFC 7396 `null` remove o campo, e um ticket sem o campo `tagIds` é um ticket sem tag. Para manter as tags como estão, não envie o campo.",
              "format" : "int64",
              "type" : "integer"
            },
            "maxItems" : 200,
            "minItems" : 0,
            "type" : "array"
          },
          "ticketTypeId" : {
            "description" : "ID do tipo do ticket.",
            "format" : "int64",
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PublicTicketPauseInput" : {
        "description" : "Encerramento do atendimento em andamento, com os dados do apontamento.",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente com o atendimento em andamento. Precisa existir, estar ativo e ser da empresa da chave.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "backdateReason" : {
            "description" : "Justificativa do lançamento retroativo. Obrigatória quando o apontamento é anterior ao prazo de um SLA de resposta já violado.",
            "maxLength" : 500,
            "minLength" : 0,
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição do que foi feito. Aceita HTML; imagens embutidas em base64 são enviadas para os anexos do ticket e substituídas pela URL.",
            "example" : "<p>Serviço reiniciado.</p>",
            "type" : "string"
          },
          "endTime" : {
            "description" : "Hora de término no formato `HH:mm`. Padrão: agora.",
            "example" : "10:30",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "pauseReasonId" : {
            "description" : "Motivo da pausa de SLA. Obrigatório quando `pauseSla` é `true`.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          },
          "pauseSla" : {
            "description" : "Pausa também o SLA do ticket. Padrão `false`.",
            "type" : "boolean"
          },
          "serviceType" : {
            "description" : "Tipo de serviço do atendimento.",
            "enum" : [
              "INTERNAL",
              "EXTERNAL"
            ],
            "type" : "string"
          },
          "slaEligible" : {
            "description" : "O apontamento conta para o SLA de resposta. Padrão `false`.",
            "type" : "boolean"
          },
          "startTime" : {
            "description" : "Hora de início no formato `HH:mm`. Padrão: a hora em que o atendimento começou.",
            "example" : "09:00",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "timeSpent" : {
            "description" : "Tempo gasto no formato `HH:mm`. Padrão `00:00`.",
            "example" : "01:30",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          }
        },
        "required" : [
          "agentId",
          "description",
          "serviceType"
        ],
        "type" : "object"
      },
      "PublicTicketReplyInput" : {
        "description" : "Resposta a enviar ao contato do ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que assina a resposta. Opcional: sem ele a resposta fica sem autor humano.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "attachmentIds" : {
            "description" : "Identificadores de anexos já enviados ao ticket que devem seguir no e-mail. Suba o arquivo antes em `POST /v1/tickets/{ticketId}/attachments`. Máximo de 20; um id repetido conta uma vez só. Cada id precisa ser um anexo deste ticket ainda sem nota nem apontamento: id que não está na lista de anexos do ticket responde `404 not_found` e anexo já vinculado responde `422 invalid_value`, os dois em `attachmentIds[i]` e sem gravar nada.",
            "items" : {
              "description" : "Identificadores de anexos já enviados ao ticket que devem seguir no e-mail. Suba o arquivo antes em `POST /v1/tickets/{ticketId}/attachments`. Máximo de 20; um id repetido conta uma vez só. Cada id precisa ser um anexo deste ticket ainda sem nota nem apontamento: id que não está na lista de anexos do ticket responde `404 not_found` e anexo já vinculado responde `422 invalid_value`, os dois em `attachmentIds[i]` e sem gravar nada.",
              "format" : "int64",
              "type" : "integer"
            },
            "maxItems" : 20,
            "minItems" : 0,
            "type" : "array"
          },
          "body" : {
            "description" : "Texto da resposta, em HTML. Alternativo a `messageTemplateId`: informe exatamente um dos dois.",
            "type" : "string"
          },
          "cc" : {
            "description" : "Endereços em cópia. O destinatário principal é sempre o contato do ticket e não entra aqui. Máximo de 20, sem repetições nem elementos vazios. Juntos, separados por `; `, cabem em 4000 caracteres; acima disso a resposta é `422` com `too_long`.",
            "items" : {
              "description" : "Endereços em cópia. O destinatário principal é sempre o contato do ticket e não entra aqui. Máximo de 20, sem repetições nem elementos vazios. Juntos, separados por `; `, cabem em 4000 caracteres; acima disso a resposta é `422` com `too_long`.",
              "type" : "string"
            },
            "maxItems" : 20,
            "minItems" : 0,
            "type" : "array"
          },
          "messageTemplateId" : {
            "description" : "Modelo de mensagem a aplicar ao ticket; o texto resolvido vira o corpo da resposta. Alternativo a `body`.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          },
          "then" : {
            "description" : "Efeito da nota sobre o ticket.",
            "enum" : [
              "PAUSE",
              "COMPLETE"
            ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketResolutionInput" : {
        "description" : "Resolução aplicada ao criar e concluir o ticket na mesma requisição.",
        "properties" : {
          "description" : {
            "description" : "Texto do realizado. Aceita HTML.",
            "example" : "<p>Reinício do serviço.</p>",
            "type" : "string"
          },
          "serviceType" : {
            "description" : "Tipo de serviço do atendimento.",
            "enum" : [
              "INTERNAL",
              "EXTERNAL"
            ],
            "type" : "string"
          },
          "timeSpent" : {
            "description" : "Tempo gasto no formato `HH:mm`. Padrão `00:00`. Ignorado quando `type` é `NOTE`.",
            "example" : "01:30",
            "pattern" : "^([01]\\d|2[0-3]):[0-5]\\d$",
            "type" : "string"
          },
          "type" : {
            "description" : "Forma de registrar o realizado do criar-e-concluir.",
            "enum" : [
              "NOTE",
              "APPOINTMENT"
            ],
            "type" : "string"
          },
          "visibility" : {
            "description" : "Visibilidade da nota de conclusão. Padrão `PRIVATE`. Ignorada quando `type` é `APPOINTMENT`.",
            "enum" : [
              "PUBLIC",
              "PRIVATE"
            ],
            "type" : "string"
          }
        },
        "required" : [
          "description",
          "serviceType"
        ],
        "type" : "object"
      },
      "PublicTicketSlaPauseInput" : {
        "description" : "Pausa manual do SLA do ticket.",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente que assina a pausa. Precisa existir, estar ativo e ser da empresa da chave.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "description" : {
            "description" : "Observação livre sobre a pausa.",
            "example" : "Aguardando retorno do cliente.",
            "maxLength" : 1000,
            "minLength" : 0,
            "type" : "string"
          },
          "pauseReasonId" : {
            "description" : "ID do motivo de pausa. Precisa estar ativo e ser da empresa da chave.",
            "example" : 3,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "agentId",
          "pauseReasonId"
        ],
        "type" : "object"
      },
      "PublicTicketStageInput" : {
        "description" : "Etapa do fluxo para onde o ticket vai.",
        "properties" : {
          "stageId" : {
            "description" : "ID da etapa alvo. Precisa pertencer ao fluxo em que o ticket está.",
            "example" : 12,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "stageId"
        ],
        "type" : "object"
      },
      "PublicTicketStartInput" : {
        "description" : "Agente que inicia o atendimento do ticket.",
        "properties" : {
          "agentId" : {
            "description" : "ID do agente que inicia o atendimento. Precisa existir, estar ativo e ser da empresa da chave.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "agentId"
        ],
        "type" : "object"
      },
      "PublicTicketTask" : {
        "description" : "Tarefa (item da lista de afazeres) de um ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente responsável pela tarefa. Nulo quando ninguém responde por ela — e sempre nulo em um título de grupo.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "completed" : {
            "description" : "A tarefa está concluída. Sempre `false` em um título de grupo.",
            "nullable" : true,
            "type" : "boolean"
          },
          "createdAt" : {
            "description" : "Instante de criação do registro. Nulo em tarefa anterior a esta API.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "createdById" : {
            "description" : "Agente que criou a tarefa. Nunca é nulo.",
            "example" : 42,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "deadline" : {
            "description" : "Prazo da tarefa, **sem fuso**, em `yyyy-MM-ddTHH:mm:ss` — os segundos saem sempre, mesmo zerados, e a entrada os aceita como opcionais. Nulo quando a tarefa não tem prazo.",
            "example" : "2026-12-01T09:30:00",
            "nullable" : true,
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição livre. Sempre nula em um título de grupo.",
            "nullable" : true,
            "type" : "string"
          },
          "groupTitle" : {
            "description" : "A linha é um **título de grupo**: um separador que agrupa as tarefas abaixo dele, sem prazo, responsável, descrição nem conclusão próprios.",
            "nullable" : true,
            "type" : "boolean"
          },
          "id" : {
            "description" : "Identificador da tarefa.",
            "example" : 512,
            "format" : "int64",
            "type" : "integer"
          },
          "position" : {
            "description" : "Posição na ordem da aba, crescente. Nula em tarefa anterior a esta API, que nunca recebeu posição; a listagem a ordena antes de todas as outras. Pode ser negativa: é um número de ordenação relativo, não um índice. Não é editável pelo `PATCH`: quem a muda é `POST /tasks/{taskId}/move`.",
            "example" : 200,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          },
          "title" : {
            "description" : "Título da tarefa.",
            "example" : "Validar o backup do servidor",
            "nullable" : true,
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "Instante da última alteração do registro. Nulo em tarefa anterior a esta API que nunca foi alterada desde então.",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketTaskFromTemplateInput" : {
        "description" : "Modelo de tarefas a aplicar ao ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que fica como criador das tarefas aplicadas. Precisa existir, estar ativo e ser da empresa da chave.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "taskTemplateId" : {
            "description" : "Identificador do modelo de tarefas. Precisa ser da empresa da chave — um modelo de outra empresa responde `404 not_found` neste campo.",
            "example" : 7,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "required" : [
          "agentId",
          "taskTemplateId"
        ],
        "type" : "object"
      },
      "PublicTicketTaskInput" : {
        "description" : "Tarefa a criar no ticket.",
        "properties" : {
          "agentId" : {
            "description" : "Agente que cria a tarefa e responde por ela. Precisa existir, estar ativo e ser da empresa da chave. Em um título de grupo ele fica só como criador.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "completed" : {
            "description" : "Cria a tarefa já concluída. Padrão `false`. **Não se aplica** a um título de grupo.",
            "type" : "boolean"
          },
          "deadline" : {
            "description" : "Prazo da tarefa, **sem fuso**, no formato `yyyy-MM-ddTHH:mm` (os segundos são opcionais). **Não se aplica** a um título de grupo.",
            "example" : "2026-12-01T09:30",
            "pattern" : "^\\d{4}-\\d{2}-\\d{2}T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$",
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição livre da tarefa. **Não se aplica** a um título de grupo: enviá-la junto de `groupTitle: true` é `422 validation_failed` com `not_applicable`. Até 65535 bytes em UTF-8.",
            "maxLength" : 65535,
            "minLength" : 0,
            "type" : "string"
          },
          "groupTitle" : {
            "description" : "Cria um **título de grupo** em vez de uma tarefa: um separador que agrupa as tarefas abaixo dele. Padrão `false`.",
            "type" : "boolean"
          },
          "title" : {
            "description" : "Título da tarefa. Até 255 caracteres.",
            "example" : "Validar o backup do servidor",
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          }
        },
        "required" : [
          "agentId",
          "title"
        ],
        "type" : "object"
      },
      "PublicTicketTaskMoveInput" : {
        "description" : "Destino da tarefa na ordem da aba.",
        "properties" : {
          "afterTaskId" : {
            "description" : "Tarefa que passa a ficar logo **acima** desta. Ausente ou nula, a tarefa vai para o topo da lista (e aí `beforeTaskId` é obrigatório).",
            "example" : 511,
            "format" : "int64",
            "type" : "integer"
          },
          "beforeTaskId" : {
            "description" : "Tarefa que passa a ficar logo **abaixo** desta. Ausente ou nula, a tarefa vai para o fim da lista (e aí `afterTaskId` é obrigatório).",
            "example" : 513,
            "format" : "int64",
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PublicTicketTaskPatchInput" : {
        "description" : "Campos alteráveis de uma tarefa (JSON Merge Patch).",
        "properties" : {
          "agentId" : {
            "description" : "Agente responsável. `null` explícito tira o responsável da tarefa. **Não se aplica** a um título de grupo.",
            "example" : 42,
            "format" : "int64",
            "type" : "integer"
          },
          "completed" : {
            "description" : "Conclui a tarefa, ou desfaz a conclusão. Concluir grava o evento `TASK_COMPLETED` no histórico do ticket; desfazer não grava nada, como na tela. **Não se aplica** a um título de grupo.",
            "type" : "boolean"
          },
          "deadline" : {
            "description" : "Prazo da tarefa, **sem fuso**, no formato `yyyy-MM-ddTHH:mm`. **Não se aplica** a um título de grupo.",
            "example" : "2026-12-01T09:30",
            "pattern" : "^\\d{4}-\\d{2}-\\d{2}T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$",
            "type" : "string"
          },
          "description" : {
            "description" : "Descrição livre da tarefa. **Não se aplica** a um título de grupo. Até 65535 bytes em UTF-8.",
            "maxLength" : 65535,
            "minLength" : 0,
            "type" : "string"
          },
          "groupTitle" : {
            "description" : "Transforma a tarefa em título de grupo, ou o contrário.",
            "type" : "boolean"
          },
          "title" : {
            "description" : "Título da tarefa. Até 255 caracteres.",
            "example" : "Validar o backup do servidor",
            "maxLength" : 255,
            "minLength" : 0,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PublicTicketWorkflowInput" : {
        "description" : "Fluxo que o ticket passa a seguir. `workflowId: null` desvincula o ticket do fluxo atual; a chave `workflowId` é obrigatória, um corpo vazio não desvincula.",
        "properties" : {
          "workflowId" : {
            "description" : "ID do fluxo alvo, ou `null` para desvincular. O fluxo precisa estar ativo e pertencer ao mesmo grupo de atendimento do ticket. Aceita o número ou o mesmo número entre aspas, como os demais ids do corpo.",
            "example" : 7,
            "format" : "int64",
            "nullable" : true,
            "type" : "integer"
          }
        },
        "type" : "object"
      }
    },
    "securitySchemes" : {
      "bearer" : {
        "bearerFormat" : "mspd_live_…",
        "description" : "Chave de API da empresa (Configurações → Chaves de API), informada no cabeçalho `Authorization: Bearer <chave>`. O formato é `mspd_live_…`.",
        "scheme" : "bearer",
        "type" : "http"
      }
    }
  },
  "externalDocs" : {
    "description" : "Guias e referência da API pública",
    "url" : "https://developers.mspdesk.com.br/"
  },
  "info" : {
    "description" : "API REST pública do MSP Desk, para integração de sistemas externos. Toda requisição exige uma chave de API no cabeçalho `Authorization: Bearer <chave>`, no formato `mspd_live_…`, com o escopo exigido por cada operação (veja a extensão `x-required-scope`). Um escopo `grupo:write` inclui o `grupo:read` do mesmo grupo: a chave criada ou editada só com o `:write` fica gravada e exibida também com o `:read`. A API pública é habilitada por empresa. Enquanto ela não estiver habilitada, toda requisição é recusada com `403 public_api_disabled`, mesmo com uma chave válida — salvo quando a MSP Works concede à empresa alguns escopos de leitura (escopos liberados por concessão): aí só esses escopos funcionam, e as demais operações respondem `403 scope_requires_public_api` (marcar o escopo na chave não resolve; é preciso habilitar a API pública). As chaves continuam guardadas e voltam a funcionar por inteiro assim que a empresa for habilitada.\n\n## Limites de uso\n\n| Camada | Taxa | Burst |\n|---|---|---|\n| Chave inválida por IP | 20/min | 20 |\n| Empresa | 200/min | 40 |\n| Chave | 100/min (50% da empresa) | 20 |\n| Executar relatório | 10/min | 2 |\n| Impressão/PDF | 10/min | 2 |\n| Upload de anexo | 30/min | 5 |\n| Concorrência por empresa | 5 em andamento | — |\n\nO limite de chave inválida por IP só é consumido por requisições recusadas na autenticação: `401` (chave ausente, inválida, revogada, expirada ou inativa) e os `403` `account_inactive` e `public_api_disabled`. Uma chave aceita nunca é bloqueada pelas falhas de outros clientes no mesmo IP. Esgotado, a tentativa recusada seguinte recebe `429` com `layer=ip` no lugar do `401` ou do `403`.\n\nToda resposta de uma requisição com chave válida traz os cabeçalhos `RateLimit-Limit`, `RateLimit-Remaining` e `RateLimit-Reset`, referentes ao balde mais restritivo consumido (ou consultado) nessa requisição. O `401` e os `403` `account_inactive` (empresa inativa) e `public_api_disabled` (API pública não habilitada para a empresa) não os trazem, porque ainda não há balde de empresa ou chave a informar; o `429` com `layer=ip` traz os do balde de IP. Ao atingir o limite, a resposta é `429` com `Retry-After` (segundos até a próxima ficha) e o corpo indica a camada responsável no campo `layer` (`ip`, `company`, `key`, `operation` ou `concurrency`; quando `layer=operation`, o campo `operation` informa qual operação pesada — `report`, `pdf` ou `upload`).",
    "title" : "API pública do MSP Desk",
    "version" : "v1"
  },
  "openapi" : "3.0.1",
  "paths" : {
    "/v1/reports/{id}" : {
      "get" : {
        "description" : "Escopo exigido: `reports:read`. As colunas trazem a chave (`key`) de cada valor nas linhas de `execute`, o nome de exibição e o tipo. Não consome o limite `report`.",
        "operationId" : "getReport",
        "parameters" : [
          {
            "description" : "UUID do relatório",
            "example" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "uuid",
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "columns" : [
                    {
                      "key" : "ticketCode",
                      "label" : "Código do Ticket",
                      "type" : "INTEGER"
                    },
                    {
                      "key" : "ticketStatus",
                      "label" : "Status",
                      "type" : "ENUM"
                    },
                    {
                      "key" : "customFields.12",
                      "label" : "Contrato",
                      "type" : "OPTION"
                    }
                  ],
                  "id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                  "name" : "Tickets por SLA"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicReport"
                }
              }
            },
            "description" : "O relatório",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_query`: `id` que não é UUID ou parâmetro de consulta",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`account_inactive`: a empresa está inativa; `public_api_disabled`: a API pública está desabilitada para a empresa e nenhum escopo foi liberado a ela por concessão; `scope_requires_public_api`: a API pública está desabilitada e `reports:read` não está entre os escopos liberados por concessão; `insufficient_scope`: a chave não tem `reports:read`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: relatório inexistente, inativo ou de outra empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Consulta um relatório personalizado e as colunas do resultado",
        "tags" : [
          "Relatórios"
        ],
        "x-required-scope" : "reports:read"
      }
    },
    "/v1/reports/{id}/count" : {
      "get" : {
        "description" : "Escopo exigido: `reports:read`. Total de linhas que `execute` percorre, com os filtros do relatório. Não consome o limite `report`.",
        "operationId" : "countReportRows",
        "parameters" : [
          {
            "description" : "UUID do relatório",
            "example" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "uuid",
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "count" : 150
                },
                "schema" : {
                  "properties" : {
                    "count" : {
                      "format" : "int64",
                      "type" : "integer"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Total de linhas",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_query`: `id` que não é UUID ou parâmetro de consulta",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`account_inactive`: a empresa está inativa; `public_api_disabled`: a API pública está desabilitada para a empresa e nenhum escopo foi liberado a ela por concessão; `scope_requires_public_api`: a API pública está desabilitada e `reports:read` não está entre os escopos liberados por concessão; `insufficient_scope`: a chave não tem `reports:read`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: relatório inexistente, inativo ou de outra empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Conta as linhas de um relatório personalizado",
        "tags" : [
          "Relatórios"
        ],
        "x-required-scope" : "reports:read"
      }
    },
    "/v1/reports/{id}/execute" : {
      "get" : {
        "description" : "Escopo exigido: `reports:read`. Lista as linhas do relatório, uma por ticket, em ordem crescente de ticket — paginação por cursor opaco (`?cursor=`), como toda listagem: use `nextCursor` da resposta anterior. Cada linha traz `ticketId` e uma chave por coluna (`GET /v1/reports/{id}`); valores tipados: número, booleano, código de enum, data ISO-8601 como em `/v1/tickets` (campo fixo em UTC, campo personalizado com o offset da empresa), duração em minutos. Campos personalizados vêm em `customFields`, na mesma forma de `/v1/tickets` (lista `{id, name, type, value}`; lista suspensa como a opção `{id, label}`). Total em `GET /v1/reports/{id}/count`. As linhas do relatório **não** trazem notas nem apontamentos do ticket — para esses dados, use `/v1/tickets/{ticketId}/notes` e `/appointments`, que exigem o escopo `tickets:read`; numa empresa com a API pública desabilitada cuja concessão libera só `reports:read`, essas duas rotas respondem `403 scope_requires_public_api`. Substitui `/v1/custom-reports/integrations/{uuid}/execute` do serviço principal, **com outro formato**. Operação pesada: além dos limites de empresa e de chave, consome o limite `report` da empresa (10 por minuto, rajada de 2); ao atingi-lo a resposta é `429` com `layer=operation` e `operation=report`.",
        "operationId" : "executeReport",
        "parameters" : [
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Linhas por página. 1 a 100; padrão 25.",
            "example" : 100,
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "UUID do relatório",
            "example" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "uuid",
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "customFields" : [
                        {
                          "id" : 12,
                          "name" : "Contrato",
                          "type" : "DROPDOWN",
                          "value" : {
                            "id" : 7,
                            "label" : "Ouro"
                          }
                        }
                      ],
                      "ticketCode" : 1042,
                      "ticketCreatedAt" : "2026-09-25T17:30:00Z",
                      "ticketId" : 1042,
                      "ticketStatus" : "IN_PROGRESS"
                    }
                  ],
                  "nextCursor" : "eyJ2IjoxLCJzIjoiaWQiLCJmIjoicmVwb3J0OmExYjIiLCJrIjpbXSwiaWQiOjEwNDJ9"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicReportRow"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de linhas",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_query`: `id` que não é UUID, `limit` fora de 1..100 ou parâmetro desconhecido (inclusive `page`, `size` e `sort`); `invalid_cursor`: cursor adulterado ou de outro relatório",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`account_inactive`: a empresa está inativa; `public_api_disabled`: a API pública está desabilitada para a empresa e nenhum escopo foi liberado a ela por concessão; `scope_requires_public_api`: a API pública está desabilitada e `reports:read` não está entre os escopos liberados por concessão; `insufficient_scope`: a chave não tem `reports:read`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: relatório inexistente, inativo ou de outra empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Executa um relatório personalizado",
        "tags" : [
          "Relatórios"
        ],
        "x-required-scope" : "reports:read"
      }
    },
    "/v1/tags" : {
      "get" : {
        "description" : "Escopo exigido: `settings:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. Filtros: `id` (`eq`, `in`), `name` (`eq`, `contains`), `color` (`eq`, `in`), `createdAt`/`updatedAt` (`gte`, `lte`), como `filter[name][contains]=suporte`. Ordenação (`sort=`): `name`, `id` — padrão `id`; prefixe com `-` para descendente (ex.: `sort=-name`), sempre desempatado por `id` na mesma direção. `fields=` seleciona colunas de primeiro nível da resposta (`id` sempre volta). Sem `expand`.",
        "operationId" : "listTags",
        "parameters" : [
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Campo de ordenação: `name` ou `id` (padrão `id`). Prefixe com `-` para descendente (ex.: `sort=-name`); sempre desempatado por `id` na mesma direção.",
            "example" : "-name",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta).",
            "example" : "id,name,color",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` entre os valores informados, separados por vírgula.",
            "example" : "1,2,3",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `name` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[name][eq]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `name` contendo o texto informado.",
            "example" : "suporte",
            "in" : "query",
            "name" : "filter[name][contains]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `color` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[color][eq]",
            "schema" : {
              "enum" : [
                "GRAY",
                "RED",
                "ORANGE",
                "YELLOW",
                "GREEN",
                "BLUE",
                "INDIGO",
                "PURPLE",
                "PINK"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `color` entre os valores informados, separados por vírgula.",
            "example" : "RED,BLUE",
            "in" : "query",
            "name" : "filter[color][in]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual à data/hora informada (ISO 8601).",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual à data/hora informada (ISO 8601).",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual à data/hora informada (ISO 8601).",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual à data/hora informada (ISO 8601).",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "color" : "RED",
                      "createdAt" : "2026-01-10T15:00:00Z",
                      "id" : 1,
                      "name" : "urgente",
                      "updatedAt" : "2026-01-10T15:00:00Z"
                    }
                  ],
                  "nextCursor" : null
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTag"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de tags",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_query`: `limit`/`sort`/`filter`/`fields`/`cursor` inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_api_key`: chave ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`insufficient_scope`: a chave não tem `settings:read`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista as tags da empresa da chave",
        "tags" : [
          "Tags"
        ],
        "x-required-scope" : "settings:read"
      },
      "post" : {
        "description" : "Escopo exigido: `settings:write`. `name` e `color` são obrigatórios; `color` usa os nomes do enum (`GRAY`, `RED`, `ORANGE`, `YELLOW`, `GREEN`, `BLUE`, `INDIGO`, `PURPLE`, `PINK`). A tag criada pela API nunca tem um usuário associado.",
        "operationId" : "createTag",
        "parameters" : [
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "color" : "RED",
                "name" : "urgente"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTagInput"
              }
            }
          },
          "description" : "Representação de uma nova tag",
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "color" : "RED",
                  "createdAt" : "2026-01-10T15:00:00Z",
                  "id" : 1,
                  "name" : "urgente",
                  "updatedAt" : "2026-01-10T15:00:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTag"
                }
              }
            },
            "description" : "Tag criada; `Location` aponta para o novo recurso",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_api_key`"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`insufficient_scope`: a chave não tem `settings:write`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`already_exists`: já existe uma tag com este nome (ignorando maiúsculas/minúsculas)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: `name`/`color` ausentes ou inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Cria uma tag",
        "tags" : [
          "Tags"
        ],
        "x-required-scope" : "settings:write"
      }
    },
    "/v1/tags/{id}" : {
      "delete" : {
        "description" : "Escopo exigido: `settings:write`. Bloqueia com `409 resource_in_use` quando a tag está referenciada em algum ticket (inclusive excluído), artigo da base de conhecimento, cliente ou contato.",
        "operationId" : "deleteTag",
        "parameters" : [
          {
            "description" : "ID da tag",
            "example" : 1,
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "Removida",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_api_key`"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`insufficient_scope`: a chave não tem `settings:write`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: tag inexistente ou de outra empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`resource_in_use`: a tag está em uso",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Remove uma tag",
        "tags" : [
          "Tags"
        ],
        "x-required-scope" : "settings:write"
      },
      "get" : {
        "description" : "Escopo exigido: `settings:read`. Aceita `fields=` para selecionar os campos de primeiro nível da resposta (`id` sempre volta).",
        "operationId" : "getTag",
        "parameters" : [
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta).",
            "example" : "id,name",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "ID da tag",
            "example" : 1,
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "color" : "RED",
                  "createdAt" : "2026-01-10T15:00:00Z",
                  "id" : 1,
                  "name" : "urgente",
                  "updatedAt" : "2026-01-10T15:00:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTag"
                }
              }
            },
            "description" : "A tag",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_api_key`"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`insufficient_scope`: a chave não tem `settings:read`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: tag inexistente ou de outra empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Busca uma tag pelo id",
        "tags" : [
          "Tags"
        ],
        "x-required-scope" : "settings:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `settings:write`. Aceita `application/merge-patch+json` ou `application/json` — RFC 7396 sobre a representação atual (`name`/`color`); campo desconhecido no corpo do patch é `422 validation_failed` com `unknown_field`.",
        "operationId" : "updateTag",
        "parameters" : [
          {
            "description" : "ID da tag",
            "example" : 1,
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "color" : "BLUE"
              },
              "schema" : {
                "properties" : {
                  "color" : {
                    "enum" : [
                      "GRAY",
                      "RED",
                      "ORANGE",
                      "YELLOW",
                      "GREEN",
                      "BLUE",
                      "INDIGO",
                      "PURPLE",
                      "PINK"
                    ],
                    "type" : "string"
                  },
                  "name" : {
                    "description" : "Novo nome da tag.",
                    "maxLength" : 255,
                    "type" : "string"
                  }
                },
                "type" : "object"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "color" : "BLUE"
              },
              "schema" : {
                "properties" : {
                  "color" : {
                    "enum" : [
                      "GRAY",
                      "RED",
                      "ORANGE",
                      "YELLOW",
                      "GREEN",
                      "BLUE",
                      "INDIGO",
                      "PURPLE",
                      "PINK"
                    ],
                    "type" : "string"
                  },
                  "name" : {
                    "description" : "Novo nome da tag.",
                    "maxLength" : 255,
                    "type" : "string"
                  }
                },
                "type" : "object"
              }
            }
          },
          "description" : "Merge patch — só os campos a alterar (ambos opcionais, envie o que quiser mudar). Campos somente-leitura da representação (`id`, `createdAt`, `updatedAt`) não são aceitos aqui: são tratados como campo desconhecido, `422 validation_failed` com `unknown_field`.",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "color" : "RED",
                  "createdAt" : "2026-01-10T15:00:00Z",
                  "id" : 1,
                  "name" : "urgente",
                  "updatedAt" : "2026-01-10T15:00:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTag"
                }
              }
            },
            "description" : "Tag atualizada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`invalid_api_key`"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`insufficient_scope`: a chave não tem `settings:write`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: tag inexistente ou de outra empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`already_exists`: outra tag já usa o nome resultante",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: resultado do patch inválido",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Edita uma tag (merge patch)",
        "tags" : [
          "Tags"
        ],
        "x-required-scope" : "settings:write"
      }
    },
    "/v1/tickets" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. Sem `filter[deleted][eq]`, a listagem só traz tickets não excluídos (`deleted=false`); com o filtro, vale o valor pedido.\n\n`filter[customerId][..]` casa todos os tickets do cliente informado, com ou sem unidade de negócio — diferente da tela do produto, que ali entende \"cliente\" como \"deste cliente e sem unidade\". Quem quer só os sem unidade soma `filter[businessUnitId][isNull]=true`. O mesmo vale para `serviceGroupId`: aqui o filtro olha só a coluna, sem a regra de \"do usuário ou sem grupo\" que a tela aplica.\n\n`ne` e `nin` incluem os registros sem valor — `filter[agentId][nin]=5` também traz os tickets sem agente. Quem quer só os preenchidos soma `filter[<campo>][isNull]=false`.\n\nCampo personalizado: `filter[customFields.<id>][<operador>]`, com o operador de acordo com o tipo do campo:\n\n| Tipo do campo | Operadores | Exemplo |\n|---|---|---|\n| Texto / Área de texto | `contains`, `eq`, `isNull` | `filter[customFields.12][contains]=urgente` |\n| Número inteiro | `eq`, `gt`, `gte`, `lt`, `lte`, `isNull` | `filter[customFields.12][gte]=10` |\n| Número decimal | `eq`, `gt`, `gte`, `lt`, `lte`, `isNull` | `filter[customFields.12][lte]=9.5` |\n| Data/hora | `gte`, `lte`, `isNull` | `filter[customFields.12][gte]=2026-01-01T00:00:00-03:00` |\n| Lista suspensa (id da opção) | `eq`, `in` | `filter[customFields.12][in]=3,4` |\n| Caixa de seleção | `eq` | `filter[customFields.12][eq]=true` |\n\nO campo personalizado de data/hora é gravado na hora local da empresa: o filtro converte o instante ISO-8601 informado (sempre com fuso) para o fuso da empresa antes de comparar, e a representação devolve o valor com o offset da empresa naquele instante.\n\nPara sincronizar \"o que mudou desde a última consulta\", use `sort=lastActivityAt` com `filter[lastActivityAt][gte]=<último valor visto menos 5 minutos>`, e deduplique pelo par `id` + `lastActivityAt` — um ticket relido com o mesmo par já foi processado. A margem de 5 minutos é necessária porque o carimbo é gravado de forma assíncrona, pouco depois da confirmação da escrita: sem ela, um ticket cujo carimbo demore mais para ser gravado pode nunca aparecer numa consulta seguinte. A precisão é de segundo, então mais de um ticket pode compartilhar o mesmo instante.",
        "operationId" : "listTickets",
        "parameters" : [
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `code` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[code][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `code` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[code][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `subject` contendo o texto informado (sem diferenciar maiúsculas de minúsculas, conforme a colação do banco).",
            "in" : "query",
            "name" : "filter[subject][contains]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `priority` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[priority][eq]",
            "schema" : {
              "enum" : [
                "PLANNED",
                "LOW",
                "MEDIUM",
                "HIGH",
                "CRITICAL"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `priority` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[priority][in]",
            "schema" : {
              "example" : "PLANNED,LOW,MEDIUM,HIGH,CRITICAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `priority` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[priority][nin]",
            "schema" : {
              "example" : "PLANNED,LOW,MEDIUM,HIGH,CRITICAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `status` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[status][eq]",
            "schema" : {
              "enum" : [
                "TO_DO",
                "IN_PROGRESS",
                "PENDING",
                "COMPLETED",
                "CLOSED",
                "DELETED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `status` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[status][in]",
            "schema" : {
              "example" : "TO_DO,IN_PROGRESS,PENDING,COMPLETED,CLOSED,DELETED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `status` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[status][nin]",
            "schema" : {
              "example" : "TO_DO,IN_PROGRESS,PENDING,COMPLETED,CLOSED,DELETED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[origin][eq]",
            "schema" : {
              "enum" : [
                "EMAIL",
                "RMM",
                "MSP_TALKS",
                "INTERNAL",
                "PORTAL",
                "EXTERNAL_FORM",
                "API"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[origin][in]",
            "schema" : {
              "example" : "EMAIL,RMM,MSP_TALKS,INTERNAL,PORTAL,EXTERNAL_FORM,API",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[origin][nin]",
            "schema" : {
              "example" : "EMAIL,RMM,MSP_TALKS,INTERNAL,PORTAL,EXTERNAL_FORM,API",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceType][eq]",
            "schema" : {
              "enum" : [
                "INTERNAL",
                "EXTERNAL"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceType][in]",
            "schema" : {
              "example" : "INTERNAL,EXTERNAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[serviceType][nin]",
            "schema" : {
              "example" : "INTERNAL,EXTERNAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `customerId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[customerId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `customerId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[customerId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `customerId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[customerId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `customerId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[customerId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[businessUnitId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[businessUnitId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[businessUnitId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[businessUnitId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceCatalogId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceCatalogId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[serviceCatalogId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[serviceCatalogId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `categoryId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[categoryId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `categoryId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[categoryId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `categoryId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[categoryId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `categoryId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[categoryId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[subcategoryId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[subcategoryId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[subcategoryId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[subcategoryId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `agentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[agentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[agentId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[agentId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[agentId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceGroupId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceGroupId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[serviceGroupId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[serviceGroupId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `contactId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[contactId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `contactId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[contactId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `contactId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[contactId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `contactId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[contactId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[ticketTypeId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[ticketTypeId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[ticketTypeId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[ticketTypeId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `tagId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[tagId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `tagId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[tagId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `tagId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[tagId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `tagId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[tagId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `slaResponseStatus` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaResponseStatus][eq]",
            "schema" : {
              "enum" : [
                "WITHOUT",
                "WITHIN",
                "APPROACHING_BREACH",
                "BREACHED",
                "FULLFILLED",
                "PAUSED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaResponseStatus` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[slaResponseStatus][in]",
            "schema" : {
              "example" : "WITHOUT,WITHIN,APPROACHING_BREACH,BREACHED,FULLFILLED,PAUSED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaSolutionStatus` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaSolutionStatus][eq]",
            "schema" : {
              "enum" : [
                "WITHOUT",
                "WITHIN",
                "APPROACHING_BREACH",
                "BREACHED",
                "FULLFILLED",
                "PAUSED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaSolutionStatus` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[slaSolutionStatus][in]",
            "schema" : {
              "example" : "WITHOUT,WITHIN,APPROACHING_BREACH,BREACHED,FULLFILLED,PAUSED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaStatusAny` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaStatusAny][eq]",
            "schema" : {
              "enum" : [
                "WITHOUT",
                "WITHIN",
                "APPROACHING_BREACH",
                "BREACHED",
                "FULLFILLED",
                "PAUSED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaStatusAny` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[slaStatusAny][in]",
            "schema" : {
              "example" : "WITHOUT,WITHIN,APPROACHING_BREACH,BREACHED,FULLFILLED,PAUSED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdById` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdById][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `followerId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[followerId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `answered` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[answered][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `deleted` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[deleted][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `solvedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[solvedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `solvedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[solvedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `lastActivityAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[lastActivityAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `lastActivityAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[lastActivityAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `stageId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[stageId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `stageId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[stageId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `stageId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[stageId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `workflowId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[workflowId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `workflowId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[workflowId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `workflowId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[workflowId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `id`, `code`, `createdAt`, `updatedAt`, `lastActivityAt` (padrão `id`). Prefixe com `-` para descendente (ex.: `sort=-createdAt`); sempre desempatado por `id` na mesma direção. Tickets cujo `lastActivityAt` ainda não foi preenchido não aparecem em listagens ordenadas ou filtradas por `lastActivityAt`; a contagem (`GET /v1/tickets/count`) sem esse filtro os inclui normalmente, então as duas podem divergir por alguns instantes.",
            "example" : "-createdAt",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `code`, `subject`, `description`, `status`, `priority`, `origin`, `answered`, `reopened`, `deleted`, `createdAt`, `updatedAt`, `lastActivityAt`, `respondedAt`, `solvedAt`, `closedAt`, `deletedAt`, `slaResponseStatus`, `slaSolutionStatus`, `slaResponseDueAt`, `slaSolutionDueAt`, `customerId`, `businessUnitId`, `contactId`, `agentId`, `serviceGroupId`, `serviceCatalogId`, `categoryId`, `subcategoryId`, `ticketTypeId`, `assetId`, `workflowId`, `stageId`, `createdById`, `followUpOfId`, `mergedIntoId`, `tagIds`, `customFields`.",
            "example" : "id,code,subject",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: `customer` (escopo `customers:read`), `contact` (escopo `contacts:read`), `agent` (escopo `agents:read`), `serviceGroup` (escopo `settings:read`). Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "agentId" : 42,
                      "answered" : true,
                      "assetId" : 310,
                      "businessUnitId" : 3,
                      "categoryId" : 6,
                      "closedAt" : null,
                      "code" : 18342,
                      "contactId" : 88,
                      "createdAt" : "2026-01-10T12:00:00Z",
                      "createdById" : null,
                      "customFields" : [
                        {
                          "id" : 12,
                          "name" : "Patrimônio",
                          "type" : "TEXT",
                          "value" : "PAT-00731"
                        }
                      ],
                      "customerId" : 15,
                      "deleted" : false,
                      "deletedAt" : null,
                      "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                      "followUpOfId" : null,
                      "id" : 1042,
                      "lastActivityAt" : "2026-01-10T14:05:00Z",
                      "mergedIntoId" : null,
                      "origin" : "EMAIL",
                      "priority" : "HIGH",
                      "reopened" : false,
                      "respondedAt" : "2026-01-10T12:40:00Z",
                      "serviceCatalogId" : 9,
                      "serviceGroupId" : 4,
                      "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                      "slaResponseStatus" : "FULLFILLED",
                      "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                      "slaSolutionStatus" : "WITHIN",
                      "solvedAt" : null,
                      "stageId" : 12,
                      "status" : "IN_PROGRESS",
                      "subcategoryId" : 21,
                      "subject" : "Impressora sem conexão",
                      "tagIds" : [
                        1
                      ],
                      "ticketTypeId" : 2,
                      "updatedAt" : "2026-01-10T14:05:00Z",
                      "workflowId" : 5
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "allOf" : [
                          {
                            "$ref" : "#/components/schemas/PublicTicket"
                          },
                          {
                            "$ref" : "#/components/schemas/PublicTicketExpansions"
                          }
                        ],
                        "type" : "object"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de tickets",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista os tickets da empresa da chave",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Abre um ticket na empresa da chave.\n\n## Campos\n\n| Campo | Obrigatório | Observação |\n|---|---|---|\n| `subject` | sim | até 255 caracteres |\n| `description` | sim | aceita HTML |\n| `priority` | sim | `PLANNED`, `LOW`, `MEDIUM`, `HIGH` ou `CRITICAL` |\n| `origin` | não | canal de origem; padrão `API`; não altera a autoria registrada |\n| `customerId` | sim | cliente do ticket |\n| `contactId` | sim | precisa ser contato do cliente informado |\n| `businessUnitId` | não | precisa ser unidade de negócio do cliente informado |\n| `assetId` | não | precisa ser ativo do cliente informado |\n| `agentId` | não | exige `serviceGroupId`: agente só é atribuído a ticket com grupo; precisa estar ativo e ser membro do grupo |\n| `serviceGroupId` | não | grupo de atendimento |\n| `serviceCatalogId` | não | precisa estar vinculado ao grupo informado |\n| `categoryId` | não | precisa pertencer ao serviço do catálogo informado |\n| `subcategoryId` | não | precisa pertencer à categoria informada |\n| `ticketTypeId` | não | tipo do ticket |\n| `tagIds` | não | até 200 tags |\n| `customFields` | não | objeto por ID do campo personalizado |\n| `resolution` | não | abre e conclui o ticket na mesma requisição |\n\n## Abrir e concluir na mesma requisição\n\nCom `resolution`, o ticket é aberto e concluído de uma vez. A conclusão exige `serviceGroupId`, `serviceCatalogId`, `categoryId`, `subcategoryId`, `ticketTypeId` e `agentId` preenchidos no mesmo corpo; faltando algum, nada é criado e a resposta é `422 business_rule_violation`. O realizado é gravado como nota de conclusão (`type: NOTE`, o padrão) ou como apontamento já encerrado (`type: APPOINTMENT`).\n\n## Campos personalizados\n\n`customFields` é um objeto por ID do campo — `{\"12\": \"texto\", \"15\": 3, \"18\": \"2026-09-22T14:00:00-03:00\"}` —, e não o array da leitura. O JSON aceito em cada valor depende do tipo do campo:\n\n| Tipo do campo | JSON aceito | Exemplo |\n|---|---|---|\n| Texto / Área de texto | texto | `\"texto\"` |\n| Número inteiro | inteiro | `10` |\n| Número decimal | número | `9.5` |\n| Caixa de seleção | booleano | `true` |\n| Data e hora | texto ISO-8601 **com fuso** | `\"2026-09-22T14:00:00-03:00\"` |\n| Lista suspensa | inteiro: o ID da opção do campo | `3` |\n\nCampo personalizado de ticket global e obrigatório precisa vir preenchido. Chave que não é ID de um campo personalizado de ticket desta empresa é `422 validation_failed` com `unknown_field` em `customFields.<id>`; valor do tipo errado, opção de outro campo ou data sem fuso é `invalid_value` no mesmo campo. Os erros de campo personalizado vêm agregados numa resposta só, ordenados pelo ID do campo.\n\n## Referências e autoria\n\nToda referência do corpo é resolvida na empresa da chave. Inexistente ou de outra empresa é `404 not_found`, com o campo culpado em `errors[0].field` — nunca `403`, para não revelar o que existe em outra empresa. Referência inativa é `422 validation_failed` com `inactive`. Referência que existe mas não combina com as demais — o serviço do catálogo que não é do grupo, a categoria que não é do serviço, a subcategoria que não é da categoria, o contato, o ativo ou a unidade que não é do cliente, o agente que não é do grupo ou sem grupo informado — é `422 validation_failed` com `inconsistent_reference` no campo incoerente.\n\nA criação fica registrada no histórico do ticket como feita pela integração: a entrada do histórico sai com origem `API` e o nome da chave usada. O ticket criado pela API não tem usuário criador (`createdById` nulo).",
        "operationId" : "createTicket",
        "parameters" : [
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "contactId" : 25,
                "customFields" : {
                  "12" : "texto",
                  "15" : 3,
                  "18" : "2026-09-22T14:00:00-03:00"
                },
                "customerId" : 10,
                "description" : "<p>A impressora do setor parou.</p>",
                "origin" : "EMAIL",
                "priority" : "MEDIUM",
                "serviceGroupId" : 3,
                "subject" : "Impressora não imprime",
                "tagIds" : [
                  1,
                  2
                ]
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketCreateInput"
              }
            }
          },
          "description" : "Dados de abertura do ticket",
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Ticket criado; `Location` aponta para o novo recurso",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: uma referência do corpo não existe nesta empresa; `errors[0].field` diz qual",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: campo obrigatório ausente, campo desconhecido, referência inativa ou incoerente, ou valor inválido de campo personalizado. `business_rule_violation`: uma regra do ticket recusou a operação",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Abre um ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/count" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Aceita só `filter[campo][operador]`, com os mesmos filtros da listagem (inclusive `filter[customFields.<id>][..]`); qualquer outro parâmetro é `400 invalid_query`. Consome o limite de uso normal, não um limite à parte.\n\nTickets cujo `lastActivityAt` ainda não foi preenchido são contados normalmente quando a contagem não filtra por esse campo, mas ficam de fora de uma listagem ordenada ou filtrada por `lastActivityAt` — por isso as duas podem divergir por alguns instantes.",
        "operationId" : "countTickets",
        "parameters" : [
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `code` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[code][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `code` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[code][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `subject` contendo o texto informado (sem diferenciar maiúsculas de minúsculas, conforme a colação do banco).",
            "in" : "query",
            "name" : "filter[subject][contains]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `priority` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[priority][eq]",
            "schema" : {
              "enum" : [
                "PLANNED",
                "LOW",
                "MEDIUM",
                "HIGH",
                "CRITICAL"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `priority` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[priority][in]",
            "schema" : {
              "example" : "PLANNED,LOW,MEDIUM,HIGH,CRITICAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `priority` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[priority][nin]",
            "schema" : {
              "example" : "PLANNED,LOW,MEDIUM,HIGH,CRITICAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `status` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[status][eq]",
            "schema" : {
              "enum" : [
                "TO_DO",
                "IN_PROGRESS",
                "PENDING",
                "COMPLETED",
                "CLOSED",
                "DELETED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `status` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[status][in]",
            "schema" : {
              "example" : "TO_DO,IN_PROGRESS,PENDING,COMPLETED,CLOSED,DELETED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `status` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[status][nin]",
            "schema" : {
              "example" : "TO_DO,IN_PROGRESS,PENDING,COMPLETED,CLOSED,DELETED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[origin][eq]",
            "schema" : {
              "enum" : [
                "EMAIL",
                "RMM",
                "MSP_TALKS",
                "INTERNAL",
                "PORTAL",
                "EXTERNAL_FORM",
                "API"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[origin][in]",
            "schema" : {
              "example" : "EMAIL,RMM,MSP_TALKS,INTERNAL,PORTAL,EXTERNAL_FORM,API",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[origin][nin]",
            "schema" : {
              "example" : "EMAIL,RMM,MSP_TALKS,INTERNAL,PORTAL,EXTERNAL_FORM,API",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceType][eq]",
            "schema" : {
              "enum" : [
                "INTERNAL",
                "EXTERNAL"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceType][in]",
            "schema" : {
              "example" : "INTERNAL,EXTERNAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[serviceType][nin]",
            "schema" : {
              "example" : "INTERNAL,EXTERNAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `customerId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[customerId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `customerId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[customerId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `customerId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[customerId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `customerId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[customerId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[businessUnitId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[businessUnitId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[businessUnitId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `businessUnitId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[businessUnitId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceCatalogId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceCatalogId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[serviceCatalogId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceCatalogId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[serviceCatalogId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `categoryId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[categoryId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `categoryId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[categoryId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `categoryId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[categoryId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `categoryId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[categoryId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[subcategoryId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[subcategoryId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[subcategoryId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `subcategoryId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[subcategoryId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `agentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[agentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[agentId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[agentId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[agentId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceGroupId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceGroupId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[serviceGroupId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceGroupId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[serviceGroupId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `contactId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[contactId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `contactId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[contactId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `contactId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[contactId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `contactId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[contactId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[ticketTypeId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[ticketTypeId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[ticketTypeId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `ticketTypeId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[ticketTypeId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `tagId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[tagId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `tagId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[tagId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `tagId` diferente de todos os valores informados, separados por vírgula (até 100; inclui registros sem valor).",
            "in" : "query",
            "name" : "filter[tagId][nin]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `tagId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[tagId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `slaResponseStatus` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaResponseStatus][eq]",
            "schema" : {
              "enum" : [
                "WITHOUT",
                "WITHIN",
                "APPROACHING_BREACH",
                "BREACHED",
                "FULLFILLED",
                "PAUSED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaResponseStatus` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[slaResponseStatus][in]",
            "schema" : {
              "example" : "WITHOUT,WITHIN,APPROACHING_BREACH,BREACHED,FULLFILLED,PAUSED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaSolutionStatus` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaSolutionStatus][eq]",
            "schema" : {
              "enum" : [
                "WITHOUT",
                "WITHIN",
                "APPROACHING_BREACH",
                "BREACHED",
                "FULLFILLED",
                "PAUSED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaSolutionStatus` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[slaSolutionStatus][in]",
            "schema" : {
              "example" : "WITHOUT,WITHIN,APPROACHING_BREACH,BREACHED,FULLFILLED,PAUSED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaStatusAny` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaStatusAny][eq]",
            "schema" : {
              "enum" : [
                "WITHOUT",
                "WITHIN",
                "APPROACHING_BREACH",
                "BREACHED",
                "FULLFILLED",
                "PAUSED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `slaStatusAny` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[slaStatusAny][in]",
            "schema" : {
              "example" : "WITHOUT,WITHIN,APPROACHING_BREACH,BREACHED,FULLFILLED,PAUSED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdById` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdById][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `followerId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[followerId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `answered` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[answered][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `deleted` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[deleted][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `solvedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[solvedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `solvedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[solvedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `lastActivityAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[lastActivityAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `lastActivityAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[lastActivityAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `stageId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[stageId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `stageId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[stageId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `stageId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[stageId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `workflowId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[workflowId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `workflowId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[workflowId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `workflowId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[workflowId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "count" : 0
                },
                "schema" : {
                  "properties" : {
                    "count" : {
                      "format" : "int64",
                      "type" : "integer"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Quantidade de tickets",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Conta os tickets da empresa da chave",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{id}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Move o ticket para a lixeira (exclusão lógica): ele some da listagem, mas continua acessível pelo `GET /v1/tickets/{id}`, com `deleted: true`. A operação é idempotente — excluir de novo devolve `204` sem registrar uma segunda exclusão. Os vínculos do ticket são desfeitos e os itens faturáveis pendentes, cancelados. Não há restauração pela API.",
        "operationId" : "deleteTicket",
        "parameters" : [
          {
            "description" : "O que fazer com os tickets associados: `ONLY_SELECTED` exclui só este e desfaz os vínculos; `DISSOCIATE` faz o mesmo, deixando os relacionados avulsos; `DELETE_ALL` exclui também, em cascata, os tickets dependentes deste",
            "example" : "ONLY_SELECTED",
            "in" : "query",
            "name" : "associationStrategy",
            "required" : false,
            "schema" : {
              "default" : "ONLY_SELECTED",
              "enum" : [
                "ONLY_SELECTED",
                "DISSOCIATE",
                "DELETE_ALL"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Cancela os itens deste ticket que estão em faturas em aberto e recalcula essas faturas. Fatura concluída nunca é tocada",
            "example" : false,
            "in" : "query",
            "name" : "cancelOpenInvoices",
            "required" : false,
            "schema" : {
              "default" : false,
              "type" : "boolean"
            }
          },
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "Ticket movido para a lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Exclui um ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve `404 not_found` para ticket inexistente ou de outra empresa. Ticket excluído não é escondido: volta com `deleted: true`, para que uma integração de sincronização também enxergue exclusões.",
        "operationId" : "getTicket",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `code`, `subject`, `description`, `status`, `priority`, `origin`, `answered`, `reopened`, `deleted`, `createdAt`, `updatedAt`, `lastActivityAt`, `respondedAt`, `solvedAt`, `closedAt`, `deletedAt`, `slaResponseStatus`, `slaSolutionStatus`, `slaResponseDueAt`, `slaSolutionDueAt`, `customerId`, `businessUnitId`, `contactId`, `agentId`, `serviceGroupId`, `serviceCatalogId`, `categoryId`, `subcategoryId`, `ticketTypeId`, `assetId`, `workflowId`, `stageId`, `createdById`, `followUpOfId`, `mergedIntoId`, `tagIds`, `customFields`.",
            "example" : "id,code,subject",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: `customer` (escopo `customers:read`), `contact` (escopo `contacts:read`), `agent` (escopo `agents:read`), `serviceGroup` (escopo `settings:read`). Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agent" : {
                    "email" : "ana.souza@exemplo.com.br",
                    "id" : 42,
                    "name" : "Ana Souza"
                  },
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contact" : {
                    "email" : "beatriz.lima@acme.com.br",
                    "id" : 88,
                    "name" : "Beatriz Lima"
                  },
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customer" : {
                    "fantasyName" : "Acme",
                    "id" : 15,
                    "name" : "Acme Indústria e Comércio Ltda."
                  },
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "allOf" : [
                    {
                      "$ref" : "#/components/schemas/PublicTicket"
                    },
                    {
                      "$ref" : "#/components/schemas/PublicTicketExpansions"
                    }
                  ],
                  "type" : "object"
                }
              }
            },
            "description" : "O ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Busca um ticket pelo id",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `tickets:write`. JSON Merge Patch (RFC 7396) aplicado sobre o estado atual do ticket: só o que vier no corpo muda, e `null` limpa o campo. Aceita `application/merge-patch+json` e `application/json`. Campo desconhecido — inclusive os só de leitura do ticket, como `id` e `status` — é recusado. `tagIds` SUBSTITUI o conjunto de tags (`[]` e `null` removem todas; para manter as tags, não envie o campo), e `customFields` faz merge POR CHAVE: campo não citado fica intacto. Trocar `customerId` passa pelas regras da troca de cliente (escopo, mesclagem, item faturável pendente e coerência de contato, ativo e unidade), e a recusa traz o motivo em `violation`; trocar só o contato, o ativo ou a unidade não passa por elas. Mudar `priority` exige `priorityChangeReason`. Ticket concluído, fechado ou na lixeira não aceita alteração. Agente só é atribuído a ticket com grupo de atendimento: `agentId` num ticket sem grupo, ou `serviceGroupId: null` mantendo o agente, é `422 validation_failed` com `inconsistent_reference` em `agentId`. Um patch que não muda nada devolve o ticket como está, sem registrar alteração.",
        "operationId" : "updateTicket",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 7,
                "assetId" : null,
                "customFields" : {
                  "12" : "valor novo",
                  "15" : null
                },
                "priority" : "HIGH",
                "priorityChangeReason" : "Cliente parado",
                "tagIds" : [
                  1,
                  2
                ]
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketPatchInput"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "agentId" : 7,
                "assetId" : null,
                "customFields" : {
                  "12" : "valor novo",
                  "15" : null
                },
                "priority" : "HIGH",
                "priorityChangeReason" : "Cliente parado",
                "tagIds" : [
                  1,
                  2
                ]
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketPatchInput"
              }
            }
          },
          "description" : "Campos a alterar no ticket",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Ticket alterado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, ou uma referência do corpo não existe — nesse caso `errors[0].field` diz qual",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`concurrent_modification`: o ticket foi alterado por outra requisição no meio desta. Releia o ticket e reaplique as alterações",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: campo esvaziado que é obrigatório, campo desconhecido, referência inativa (`inactive`) ou incoerente (`inconsistent_reference`), ou valor inválido de campo personalizado. `ticket_not_editable`: o ticket está concluído — reabra antes de alterar — ou fechado, e ticket fechado não é editável. `ticket_deleted`: o ticket está na lixeira. `business_rule_violation`: uma regra do ticket recusou a operação",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Altera um ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/complete" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Marca o ticket como concluído, dispara as notificações de conclusão e a pesquisa de satisfação. O corpo pode ser omitido ou `{}`; qualquer campo é recusado. O ticket precisa ter grupo, catálogo, agente, categoria, subcategoria e tipo preenchidos, nenhuma tarefa em aberto, nenhum apontamento incompleto e nenhum ticket dependente ainda aberto. Um ticket EM ATENDIMENTO não conclui direto: encerre o atendimento antes. Se a baixa dos alertas do Datto falhar, a conclusão continua valendo e a resposta é `200`.",
        "operationId" : "completeTicket",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : { },
              "schema" : {
                "$ref" : "#/components/schemas/PublicEmptyInput"
              }
            }
          },
          "description" : "Sem dados: omita ou envie `{}`"
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Ticket concluído; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: campo desconhecido no corpo (`unknown_field`). `business_rule_violation`: campos obrigatórios ausentes, tarefa em aberto, apontamento incompleto, dependente em aberto, ou transição de status não permitida",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Conclui o ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/end-appointment" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Fecha o atendimento em andamento do agente SEM os dados do apontamento — é o \"encerrar sem preencher\" da tela, para quando quem aciona não sabe o que foi feito. O apontamento fica incompleto e **bloqueia a conclusão do ticket** até alguém preenchê-lo, e o agente recebe um aviso interno nomeando a integração. O agente pode estar inativo: a sessão aberta continua encerrável.",
        "operationId" : "endTicketAppointment",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketEndAppointmentInput"
              }
            }
          },
          "description" : "Agente cuja sessão será encerrada",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Atendimento encerrado; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, o agente não existe nela, ou aquele agente não tem atendimento em andamento neste ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Encerra o atendimento sem preencher",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/merge" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Consolida os tickets de `secondaryTicketIds` no ticket da rota. Cada secundário é fechado, aponta para o principal e tem notas, apontamentos, itens faturáveis, tarefas e linha do tempo transferidos para ele — a mescla é irreversível. Todos precisam ser do mesmo cliente do principal, e nenhum deles (nem o principal) pode estar na lixeira. No máximo 50 secundários por requisição. A lista vazia não mescla nada: a resposta é `422 validation_failed` com `required` em `secondaryTicketIds`. O `minItems: 0` que o schema publica é o padrão da restrição de tamanho; o mínimo que a API aceita é 1.",
        "operationId" : "mergeTickets",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "secondaryTicketIds" : [
                  101,
                  102
                ]
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketMergeInput"
              }
            }
          },
          "description" : "Tickets secundários a consolidar",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Mescla concluída; devolve o ticket principal",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket da rota não existe nesta empresa, ou um dos secundários não existe — nesse caso `errors[0].field` traz o índice, como `secondaryTicketIds[1]`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: lista vazia, acima de 50, ou com IDs repetidos. `ticket_deleted`: o principal ou um dos secundários está na lixeira. `business_rule_violation`: o secundário é o próprio principal, é de outro cliente, ou já foi mesclado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Mescla tickets",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/pause" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Fecha o atendimento em andamento do agente, gravando o apontamento com a descrição, o tipo de serviço e os horários informados, e deixa o ticket `PENDING`. Imagens embutidas em base64 na descrição são enviadas para os anexos do ticket e substituídas pela URL. Com `pauseSla` o SLA do ticket também é pausado, e aí `pauseReasonId` é obrigatório.",
        "operationId" : "pauseTicket",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "description" : "<p>Serviço reiniciado.</p>",
                "serviceType" : "INTERNAL",
                "timeSpent" : "01:30"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketPauseInput"
              }
            }
          },
          "description" : "Dados do apontamento a gravar",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Apontamento gravado; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, o agente não existe nela, ou aquele agente não tem atendimento em andamento neste ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: `pauseSla` sem `pauseReasonId` (`required`), ou formato de hora inválido. `business_rule_violation`: apontamento retroativo sobre um SLA de resposta já violado sem `backdateReason`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Encerra o atendimento com o apontamento",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/print" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve o relatório do ticket em PDF (`application/pdf`), o mesmo da tela. É leitura: exige `tickets:read` e imprime também o ticket na lixeira. Cada seção do relatório pode ser desligada pelos parâmetros de consulta, todos `true` por padrão. Esta operação tem limite de uso próprio, por empresa: ao atingi-lo a resposta é `429` com `layer=operation` e `operation=pdf`.",
        "operationId" : "printTicket",
        "parameters" : [
          {
            "description" : "Inclui os apontamentos",
            "example" : true,
            "in" : "query",
            "name" : "appointments",
            "required" : false,
            "schema" : {
              "default" : true,
              "type" : "boolean"
            }
          },
          {
            "description" : "Inclui as notas públicas",
            "example" : true,
            "in" : "query",
            "name" : "publicNotes",
            "required" : false,
            "schema" : {
              "default" : true,
              "type" : "boolean"
            }
          },
          {
            "description" : "Inclui os itens faturáveis",
            "example" : true,
            "in" : "query",
            "name" : "billableItems",
            "required" : false,
            "schema" : {
              "default" : true,
              "type" : "boolean"
            }
          },
          {
            "description" : "Inclui o bloco de SLA",
            "example" : true,
            "in" : "query",
            "name" : "sla",
            "required" : false,
            "schema" : {
              "default" : true,
              "type" : "boolean"
            }
          },
          {
            "description" : "Inclui as imagens da descrição, das notas e dos apontamentos",
            "example" : true,
            "in" : "query",
            "name" : "images",
            "required" : false,
            "schema" : {
              "default" : true,
              "type" : "boolean"
            }
          },
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/pdf" : {
                "schema" : {
                  "format" : "binary",
                  "type" : "string"
                }
              }
            },
            "description" : "PDF do relatório; `Content-Disposition` traz o nome do arquivo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Imprime o relatório de atendimento",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{id}/reopen" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Devolve um ticket concluído ao status `PENDING`, marcando-o como reaberto e limpando a data de solução. O corpo pode ser omitido ou `{}`; qualquer campo é recusado. Só reabre ticket concluído: ticket aberto e ticket fechado são recusados.",
        "operationId" : "reopenTicket",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : { },
              "schema" : {
                "$ref" : "#/components/schemas/PublicEmptyInput"
              }
            }
          },
          "description" : "Sem dados: omita ou envie `{}`"
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Ticket reaberto; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: campo desconhecido no corpo (`unknown_field`). `business_rule_violation`: o ticket ainda está aberto, ou está fechado (estado terminal)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Reabre o ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/sla-pause" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Congela a contagem do SLA do ticket com o motivo informado. O `agentId` é obrigatório porque a pausa é assinada por um agente, e a chave de API não é um: quem assina vem do corpo. O ticket não pode estar em atendimento, já ter o SLA pausado, estar concluído ou ter o SLA já violado.",
        "operationId" : "pauseTicketSla",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "description" : "Aguardando retorno do cliente.",
                "pauseReasonId" : 3
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketSlaPauseInput"
              }
            }
          },
          "description" : "Autor e motivo da pausa",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "SLA pausado; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, ou o `agentId`/`pauseReasonId` não existe nela — nesse caso `errors[0].field` traz o campo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: campo obrigatório ausente, ou motivo de pausa inativo (`inactive`). `business_rule_violation`: o SLA já está pausado, o ticket está em atendimento, já foi concluído, ou o SLA já foi violado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Pausa o SLA do ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/sla-resume" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Encerra a pausa ativa do SLA e volta a contagem. O corpo pode ser omitido ou `{}`; qualquer campo é recusado. Ao contrário da pausa, a retomada **não tem autor**: ela não pede `agentId`, e o registro da retomada fica sem usuário — a origem `API` e a chave usada ficam gravadas na linha do tempo do ticket. Sem pausa ativa a resposta é `404` — a pausa é o recurso que a ação retoma, e ela não existe.",
        "operationId" : "resumeTicketSla",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : { },
              "schema" : {
                "$ref" : "#/components/schemas/PublicEmptyInput"
              }
            }
          },
          "description" : "Sem dados: omita ou envie `{}`"
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "SLA retomado; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, ou ele não tem pausa de SLA ativa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: campo desconhecido no corpo (`unknown_field`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Retoma o SLA do ticket",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/stage" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Leva o ticket para outra etapa do fluxo em que ele está e dispara as automações de entrada da etapa alvo, exatamente como a tela. Em fluxo ramificado só valem as transições configuradas a partir da etapa atual; em fluxo linear vale qualquer etapa do fluxo. Etapa que não pertence ao fluxo do ticket — inclusive uma que não existe ou é de outra empresa — é `422`, e não `404`: a resposta não distingue os casos nem revela a existência da etapa.",
        "operationId" : "changeTicketStage",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "stageId" : 12
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketStageInput"
              }
            }
          },
          "description" : "Etapa alvo",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Etapa alterada; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: `stageId` ausente. `business_rule_violation`: o ticket não está em nenhum fluxo, a etapa não pertence ao fluxo dele, ou a transição não é permitida pelo fluxo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Move o ticket de etapa",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/start" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Coloca o ticket em atendimento pelo agente informado: abre um apontamento, atribui o ticket a ele e retoma o SLA, se estiver pausado. É idempotente — se o mesmo agente já está atendendo, nada muda e a resposta continua `200`.",
        "operationId" : "startTicket",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketStartInput"
              }
            }
          },
          "description" : "Agente que inicia o atendimento",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Atendimento iniciado; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, ou o `agentId` não existe, está inativo ou é de outra empresa — nesse caso `errors[0].field` traz `agentId`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `business_rule_violation`: a empresa não permite vários agentes no mesmo ticket e outro agente já está atendendo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Inicia o atendimento",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{id}/workflow" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Passa o ticket para o fluxo informado, entrando na etapa inicial dele, ou desvincula o ticket do fluxo atual com `workflowId: null`. A decisão fica marcada como manual: a resolução automática não re-vincula o fluxo enquanto o ticket seguir no mesmo grupo de atendimento. A chave `workflowId` é obrigatória — um corpo vazio é `422`, e não um desvínculo. Como nos demais ids do corpo, o valor pode vir como número ou como o mesmo número entre aspas.",
        "operationId" : "changeTicketWorkflow",
        "parameters" : [
          {
            "in" : "path",
            "name" : "id",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "workflowId" : 7
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketWorkflowInput"
              }
            }
          },
          "description" : "Fluxo alvo, ou `null` para desvincular",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "answered" : true,
                  "assetId" : 310,
                  "businessUnitId" : 3,
                  "categoryId" : 6,
                  "closedAt" : null,
                  "code" : 18342,
                  "contactId" : 88,
                  "createdAt" : "2026-01-10T12:00:00Z",
                  "createdById" : null,
                  "customFields" : [
                    {
                      "id" : 12,
                      "name" : "Patrimônio",
                      "type" : "TEXT",
                      "value" : "PAT-00731"
                    }
                  ],
                  "customerId" : 15,
                  "deleted" : false,
                  "deletedAt" : null,
                  "description" : "<p>A impressora do financeiro não aparece na rede desde a troca do roteador.</p>",
                  "followUpOfId" : null,
                  "id" : 1042,
                  "lastActivityAt" : "2026-01-10T14:05:00Z",
                  "mergedIntoId" : null,
                  "origin" : "EMAIL",
                  "priority" : "HIGH",
                  "reopened" : false,
                  "respondedAt" : "2026-01-10T12:40:00Z",
                  "serviceCatalogId" : 9,
                  "serviceGroupId" : 4,
                  "slaResponseDueAt" : "2026-01-10T13:00:00Z",
                  "slaResponseStatus" : "FULLFILLED",
                  "slaSolutionDueAt" : "2026-01-10T20:00:00Z",
                  "slaSolutionStatus" : "WITHIN",
                  "solvedAt" : null,
                  "stageId" : 12,
                  "status" : "IN_PROGRESS",
                  "subcategoryId" : 21,
                  "subject" : "Impressora sem conexão",
                  "tagIds" : [
                    1
                  ],
                  "ticketTypeId" : 2,
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "workflowId" : 5
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicket"
                }
              }
            },
            "description" : "Fluxo alterado; devolve o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket não existe nesta empresa, ou o `workflowId` não existe nela — nesse caso `errors[0].field` traz `workflowId`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted`: o ticket está na lixeira. `validation_failed`: `workflowId` ausente (`required`), valor que não é um id inteiro (`invalid_value`), campo desconhecido no corpo (`unknown_field`), ou fluxo inativo (`inactive`). `business_rule_violation`: o fluxo é de outro grupo de atendimento",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Troca ou desvincula o fluxo",
        "tags" : [
          "Tickets"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/activities" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é `-createdAt` (o evento mais novo primeiro), a mesma da aba.\n\n**Filtre por `category`, não por `type`.** A categoria é o recorte que a aba oferece e que esta documentação consegue manter estável; `type` tem dezenas de valores e ganha valores novos a cada funcionalidade do produto. O `type` continua no corpo da resposta, para quem quiser um recorte mais fino do lado dele.\n\n**Seis tipos não têm categoria, e `filter[category]` não os alcança:** `GROUPING`, `UNGROUPING`, `MERGE`, `AUTOMATION`, `FOLLOWER_ADDED` e `FOLLOWER_REMOVED`. Eles aparecem na listagem sem filtro, com `category: null`, mas nenhum valor de `filter[category][eq]` os traz — é o mesmo recorte que a aba do produto oferece hoje. Quem sincroniza **tudo** não deve filtrar por categoria; quem filtra por categoria precisa saber que agrupamento, mesclagem, automação e seguidores ficam de fora.\n\n`filter[category][eq]=ALL` é aceito e significa **sem recorte** — o mesmo que omitir o filtro. `ALL` é valor de entrada apenas: nenhuma entrada do histórico sai com `category: \\\"ALL\\\"`.\n\n`updatedAt` é igual a `createdAt` em toda entrada: o histórico não é editado. O campo existe para que a sincronização por data funcione igual em todos os sub-recursos.",
        "operationId" : "listTicketActivities",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `category` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[category][eq]",
            "schema" : {
              "enum" : [
                "ALL",
                "INTERACTIONS",
                "ATTACHMENTS",
                "SLA",
                "COMMUNICATIONS",
                "APPOINTMENTS",
                "INTEGRATIONS",
                "TASKS",
                "ITEMS",
                "WORKFLOW"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[origin][eq]",
            "schema" : {
              "enum" : [
                "USER",
                "CONTACT_CUSTOMER",
                "EMAIL_INBOUND",
                "NINJA_RMM",
                "DATTO_RMM",
                "SYSTEM",
                "API"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[origin][in]",
            "schema" : {
              "example" : "USER,CONTACT_CUSTOMER,EMAIL_INBOUND,NINJA_RMM,DATTO_RMM,SYSTEM,API",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[agentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[agentId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `createdAt`, `id` (padrão `-createdAt`). Prefixe com `-` para descendente (ex.: `sort=-createdAt`); sempre desempatado por `id` na mesma direção.",
            "example" : "-createdAt",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `type`, `category`, `description`, `fieldChanges`, `agentId`, `contactId`, `origin`, `apiKeyId`, `apiKeyName`, `createdAt`, `updatedAt`.",
            "example" : "id,type,category",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "agentId" : 42,
                      "apiKeyId" : 8,
                      "apiKeyName" : "Integração ERP",
                      "category" : "INTERACTIONS",
                      "contactId" : null,
                      "createdAt" : "2026-01-10T12:20:00Z",
                      "description" : "Prioridade: [Média] para [Alta]",
                      "fieldChanges" : [
                        {
                          "field" : "priority",
                          "newValue" : "HIGH",
                          "oldValue" : "MEDIUM"
                        }
                      ],
                      "id" : 9120,
                      "origin" : "API",
                      "type" : "UPDATE",
                      "updatedAt" : "2026-01-10T12:20:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketActivity"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página do histórico",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista o histórico de um ticket",
        "tags" : [
          "Atividades e alertas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{ticketId}/alerts" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. A lista é a do **Datto RMM** ou a do **NinjaRMM**, conforme a integração ativa na empresa — as duas nunca vêm misturadas, exatamente como na aba Alertas. O campo `source` diz qual é a origem de cada linha.\n\n**Campos nulos conforme a origem.** Só existem no Datto: `alertDiagnostic`, `alertPriority`, `alertCategory`, `alertType`, `alertUid` e `siteName`. Só existem no Ninja: `severity`, `statusCode`, `conditionLabel`, `jobCode` e `resolvedAt`. Os demais existem nas duas.\n\n**Só `id` e `createdAt` filtram**, porque são os únicos que existem nas duas origens. `resolved` não filtra: ele é coluna no Datto e derivado de `resolvedAt` no Ninja, e um filtro que funcionasse em uma empresa e não em outra seria pior que a ausência dele. `createdAt` é a criação no Datto e o disparo no Ninja.\n\nA ordenação padrão é `-id` (o alerta mais recente primeiro), a mesma da aba.",
        "operationId" : "listTicketAlerts",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `id`, `createdAt` (padrão `-id`). Prefixe com `-` para descendente (ex.: `sort=-createdAt`); sempre desempatado por `id` na mesma direção.",
            "example" : "-createdAt",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `source`, `deviceName`, `alertDescription`, `alertDiagnostic`, `alertPriority`, `alertCategory`, `alertType`, `alertUid`, `siteName`, `severity`, `statusCode`, `conditionLabel`, `jobCode`, `resolved`, `createdAt`, `updatedAt`, `resolvedAt`.",
            "example" : "id,source,deviceName",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "alertCategory" : "Disco",
                      "alertDescription" : "Espaço em disco abaixo de 10%",
                      "alertDiagnostic" : "Disco C: com 7% livre",
                      "alertPriority" : "HIGH",
                      "alertType" : "disk_usage",
                      "alertUid" : "5f1c9a2e-7d4b-4e8a-b1c3-2a9d6e0f4b71",
                      "conditionLabel" : null,
                      "createdAt" : "2026-01-10T11:58:00Z",
                      "deviceName" : "SRV-ARQUIVOS-01",
                      "id" : 3312,
                      "jobCode" : null,
                      "resolved" : false,
                      "resolvedAt" : null,
                      "severity" : null,
                      "siteName" : "Acme - Matriz",
                      "source" : "DATTO_RMM",
                      "statusCode" : null,
                      "updatedAt" : "2026-01-10T11:58:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketAlert"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de alertas",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista os alertas de RMM vinculados a um ticket",
        "tags" : [
          "Atividades e alertas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{ticketId}/appointments" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é a da aba: `-date`, desempatada pelo `id` na mesma direção.\n\n`sort=` aceita só `date` e `id`. `createdAt` e `updatedAt` são filtro e não ordenação: são colunas novas, nulas no que foi registrado antes desta API, e um valor nulo não serve de chave de paginação estável.\n\nO atendimento **em andamento** também aparece na lista, com `open: true`: ele ainda não tem fim, então `date` traz o instante em que começou. Use `filter[open][eq]=false` para ver só o que já foi encerrado.\n\n`filter[date][gte]` e `filter[date][lte]` recebem data e hora **sem fuso** (`2026-09-23T14:30`), porque é isso que a coluna guarda; `filter[createdAt][gte]` e `filter[updatedAt][gte]`, ao contrário, exigem o fuso (`2026-09-23T14:30:00Z`).",
        "operationId" : "listTicketAppointments",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[agentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[agentId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[serviceType][eq]",
            "schema" : {
              "enum" : [
                "INTERNAL",
                "EXTERNAL"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `serviceType` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[serviceType][in]",
            "schema" : {
              "example" : "INTERNAL,EXTERNAL",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `open` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[open][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `slaEligible` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[slaEligible][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `date` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[date][gte]",
            "schema" : {
              "example" : "2026-09-23T14:30",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `date` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[date][lte]",
            "schema" : {
              "example" : "2026-09-23T14:30",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `date`, `id` (padrão `-date`). Prefixe com `-` para descendente (ex.: `sort=-date`); sempre desempatado por `id` na mesma direção.",
            "example" : "-date",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `agentId`, `description`, `serviceType`, `slaEligible`, `open`, `date`, `startTime`, `endTime`, `timeSpent`, `backdateReason`, `attachmentIds`, `createdAt`, `updatedAt`.",
            "example" : "id,agentId,description",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "agentId" : 42,
                      "attachmentIds" : [ ],
                      "backdateReason" : null,
                      "createdAt" : "2026-01-10T13:02:00Z",
                      "date" : "2026-01-10T09:00:00",
                      "description" : "<p>Driver da impressora reinstalado e fila de impressão limpa.</p>",
                      "endTime" : "10:00",
                      "id" : 3021,
                      "open" : false,
                      "serviceType" : "INTERNAL",
                      "slaEligible" : true,
                      "startTime" : "09:00",
                      "timeSpent" : "01:00",
                      "updatedAt" : "2026-01-10T13:02:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketAppointment"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de apontamentos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista os apontamentos de um ticket",
        "tags" : [
          "Apontamentos do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Registra um atendimento já encerrado. `agentId`, `description`, `serviceType` e `date` são obrigatórios; `timeSpent` ausente vale `01:00` e `endTime` ausente vale a hora de `date`.\n\n`date` é data e hora **sem fuso**, no formato `yyyy-MM-ddTHH:mm` (os segundos são opcionais). Uma data de calendário que não existe (`2026-02-30T10:00`) responde `422 validation_failed`.\n\n`pauseSla: true` pausa também o SLA do ticket e exige `pauseReasonId` — sem ele a resposta é `422 validation_failed` com `required`, e nada é gravado. O SLA não é pausado se já houver uma pausa ativa, nem com o ticket em atendimento.\n\n`then: PAUSE` é o \"apontar e pausar\" da tela: além de gravar o apontamento, deixa o ticket pendente. Ele exige o ticket em `TO_DO`, e a verificação roda **antes** de gravar — num ticket em outro estado a resposta é `422 business_rule_violation` sem apontamento nenhum criado.\n\nNão há `attachmentIds` no corpo: vincular arquivo a um apontamento é do envio de anexo, não da criação. Um corpo que o envie é recusado com `422 validation_failed` e `unknown_field`.\n\nNenhum parâmetro de consulta é aceito.",
        "operationId" : "createTicketAppointment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "date" : "2026-01-10T09:00",
                "description" : "<p>Driver da impressora reinstalado e fila de impressão limpa.</p>",
                "endTime" : "10:00",
                "serviceType" : "INTERNAL",
                "slaEligible" : true,
                "startTime" : "09:00",
                "timeSpent" : "01:00"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketAppointmentInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "attachmentIds" : [ ],
                  "backdateReason" : null,
                  "createdAt" : "2026-01-10T13:02:00Z",
                  "date" : "2026-01-10T09:00:00",
                  "description" : "<p>Driver da impressora reinstalado e fila de impressão limpa.</p>",
                  "endTime" : "10:00",
                  "id" : 3021,
                  "open" : false,
                  "serviceType" : "INTERNAL",
                  "slaEligible" : true,
                  "startTime" : "09:00",
                  "timeSpent" : "01:00",
                  "updatedAt" : "2026-01-10T13:02:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketAppointment"
                }
              }
            },
            "description" : "O apontamento criado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o agente ou o motivo de pausa não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Registra um apontamento no ticket",
        "tags" : [
          "Apontamentos do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/appointments/summary" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve as horas internas, externas e totais, e quantos apontamentos já foram encerrados — os mesmos números que a tela mostra no topo da aba.\n\nAs horas são texto acumulado no formato `HH:mm`, e passar de 24 horas é normal (`37:15` é um total legítimo). O atendimento em andamento não entra em nenhum dos quatro números: ele ainda não tem tempo gasto.\n\nNenhum parâmetro de consulta é aceito: não há o que filtrar num total.",
        "operationId" : "getTicketAppointmentSummary",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "count" : 4,
                  "externalHours" : "01:00",
                  "internalHours" : "02:30",
                  "totalHours" : "03:30"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketAppointmentSummary"
                }
              }
            },
            "description" : "Os totais do ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Soma as horas apontadas no ticket",
        "tags" : [
          "Apontamentos do ticket"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{ticketId}/appointments/{appointmentId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Remove o apontamento e os arquivos vinculados a ele. Apontamento inexistente ou de outro ticket responde `404 not_found`; em ticket concluído ou fechado a resposta é `422 ticket_not_editable`.",
        "operationId" : "deleteTicketAppointment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do apontamento",
            "example" : 10,
            "in" : "path",
            "name" : "appointmentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "Apontamento excluído",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_not_editable` em ticket concluído ou fechado, ou `ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Exclui um apontamento do ticket",
        "tags" : [
          "Apontamentos do ticket"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve `404 not_found` quando o apontamento não existe ou pertence a outro ticket.",
        "operationId" : "getTicketAppointment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do apontamento",
            "example" : 10,
            "in" : "path",
            "name" : "appointmentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `agentId`, `description`, `serviceType`, `slaEligible`, `open`, `date`, `startTime`, `endTime`, `timeSpent`, `backdateReason`, `attachmentIds`, `createdAt`, `updatedAt`.",
            "example" : "id,agentId,description",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "attachmentIds" : [ ],
                  "backdateReason" : null,
                  "createdAt" : "2026-01-10T13:02:00Z",
                  "date" : "2026-01-10T09:00:00",
                  "description" : "<p>Driver da impressora reinstalado e fila de impressão limpa.</p>",
                  "endTime" : "10:00",
                  "id" : 3021,
                  "open" : false,
                  "serviceType" : "INTERNAL",
                  "slaEligible" : true,
                  "startTime" : "09:00",
                  "timeSpent" : "01:00",
                  "updatedAt" : "2026-01-10T13:02:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketAppointment"
                }
              }
            },
            "description" : "O apontamento",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Busca um apontamento do ticket pelo id",
        "tags" : [
          "Apontamentos do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `tickets:write`. JSON Merge Patch (RFC 7396): só os campos enviados mudam, e o resto do apontamento é reenviado ao produto como está.\n\nO autor não é alterável: `agentId` não existe neste corpo, porque a edição do produto nunca trocou o agente de um apontamento. `then` também não — ele é o efeito da criação sobre o ticket. Os dois respondem `422 validation_failed` com `unknown_field`.\n\n`pauseSla: true` pausa o SLA agora, e exige `pauseReasonId`. Não é um estado do apontamento: mandar `false` não retoma o SLA — para isso existe `POST /v1/tickets/{ticketId}/sla-resume`.\n\n`description`, `serviceType` e `date` continuam obrigatórios no RESULTADO do patch: mandá-los como `null` explícito é `422 validation_failed` com `required`, e o valor atual não é apagado.\n\nUm apontamento **em andamento** não é editável: a resposta é `422 appointment_in_progress`. Ele ainda não tem hora de fim, e o que a leitura publica em `date` é o instante em que ele começou — editar gravaria esse valor derivado como se fosse o encerramento. Encerre o atendimento em `POST /v1/tickets/{ticketId}/pause` e só então edite; excluir, ao contrário, continua permitido.\n\nEm ticket concluído ou fechado a resposta é `422 ticket_not_editable`.",
        "operationId" : "updateTicketAppointment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do apontamento",
            "example" : 10,
            "in" : "path",
            "name" : "appointmentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "description" : "<p>Servico reiniciado.</p>",
                "endTime" : "10:30",
                "timeSpent" : "01:30"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketAppointmentPatchInput"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "description" : "<p>Servico reiniciado.</p>",
                "endTime" : "10:30",
                "timeSpent" : "01:30"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketAppointmentPatchInput"
              }
            }
          },
          "description" : "Campos a alterar no apontamento",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "attachmentIds" : [ ],
                  "backdateReason" : null,
                  "createdAt" : "2026-01-10T13:02:00Z",
                  "date" : "2026-01-10T09:00:00",
                  "description" : "<p>Driver da impressora reinstalado e fila de impressão limpa.</p>",
                  "endTime" : "10:00",
                  "id" : 3021,
                  "open" : false,
                  "serviceType" : "INTERNAL",
                  "slaEligible" : true,
                  "startTime" : "09:00",
                  "timeSpent" : "01:00",
                  "updatedAt" : "2026-01-10T13:02:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketAppointment"
                }
              }
            },
            "description" : "O apontamento alterado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`appointment_in_progress`: o atendimento ainda está em andamento; `ticket_not_editable`: o ticket está encerrado; `validation_failed`: campo obrigatório ausente ou nulo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Altera um apontamento do ticket",
        "tags" : [
          "Apontamentos do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/attachments" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é `id` crescente.\n\nA lista é a da aba Anexos: ficam **de fora** os dois tipos de imagem que existem por causa do texto e não como arquivo — a que o remetente do e-mail declarou embutida (`inline`, tipicamente assinatura ou papel de carta) e a que o agente colou no editor da descrição (`linkedToDescription`). As duas seguem visíveis onde foram postas, no corpo. Por isso os dois campos saem sempre `false` aqui, e nenhum dos dois é filtro: um filtro que só pode casar um valor não filtra nada.\n\nAnexo de nota e de apontamento **continuam na lista**: são arquivo de verdade, só que anexados em outro momento do ticket. Use `filter[noteId][isNull]=true` e `filter[appointmentId][isNull]=true` para ficar só com os anexos soltos.\n\n`sort=` aceita só `id` e `fileName`. `createdAt` e `updatedAt` são filtro e não ordenação: são colunas novas, nulas no que foi registrado antes desta API, e um valor nulo não serve de chave de paginação estável.\n\n`fileName` é o nome de exibição do arquivo, o mesmo que a tela mostra — a ordenação e o `filter[fileName][contains]` valem sobre ele, não sobre a chave interna de armazenamento.",
        "operationId" : "listTicketAttachments",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `noteId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[noteId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `noteId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[noteId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `appointmentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[appointmentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `appointmentId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[appointmentId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `fileName` contendo o texto informado (sem diferenciar maiúsculas de minúsculas, conforme a colação do banco).",
            "in" : "query",
            "name" : "filter[fileName][contains]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `fileName`, `id` (padrão `id`). Prefixe com `-` para descendente (ex.: `sort=-id`); sempre desempatado por `id` na mesma direção.",
            "example" : "-id",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `fileName`, `contentType`, `size`, `noteId`, `appointmentId`, `linkedToDescription`, `inline`, `createdAt`, `updatedAt`.",
            "example" : "id,fileName,contentType",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "appointmentId" : null,
                      "contentType" : "application/pdf",
                      "createdAt" : "2026-01-10T14:04:00Z",
                      "fileName" : "log-impressora.pdf",
                      "id" : 912,
                      "inline" : false,
                      "linkedToDescription" : false,
                      "noteId" : 1204,
                      "size" : 184320,
                      "updatedAt" : "2026-01-10T14:04:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketAttachment"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de anexos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista os anexos de um ticket",
        "tags" : [
          "Anexos do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Corpo em `multipart/form-data` com a parte **`file`** obrigatória. O que seria campo de corpo vai como parâmetro de consulta, e são só três: `noteId`, `appointmentId` e `agentId`. Qualquer outro parâmetro responde `400 invalid_query`.\n\n`noteId` e `appointmentId` prendem o anexo a uma nota ou a um apontamento **do mesmo ticket**; os dois juntos são recusados (um anexo pertence a um escopo só), e um id de outro ticket responde `404 not_found` no campo que o enviou. Sem nenhum dos dois, o anexo fica solto na aba.\n\n`agentId` é opcional e só alimenta o histórico: é o agente que aparece como autor do evento de anexo. Sem ele o evento fica sem autor — uma chave de API não é uma pessoa, e nenhum agente é inventado no lugar.\n\n**Limite de tamanho: 6 MB por arquivo.** O arquivo é validado por extensão, tamanho e tipo de mídia, como na tela: extensão fora da lista aceita ou arquivo acima dos 6 MB respondem `422 business_rule_violation`; tipo de mídia não suportado responde `415 unsupported_media_type`. Um corpo maior que o envelope aceito (os 6 MB do arquivo mais a margem das outras partes do `multipart`) responde `413 payload_too_large` sem ser lido — é o único limite desta API que não são os 1 MB do corpo JSON.\n\n**`Idempotency-Key` neste envio não compara o conteúdo do arquivo.** Repetir o `POST` com a mesma chave devolve a resposta original — é o que evita o anexo duplicado numa repetição por timeout. Como consequência, enviar um arquivo **diferente** com a mesma chave e os mesmos parâmetros também devolve a resposta original, em vez de `422 idempotency_key_reused`: use uma chave nova para cada arquivo novo. O método, a rota e os parâmetros de consulta continuam comparados — repetir a chave mudando `noteId`, `appointmentId` ou `agentId` responde `422 idempotency_key_reused` e não grava nada.\n\nEsta rota consome um balde de limite de uso próprio, de upload, por empresa — o estouro é `429` com `operation: \"upload\"`.",
        "operationId" : "uploadTicketAttachment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Nota do mesmo ticket a que o anexo fica preso",
            "example" : 77,
            "in" : "query",
            "name" : "noteId",
            "required" : false,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Apontamento do mesmo ticket a que o anexo fica preso",
            "example" : 31,
            "in" : "query",
            "name" : "appointmentId",
            "required" : false,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Agente que aparece como autor do evento de anexo",
            "example" : 42,
            "in" : "query",
            "name" : "agentId",
            "required" : false,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com **parâmetros de consulta** diferentes é `422 idempotency_key_reused`. O **conteúdo do arquivo não entra na comparação**: repetir a chave com outro arquivo e os mesmos parâmetros devolve a resposta original, em vez de recusar — use uma chave nova para cada arquivo novo. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "multipart/form-data" : {
              "schema" : {
                "properties" : {
                  "file" : {
                    "description" : "O arquivo a anexar",
                    "format" : "binary",
                    "type" : "string"
                  }
                },
                "required" : [
                  "file"
                ],
                "type" : "object"
              }
            }
          }
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "appointmentId" : null,
                  "contentType" : "application/pdf",
                  "createdAt" : "2026-01-10T14:04:00Z",
                  "fileName" : "log-impressora.pdf",
                  "id" : 912,
                  "inline" : false,
                  "linkedToDescription" : false,
                  "noteId" : 1204,
                  "size" : 184320,
                  "updatedAt" : "2026-01-10T14:04:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketAttachment"
                }
              }
            },
            "description" : "O anexo criado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, a nota, o apontamento ou o agente não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`payload_too_large`: o corpo passa do tamanho aceito para um envio de arquivo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_not_editable` em ticket concluído ou fechado, `ticket_deleted` em ticket na lixeira, ou `business_rule_violation` quando o arquivo é recusado pelas regras de anexo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Envia um anexo para o ticket",
        "tags" : [
          "Anexos do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/attachments/{attachmentId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Exclusão definitiva: o registro sai da aba e o arquivo sai do armazenamento — não há lixeira de anexo. O histórico do ticket guarda o evento de remoção.\n\nEm ticket concluído ou fechado a resposta é `422 ticket_not_editable`, a mesma trava do envio. Excluir de novo responde `404 not_found`. Nenhum parâmetro de consulta é aceito.",
        "operationId" : "deleteTicketAttachment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do anexo",
            "example" : 912,
            "in" : "path",
            "name" : "attachmentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "Anexo excluído",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_not_editable` em ticket concluído ou fechado, ou `ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Exclui um anexo do ticket",
        "tags" : [
          "Anexos do ticket"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve `404 not_found` quando o anexo não existe ou pertence a outro ticket.\n\nAo contrário da listagem, esta rota **não** esconde a imagem embutida nem a imagem colada na descrição: um id devolvido em outro lugar da API continua legível aqui, e os campos `inline` e `linkedToDescription` dizem o que o arquivo é. Só a listagem esconde.\n\nO conteúdo do arquivo não vem nesta resposta: ele está em `GET /v1/tickets/{ticketId}/attachments/{attachmentId}/content`.",
        "operationId" : "getTicketAttachment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do anexo",
            "example" : 912,
            "in" : "path",
            "name" : "attachmentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `fileName`, `contentType`, `size`, `noteId`, `appointmentId`, `linkedToDescription`, `inline`, `createdAt`, `updatedAt`.",
            "example" : "id,fileName,contentType",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "appointmentId" : null,
                  "contentType" : "application/pdf",
                  "createdAt" : "2026-01-10T14:04:00Z",
                  "fileName" : "log-impressora.pdf",
                  "id" : 912,
                  "inline" : false,
                  "linkedToDescription" : false,
                  "noteId" : 1204,
                  "size" : 184320,
                  "updatedAt" : "2026-01-10T14:04:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketAttachment"
                }
              }
            },
            "description" : "O anexo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Busca um anexo do ticket pelo id",
        "tags" : [
          "Anexos do ticket"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{ticketId}/attachments/{attachmentId}/content" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve os **bytes** do arquivo, não a representação JSON.\n\nQuando o armazenamento entrega o arquivo direto ao cliente, a resposta é `302` com a URL assinada no cabeçalho `Location`: **siga o redirecionamento** — configure o seu cliente HTTP para segui-lo, porque um cliente que pare no `302` recebe um corpo vazio e conclui que o arquivo não existe. Quando não, a resposta é `200` com o tipo de mídia do arquivo e `Content-Disposition: attachment`.\n\nNenhum parâmetro de consulta é aceito: `fields` não faz sentido sobre bytes.",
        "operationId" : "downloadTicketAttachment",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do anexo",
            "example" : 912,
            "in" : "path",
            "name" : "attachmentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "*/*" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "O conteúdo do arquivo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "302" : {
            "content" : {
              "*/*" : {
                "schema" : {
                  "type" : "object"
                }
              }
            },
            "description" : "A URL assinada do arquivo, em `Location`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o anexo não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Baixa o conteúdo de um anexo",
        "tags" : [
          "Anexos do ticket"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{ticketId}/billable-items" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é `-createdAt` (o lançamento mais novo primeiro), a mesma da aba.\n\n`createdAt` é o instante do lançamento, e é a única data desta API que também ordena: ela existe em todo item, desde sempre. `updatedAt` só filtra — é uma coluna nova, nula no item que nunca foi alterado desde ela, e um valor nulo não serve de chave de paginação estável.",
        "operationId" : "listTicketBillableItems",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `billingStatus` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[billingStatus][eq]",
            "schema" : {
              "enum" : [
                "PENDING",
                "INVOICED",
                "COMPLETED",
                "CANCELED"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `billingStatus` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[billingStatus][in]",
            "schema" : {
              "example" : "PENDING,INVOICED,COMPLETED,CANCELED",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `productServiceId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[productServiceId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `productServiceId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[productServiceId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `invoiceId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[invoiceId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `invoiceId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[invoiceId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `launchedByAgentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[launchedByAgentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `createdAt`, `id` (padrão `-createdAt`). Prefixe com `-` para descendente (ex.: `sort=-createdAt`); sempre desempatado por `id` na mesma direção.",
            "example" : "-createdAt",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `description`, `quantity`, `unitPrice`, `totalPrice`, `productServiceId`, `customerId`, `billingStatus`, `invoiceId`, `launchedByAgentId`, `createdAt`, `updatedAt`.",
            "example" : "id,description,quantity",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "billingStatus" : "PENDING",
                      "createdAt" : "2026-01-10T13:10:00Z",
                      "customerId" : 15,
                      "description" : "Hora técnica",
                      "id" : 614,
                      "invoiceId" : null,
                      "launchedByAgentId" : 42,
                      "productServiceId" : 8,
                      "quantity" : 2.0,
                      "totalPrice" : 61.0,
                      "unitPrice" : 30.5,
                      "updatedAt" : "2026-01-10T13:10:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketBillableItem"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de itens faturáveis",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista os itens faturáveis de um ticket",
        "tags" : [
          "Itens faturáveis do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. O `agentId` é **obrigatório**: a coluna que registra quem lançou não aceita nulo, e uma chave de API não é uma pessoa — o corpo precisa dizer em nome de quem o lançamento entra. Ele fica registrado no item e **não muda** em edições posteriores.\n\nSem `unitPrice`, o preço é o do produto no catálogo naquele instante, e fica travado no item. Sem `description`, a descrição é o nome do produto. O item nasce `PENDING`, sem fatura.\n\nLançar é permitido em ticket concluído ou fechado, como na tela. Nenhum parâmetro de consulta é aceito.",
        "operationId" : "createTicketBillableItem",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "description" : "Hora técnica",
                "productServiceId" : 8,
                "quantity" : 2,
                "unitPrice" : 30.5
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketBillableItemInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "billingStatus" : "PENDING",
                  "createdAt" : "2026-01-10T13:10:00Z",
                  "customerId" : 15,
                  "description" : "Hora técnica",
                  "id" : 614,
                  "invoiceId" : null,
                  "launchedByAgentId" : 42,
                  "productServiceId" : 8,
                  "quantity" : 2.0,
                  "totalPrice" : 61.0,
                  "unitPrice" : 30.5,
                  "updatedAt" : "2026-01-10T13:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketBillableItem"
                }
              }
            },
            "description" : "O item lançado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o agente ou o produto não existe nesta empresa — o campo culpado vem em `errors[].field`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed` (campo obrigatório ausente, quantidade não positiva, produto inativo) ou `ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lança um produto/serviço no ticket",
        "tags" : [
          "Itens faturáveis do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/billable-items/{itemId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Exclusão definitiva da linha, como na aba. Item que já está em uma fatura responde `422 business_rule_violation`: retire-o pela fatura.\n\nEm ticket concluído ou fechado a resposta é `422 ticket_not_editable`, e em ticket na lixeira, `422 ticket_deleted`. Nenhum parâmetro de consulta é aceito.",
        "operationId" : "deleteTicketBillableItem",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do item faturável",
            "example" : 512,
            "in" : "path",
            "name" : "itemId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "O item não existe mais",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o item não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`business_rule_violation` quando o item já está em uma fatura, `ticket_not_editable` ou `ticket_deleted`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Exclui um item faturável do ticket",
        "tags" : [
          "Itens faturáveis do ticket"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. O item precisa ser **deste** ticket: um item que existe, mas pertence a outro ticket da mesma empresa, responde `404 not_found`.",
        "operationId" : "getTicketBillableItem",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do item faturável",
            "example" : 512,
            "in" : "path",
            "name" : "itemId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `description`, `quantity`, `unitPrice`, `totalPrice`, `productServiceId`, `customerId`, `billingStatus`, `invoiceId`, `launchedByAgentId`, `createdAt`, `updatedAt`.",
            "example" : "id,description,quantity",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "billingStatus" : "PENDING",
                  "createdAt" : "2026-01-10T13:10:00Z",
                  "customerId" : 15,
                  "description" : "Hora técnica",
                  "id" : 614,
                  "invoiceId" : null,
                  "launchedByAgentId" : 42,
                  "productServiceId" : 8,
                  "quantity" : 2.0,
                  "totalPrice" : 61.0,
                  "unitPrice" : 30.5,
                  "updatedAt" : "2026-01-10T13:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketBillableItem"
                }
              }
            },
            "description" : "O item",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o item não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Obtém um item faturável do ticket",
        "tags" : [
          "Itens faturáveis do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `tickets:write`. JSON Merge Patch (RFC 7396) sobre o estado atual: só os campos enviados mudam, e `null` explícito apaga o membro — o que aqui significa recusa, porque nenhum dos quatro campos aceita nulo.\n\n**`agentId` não existe neste corpo**, e enviá-lo é `422 validation_failed` com `unknown_field`: quem lançou o item não muda numa edição. Quem assina a alteração é a própria chave, no histórico do ticket.\n\nTrocar o produto **não** retraz o preço do catálogo: `unitPrice` é o que estiver no corpo, ou o que já estava no item. O total é recalculado sempre.\n\nItem que já está em uma fatura responde `422 business_rule_violation`: edite-o pela fatura.",
        "operationId" : "updateTicketBillableItem",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do item faturável",
            "example" : 512,
            "in" : "path",
            "name" : "itemId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "description" : "Hora tecnica",
                "productServiceId" : 8,
                "quantity" : 3,
                "unitPrice" : 30.5
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketBillableItemPatchInput"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "description" : "Hora tecnica",
                "productServiceId" : 8,
                "quantity" : 3,
                "unitPrice" : 30.5
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketBillableItemPatchInput"
              }
            }
          },
          "description" : "Campos a alterar no item faturável",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "billingStatus" : "PENDING",
                  "createdAt" : "2026-01-10T13:10:00Z",
                  "customerId" : 15,
                  "description" : "Hora técnica",
                  "id" : 614,
                  "invoiceId" : null,
                  "launchedByAgentId" : 42,
                  "productServiceId" : 8,
                  "quantity" : 2.0,
                  "totalPrice" : 61.0,
                  "unitPrice" : 30.5,
                  "updatedAt" : "2026-01-10T13:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketBillableItem"
                }
              }
            },
            "description" : "O item depois da edição",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o item ou o produto não existe nesta empresa — o item precisa ser deste ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`business_rule_violation` quando o item já está em uma fatura, `ticket_not_editable` em ticket concluído ou fechado, `ticket_deleted` em ticket na lixeira, ou `validation_failed`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Edita um item faturável do ticket",
        "tags" : [
          "Itens faturáveis do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/chat-conversations" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Manda o modelo aprovado pelo canal para o **contato do ticket** — o telefone sai do contato, no servidor, e não do corpo: um número livre transformaria permissão de ticket em permissão de mandar mensagem para qualquer um.\n\n**Isto custa dinheiro**: a Meta cobra por conversa iniciada. Mande `Idempotency-Key` — uma repetição por timeout devolve a resposta original, inclusive o `202`, em vez de iniciar uma segunda conversa.\n\nDuas respostas possíveis, e as duas são sucesso:\n\n- `201` com o vínculo e o cabeçalho `Location`, quando a conversa já existe do outro lado;\n- `202` **sem corpo**, quando não há vínculo a devolver: a conversa ainda não nasceu do outro lado, o vínculo falhou depois do envio, **ou** a chamada ao MSP Talks ficou sem resposta depois de a conexão abrir (timeout). O `202` significa **\"pode ter saído\"**, e é assim que ele deve ser lido: preferimos aceitar uma mensagem que talvez não tenha saído a cobrar o cliente duas vezes.\n\n**Como conferir depois de um `202`, sempre:** liste as conversas do ticket (`GET /v1/tickets/{ticketId}/chat-sessions`). Se a conversa aparecer, a mensagem saiu — não reenvie. Se **nada** aparecer ali depois de alguns minutos (a conversa também entra sozinha quando o contato responder), então o envio provavelmente não aconteceu: para tentar de novo, mande a requisição com uma `Idempotency-Key` **NOVA**. Repetir com a mesma chave devolve o `202` guardado e não fala com o fornecedor.\n\n**Os erros desta rota significam que nenhuma mensagem saiu**: `422` é recusa nossa, antes de qualquer envio, e `503` é recusa explícita do MSP Talks ou conexão que nem chegou a abrir (recusada, endereço que não resolve). Os dois podem ser repetidos com a mesma chave.\n\n`agentId` é obrigatório: é o e-mail dele que o MSP Talks recebe como atendente da conversa. O ticket precisa ter contato com telefone, e a integração precisa estar configurada e ativa na empresa.",
        "operationId" : "startTicketChatConversation",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "channelId" : "c1",
                "departmentId" : "d1",
                "parameters" : {
                  "CHAMADO" : "18342",
                  "NOME" : "Beatriz"
                },
                "primary" : true,
                "templateId" : "t1"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketChatConversationInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "alsoLinkedToTicketId" : null,
                  "channelLabel" : "Suporte WhatsApp",
                  "contactName" : "Beatriz Lima",
                  "createdAt" : "2026-01-10T12:50:00Z",
                  "id" : 77,
                  "lastNoteAt" : "2026-01-10T14:10:00Z",
                  "lastNoteStatus" : "SENT",
                  "linkOrigin" : "OUTBOUND",
                  "linkedByAgentId" : 42,
                  "primarySession" : true,
                  "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "sessionNumber" : "98765",
                  "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "updatedAt" : "2026-01-10T14:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketChatSession"
                }
              }
            },
            "description" : "A conversa foi aberta e vinculada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "202" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "alsoLinkedToTicketId" : null,
                  "channelLabel" : "Suporte WhatsApp",
                  "contactName" : "Beatriz Lima",
                  "createdAt" : "2026-01-10T12:50:00Z",
                  "id" : 77,
                  "lastNoteAt" : "2026-01-10T14:10:00Z",
                  "lastNoteStatus" : "SENT",
                  "linkOrigin" : "OUTBOUND",
                  "linkedByAgentId" : 42,
                  "primarySession" : true,
                  "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "sessionNumber" : "98765",
                  "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "updatedAt" : "2026-01-10T14:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketChatSession"
                }
              }
            },
            "description" : "A mensagem **pode ter saído** e não há vínculo a devolver. Confirme listando as conversas do ticket em `GET /v1/tickets/{ticketId}/chat-sessions`: se a conversa aparecer, não reenvie; se nada aparecer ali, tente de novo com uma `Idempotency-Key` NOVA — repetir com a mesma devolve este mesmo `202` sem falar com o fornecedor",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o agente não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira, ou `business_rule_violation` quando o contato do ticket não tem telefone, ou quando a integração com o MSP Talks não está configurada/ativa nesta empresa. **Nenhuma mensagem saiu**",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`service_unavailable`: o MSP Talks recusou a chamada respondendo um erro, ou a conexão com ele nem chegou a abrir — **nenhuma mensagem saiu**, e vale repetir, inclusive com a mesma `Idempotency-Key`. Uma falha SEM resposta depois de a conexão abrir não chega aqui: ela sai como `202`, porque não dá para afirmar que nada foi enviado. O mesmo código também sai como `idempotency_unavailable` quando a requisição traz `Idempotency-Key` e o Redis está fora — o campo `code` do corpo distingue os dois",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Inicia uma conversa no MSP Talks a partir do ticket",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/chat-sessions" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é `-id` (a mais recente primeiro); `createdAt` também ordena.\n\n`updatedAt` é `lastNoteAt` quando há anotação e `createdAt` quando não há — a anotação é a única alteração que um vínculo sofre. Ele filtra, mas não ordena: o valor combina duas colunas e não serve de chave de paginação estável.\n\nNenhuma chamada ao MSP Talks acontece na leitura: o que volta é o que o Desk gravou quando a conversa foi vinculada.",
        "operationId" : "listTicketChatSessions",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `sessionId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[sessionId][eq]",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `primarySession` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[primarySession][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `id`, `createdAt` (padrão `-id`). Prefixe com `-` para descendente (ex.: `sort=-createdAt`); sempre desempatado por `id` na mesma direção.",
            "example" : "-createdAt",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `sessionId`, `sessionNumber`, `sessionUrl`, `channelLabel`, `contactName`, `linkOrigin`, `primarySession`, `lastNoteStatus`, `lastNoteAt`, `linkedByAgentId`, `alsoLinkedToTicketId`, `createdAt`, `updatedAt`.",
            "example" : "id,sessionId,sessionNumber",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "alsoLinkedToTicketId" : null,
                      "channelLabel" : "Suporte WhatsApp",
                      "contactName" : "Beatriz Lima",
                      "createdAt" : "2026-01-10T12:50:00Z",
                      "id" : 77,
                      "lastNoteAt" : "2026-01-10T14:10:00Z",
                      "lastNoteStatus" : "SENT",
                      "linkOrigin" : "OUTBOUND",
                      "linkedByAgentId" : 42,
                      "primarySession" : true,
                      "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                      "sessionNumber" : "98765",
                      "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                      "updatedAt" : "2026-01-10T14:10:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketChatSession"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de conversas vinculadas",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista as conversas do MSP Talks vinculadas a um ticket",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. O Desk **confirma a conversa no MSP Talks** antes de gravar: um `sessionId` que não existe lá é recusado, em vez de virar um vínculo que aponta para lugar nenhum. A resposta é `201` com o vínculo e o cabeçalho `Location`.\n\n`agentId` é obrigatório: é quem fica registrado como tendo vinculado a conversa. Um agente que não existe, está inativo ou é de outra empresa responde `404 not_found` apontando o campo.\n\n`primary` ausente decide sozinho — a conversa vira a principal se o ticket ainda não tiver uma; `false` explícito é escolha e é respeitado.\n\nSe a conversa já estiver em **outro** ticket da empresa, o vínculo é criado do mesmo jeito e `alsoLinkedToTicketId` diz qual é o outro. Repetir o vínculo **no mesmo ticket** é `422 business_rule_violation`: ele já existe.\n\nRequer a integração com o MSP Talks configurada e ativa na empresa: sem ela a resposta é `422 business_rule_violation`. Uma falha do próprio fornecedor é `503 service_unavailable` — e essa, sim, vale repetir.",
        "operationId" : "linkTicketChatSession",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "primary" : true,
                "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketChatSessionInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "alsoLinkedToTicketId" : null,
                  "channelLabel" : "Suporte WhatsApp",
                  "contactName" : "Beatriz Lima",
                  "createdAt" : "2026-01-10T12:50:00Z",
                  "id" : 77,
                  "lastNoteAt" : "2026-01-10T14:10:00Z",
                  "lastNoteStatus" : "SENT",
                  "linkOrigin" : "OUTBOUND",
                  "linkedByAgentId" : 42,
                  "primarySession" : true,
                  "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "sessionNumber" : "98765",
                  "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "updatedAt" : "2026-01-10T14:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketChatSession"
                }
              }
            },
            "description" : "O vínculo criado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o agente não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira, `business_rule_violation` quando a conversa já está neste ticket ou quando a integração com o MSP Talks não está configurada/ativa nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`service_unavailable`: o MSP Talks não respondeu, respondeu fora do contrato ou recusou a chamada. É o único erro destas rotas que vale repetir. O mesmo código também sai como `idempotency_unavailable` quando a requisição traz `Idempotency-Key` e o Redis está fora — o campo `code` do corpo distingue os dois",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Vincula uma conversa existente do MSP Talks ao ticket",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/chat-sessions/{linkId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Apaga o vínculo — a conversa continua existindo no MSP Talks, e o resumo dela guardado no Desk é apagado junto.\n\nSe a desvinculada era a principal, a mais antiga que sobrar assume o posto; não sobrando nenhuma com endereço, o ticket deixa de referenciar conversa.\n\nUm vínculo de outro ticket, ou já removido, responde `404 not_found`. Nenhuma chamada ao MSP Talks acontece aqui.",
        "operationId" : "unlinkTicketChatSession",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do vínculo",
            "example" : 77,
            "in" : "path",
            "name" : "linkId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "A conversa não está mais no ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Desvincula a conversa do ticket",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. O `linkId` é o id do **vínculo**, não o da conversa no MSP Talks. Um vínculo de outro ticket responde `404 not_found`, mesmo sendo da mesma empresa.\n\n`alsoLinkedToTicketId` vem nulo aqui: ele só é apurado no momento do vínculo, porque depois de gravado o próprio vínculo apareceria como \"o outro ticket\".",
        "operationId" : "getTicketChatSession",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do vínculo",
            "example" : 77,
            "in" : "path",
            "name" : "linkId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `sessionId`, `sessionNumber`, `sessionUrl`, `channelLabel`, `contactName`, `linkOrigin`, `primarySession`, `lastNoteStatus`, `lastNoteAt`, `linkedByAgentId`, `alsoLinkedToTicketId`, `createdAt`, `updatedAt`.",
            "example" : "id,sessionId,sessionNumber",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "alsoLinkedToTicketId" : null,
                  "channelLabel" : "Suporte WhatsApp",
                  "contactName" : "Beatriz Lima",
                  "createdAt" : "2026-01-10T12:50:00Z",
                  "id" : 77,
                  "lastNoteAt" : "2026-01-10T14:10:00Z",
                  "lastNoteStatus" : "SENT",
                  "linkOrigin" : "OUTBOUND",
                  "linkedByAgentId" : 42,
                  "primarySession" : true,
                  "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "sessionNumber" : "98765",
                  "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "updatedAt" : "2026-01-10T14:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketChatSession"
                }
              }
            },
            "description" : "A conversa vinculada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lê uma conversa vinculada ao ticket",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `tickets:write`. JSON Merge Patch com **um campo só**, `primary`, e ele só aceita `true`. O resto da representação é o que o MSP Talks respondeu quando a conversa foi vinculada, e um corpo que o envie responde `422 validation_failed` com `unknown_field`.\n\n**Não existe despromover**: a conversa principal sai do posto quando outra entra, e `false` responde `422 validation_failed` com `invalid_value`. Um corpo **vazio** é outra coisa: ele não pede nada, e responde `200` com o vínculo como está, sem escrever.\n\nO endereço da conversa principal é o que o ticket passa a referenciar.\n\nNenhuma chamada ao MSP Talks acontece aqui.",
        "operationId" : "updateTicketChatSession",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do vínculo",
            "example" : 77,
            "in" : "path",
            "name" : "linkId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "primary" : true
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketChatSessionPatchInput"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "primary" : true
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketChatSessionPatchInput"
              }
            }
          },
          "description" : "O único campo alterável do vínculo",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "alsoLinkedToTicketId" : null,
                  "channelLabel" : "Suporte WhatsApp",
                  "contactName" : "Beatriz Lima",
                  "createdAt" : "2026-01-10T12:50:00Z",
                  "id" : 77,
                  "lastNoteAt" : "2026-01-10T14:10:00Z",
                  "lastNoteStatus" : "SENT",
                  "linkOrigin" : "OUTBOUND",
                  "linkedByAgentId" : 42,
                  "primarySession" : true,
                  "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "sessionNumber" : "98765",
                  "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "updatedAt" : "2026-01-10T14:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketChatSession"
                }
              }
            },
            "description" : "O vínculo, agora principal",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o vínculo não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira, ou `validation_failed` para `primary` diferente de `true` e campo desconhecido",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Torna esta a conversa principal do ticket",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/chat-sessions/{linkId}/notes" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. A anotação é interna à conversa: só quem atende do lado do MSP Talks a vê, o cliente não. É a mesma que o Desk escreve sozinho quando uma conversa é vinculada.\n\n`text` é opcional — sem ele vale o modelo de mensagem configurado na integração, ou o texto padrão com código, assunto e link do ticket. O que for enviado vai em **texto puro**: marcação HTML apareceria literal para quem atende.\n\nA resposta é `200` com o vínculo, onde `lastNoteStatus` e `lastNoteAt` dizem como terminou. Uma falha do fornecedor **chega ao chamador** e fica gravada como `FAILED`, para que o reenvio seja possível.\n\nSem integração configurada e ativa na empresa a resposta é `422 business_rule_violation`; uma falha do fornecedor é `503 service_unavailable`.",
        "operationId" : "noteTicketChatSession",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do vínculo",
            "example" : 77,
            "in" : "path",
            "name" : "linkId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "text" : "Chamado em análise pelo time de infraestrutura."
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketChatNoteInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "alsoLinkedToTicketId" : null,
                  "channelLabel" : "Suporte WhatsApp",
                  "contactName" : "Beatriz Lima",
                  "createdAt" : "2026-01-10T12:50:00Z",
                  "id" : 77,
                  "lastNoteAt" : "2026-01-10T14:10:00Z",
                  "lastNoteStatus" : "SENT",
                  "linkOrigin" : "OUTBOUND",
                  "linkedByAgentId" : 42,
                  "primarySession" : true,
                  "sessionId" : "3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "sessionNumber" : "98765",
                  "sessionUrl" : "https://atendimento.exemplo.com.br/sessions/3b2f6c1e-9a4d-4f8b-8c2e-1d5a7e9b0c34",
                  "updatedAt" : "2026-01-10T14:10:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketChatSession"
                }
              }
            },
            "description" : "O vínculo, com o resultado da anotação",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o vínculo não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira, ou `business_rule_violation` quando a integração com o MSP Talks não está configurada/ativa nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`service_unavailable`: o MSP Talks não respondeu, respondeu fora do contrato ou recusou a chamada. É o único erro destas rotas que vale repetir. O mesmo código também sai como `idempotency_unavailable` quando a requisição traz `Idempotency-Key` e o Redis está fora — o campo `code` do corpo distingue os dois",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Escreve uma anotação interna na conversa do MSP Talks",
        "tags" : [
          "Chat do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/followers" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação é por `agentId` crescente, e é a única aceita: `createdAt` é uma coluna nova, nula no vínculo anterior a esta API, e um valor nulo não serve de chave de paginação estável.\n\n`updatedAt` filtra pela **mesma** data que `createdAt`. O vínculo não é editável, então não existe uma segunda data — o campo está aqui para que uma sincronização por data de alteração possa varrer todas as abas do ticket com os mesmos parâmetros, sem tratar seguidores como exceção.",
        "operationId" : "listTicketFollowers",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[agentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[agentId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `agentId` (padrão `agentId`). Prefixe com `-` para descendente (ex.: `sort=-agentId`); sempre desempatado por `id` na mesma direção.",
            "example" : "-agentId",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `agentId`, `firstName`, `lastName`, `createdAt`, `updatedAt`.",
            "example" : "agentId,firstName,lastName",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "agentId" : 51,
                      "createdAt" : "2026-01-10T12:15:00Z",
                      "firstName" : "Carlos",
                      "lastName" : "Pereira",
                      "updatedAt" : "2026-01-10T12:15:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketFollower"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de seguidores",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista os seguidores de um ticket",
        "tags" : [
          "Seguidores do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. O corpo tem um campo só, `agentId`, e ele é obrigatório: é o próprio recurso. A resposta é `201` com o vínculo e o cabeçalho `Location` apontando para ele.\n\n**Repetir é `201` com o mesmo corpo**, não `409`: o estado final pedido já é o estado do ticket. Nenhum parâmetro de consulta é aceito.\n\nO agente precisa existir, estar ativo e ser da empresa da chave — senão `404 not_found` apontando `agentId`. Um agente que existe mas **não alcança o ticket** (por carteira de clientes ou por grupo de serviço) é outra coisa: a resposta é `422 business_rule_violation` com a mensagem da regra, a mesma que a tela mostra.\n\nO histórico registra quem adicionou. Como uma chave de API não é uma pessoa, o evento sai em nome da **integração**, com o id da chave — e o agente recebe o aviso no sino e por e-mail, como receberia de um colega.",
        "operationId" : "addTicketFollower",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 51
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketFollowerInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 51,
                  "createdAt" : "2026-01-10T12:15:00Z",
                  "firstName" : "Carlos",
                  "lastName" : "Pereira",
                  "updatedAt" : "2026-01-10T12:15:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketFollower"
                }
              }
            },
            "description" : "O seguidor",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o agente não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira, ou `business_rule_violation` quando o agente não pode seguir este ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Adiciona um seguidor ao ticket",
        "tags" : [
          "Seguidores do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/followers/{agentId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. **Idempotente**: remover um agente que não segue o ticket também responde `204`. Não há o que distinguir — o estado final é o mesmo. Nenhum parâmetro de consulta é aceito.\n\nEm ticket na lixeira a resposta é `422 ticket_deleted`, a mesma trava da adição.",
        "operationId" : "removeTicketFollower",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do agente seguidor",
            "example" : 42,
            "in" : "path",
            "name" : "agentId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "O agente não segue mais o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Remove um seguidor do ticket",
        "tags" : [
          "Seguidores do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/message-templates/{templateId}" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve `templateId`, `name` e `body` — o texto do modelo com os placeholders já trocados pelos dados deste ticket. É a mesma operação que a tela faz antes de abrir o editor.\n\n**Sem assunto e sem lista de anexos**, porque o produto não tem nenhum dos dois: o modelo de mensagem não guarda assunto, e os arquivos do modelo não são anexados à nota. Para anexar um arquivo, envie-o em `POST /v1/tickets/{ticketId}/attachments` e passe o id em `attachmentIds` da resposta ou do encaminhamento.\n\nExige apenas `tickets:read`, e funciona também em ticket na lixeira: ler o texto de um modelo não escreve nada. Um modelo de outra empresa responde `404 not_found`.",
        "operationId" : "getTicketMessageTemplate",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID do modelo de mensagem",
            "example" : 7,
            "in" : "path",
            "name" : "templateId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "body" : "<p>Olá, Beatriz. Para seguirmos com o chamado 18342, precisamos de acesso remoto ao seu computador. Podemos conectar hoje às 15h?</p>",
                  "name" : "Solicitação de acesso remoto",
                  "templateId" : 7
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicMessageTemplateApplication"
                }
              }
            },
            "description" : "O modelo resolvido para o ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Aplica um modelo de mensagem a este ticket",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      }
    },
    "/v1/tickets/{ticketId}/notes" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é a da linha do tempo do produto: `-createdAt`, desempatada pelo `id` na mesma direção.\n\n`sort=` aceita só `createdAt` e `id`. `updatedAt` é filtro e não ordenação: o valor é `createdAt` enquanto a nota nunca tiver sido editada, e essa expressão não serve de chave de paginação estável.\n\n`createdAt` tem precisão de segundo, então várias notas podem compartilhar o mesmo instante — é por isso que o `id` sempre desempata.",
        "operationId" : "listTicketNotes",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `type` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[type][eq]",
            "schema" : {
              "enum" : [
                "FORWARD",
                "REPLY",
                "NOTE"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `type` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[type][in]",
            "schema" : {
              "example" : "FORWARD,REPLY,NOTE",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `visibility` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[visibility][eq]",
            "schema" : {
              "enum" : [
                "PUBLIC",
                "PRIVATE"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[origin][eq]",
            "schema" : {
              "enum" : [
                "USER",
                "CONTACT_CUSTOMER",
                "EMAIL_INBOUND",
                "NINJA_RMM",
                "DATTO_RMM",
                "SYSTEM",
                "API"
              ],
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `origin` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[origin][in]",
            "schema" : {
              "example" : "USER,CONTACT_CUSTOMER,EMAIL_INBOUND,NINJA_RMM,DATTO_RMM,SYSTEM,API",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `authorAgentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[authorAgentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `authorAgentId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[authorAgentId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `id`, `createdAt` (padrão `-createdAt`). Prefixe com `-` para descendente (ex.: `sort=-createdAt`); sempre desempatado por `id` na mesma direção.",
            "example" : "-createdAt",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `type`, `visibility`, `body`, `recipients`, `cc`, `sender`, `origin`, `apiKeyId`, `apiKeyName`, `authorAgentId`, `authorContactId`, `mentionedAgentIds`, `attachmentIds`, `createdAt`, `updatedAt`.",
            "example" : "id,type,visibility",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "apiKeyId" : 8,
                      "apiKeyName" : "Integração ERP",
                      "attachmentIds" : [
                        912
                      ],
                      "authorAgentId" : 42,
                      "authorContactId" : null,
                      "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                      "cc" : "financeiro@acme.com.br",
                      "createdAt" : "2026-01-10T14:05:00Z",
                      "id" : 1204,
                      "mentionedAgentIds" : [ ],
                      "origin" : "API",
                      "recipients" : "beatriz.lima@acme.com.br",
                      "sender" : null,
                      "type" : "REPLY",
                      "updatedAt" : "2026-01-10T14:05:00Z",
                      "visibility" : "PUBLIC"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketNote"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de notas",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista as notas de um ticket",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Informe exatamente um entre `body` e `messageTemplateId`; os dois juntos, ou nenhum, respondem `422 validation_failed`. Com `messageTemplateId`, o corpo da nota é o texto do modelo já resolvido para este ticket.\n\n`then` decide o que acontece com o ticket depois da nota: `PAUSE` deixa o atendimento pendente e `COMPLETE` conclui. A resposta é sempre a nota criada — o novo estado do ticket sai em `GET /v1/tickets/{id}`. Com `COMPLETE`, as condições da conclusão (tarefa em aberto, vínculo dependente em aberto, apontamento sem descrição, campo obrigatório para concluir) são conferidas **antes** de gravar: se alguma impede, a resposta é `422 business_rule_violation` e nada é gravado — resolva o impedimento e reenvie. Se a conclusão ainda for recusada depois (o ticket mudou entre a conferência e a conclusão), a resposta também é `422 business_rule_violation`, mas a nota **já ficou gravada**: não a reenvie — conclua o ticket pela ação de conclusão.\n\n`agentId`, `messageTemplateId` e cada `mentionedAgentIds[i]` são resolvidos na empresa da chave: um id que não existe nela responde `404 not_found` com o campo culpado em `errors[].field`, e nada é gravado. Uma menção a um agente que não enxerga este ticket é registrada, mas não gera notificação.\n\nA nota simples não aceita anexos — quem vincula arquivo ao e-mail é a resposta ou o encaminhamento. Um corpo com `attachmentIds` é recusado com `422 validation_failed` e `unknown_field`.\n\nNenhum parâmetro de consulta é aceito.",
        "operationId" : "createTicketNote",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "body" : "<p>Cliente autorizou a troca do toner; cartucho separado no estoque.</p>",
                "mentionedAgentIds" : [
                  51
                ],
                "visibility" : "PRIVATE"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketNoteInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "apiKeyId" : 8,
                  "apiKeyName" : "Integração ERP",
                  "attachmentIds" : [
                    912
                  ],
                  "authorAgentId" : 42,
                  "authorContactId" : null,
                  "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                  "cc" : "financeiro@acme.com.br",
                  "createdAt" : "2026-01-10T14:05:00Z",
                  "id" : 1204,
                  "mentionedAgentIds" : [ ],
                  "origin" : "API",
                  "recipients" : "beatriz.lima@acme.com.br",
                  "sender" : null,
                  "type" : "REPLY",
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "visibility" : "PUBLIC"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketNote"
                }
              }
            },
            "description" : "A nota criada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o agente, o modelo de mensagem ou uma menção não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Registra uma nota no ticket",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/notes/forward" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Envia um e-mail para os endereços informados, com assunto próprio, e registra o encaminhamento na linha do tempo. `recipients` exige ao menos um endereço, no máximo 20 e sem repetições.\n\n`subject` é obrigatório **sempre**, inclusive com `messageTemplateId`: o modelo de mensagem não tem assunto no produto, então não há de onde herdá-lo.\n\n`visibility` também é obrigatória, como na tela, e **não** decide quem recebe o e-mail: os destinatários recebem nos dois casos. Ela decide quem vê a nota no portal do cliente — `PUBLIC` mostra a conversa com o terceiro para o contato do solicitante, `PRIVATE` a mantém entre os agentes. Não há padrão: a escolha é sua, porque publicar não se desfaz.\n\nInforme exatamente um entre `body` e `messageTemplateId`. Os arquivos do modelo **não** são anexados; para anexar, envie o arquivo em `POST /v1/tickets/{ticketId}/attachments` e passe o id em `attachmentIds`.\n\nO encaminhamento não dispara a automação de fluxo por comentário de agente — ele não é um comentário. Nenhum parâmetro de consulta é aceito.",
        "operationId" : "forwardTicketNote",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "attachmentIds" : [
                  912
                ],
                "body" : "<p>Segue o chamado para aprovação da compra do toner.</p>",
                "recipients" : [
                  "compras@acme.com.br"
                ],
                "subject" : "Fwd: Troca de toner",
                "visibility" : "PRIVATE"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketForwardInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "apiKeyId" : 8,
                  "apiKeyName" : "Integração ERP",
                  "attachmentIds" : [
                    912
                  ],
                  "authorAgentId" : 42,
                  "authorContactId" : null,
                  "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                  "cc" : "financeiro@acme.com.br",
                  "createdAt" : "2026-01-10T14:05:00Z",
                  "id" : 1204,
                  "mentionedAgentIds" : [ ],
                  "origin" : "API",
                  "recipients" : "beatriz.lima@acme.com.br",
                  "sender" : null,
                  "type" : "REPLY",
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "visibility" : "PUBLIC"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketNote"
                }
              }
            },
            "description" : "O encaminhamento registrado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o agente ou o modelo de mensagem não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Encaminha o ticket para destinatários livres",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/notes/reply" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Envia um e-mail ao contato do ticket e registra a resposta na linha do tempo. O destinatário não vem no corpo: é sempre o contato do ticket, como na tela — `cc` são só as cópias, no máximo 20 e sem repetições. Por isso a resposta é sempre pública e não há `visibility` a informar.\n\nUm ticket sem contato solicitante responde `422 business_rule_violation`: não há para quem enviar.\n\nInforme exatamente um entre `body` e `messageTemplateId`. Com `messageTemplateId`, o corpo é o texto do modelo já resolvido para este ticket — e os arquivos do modelo **não** são anexados; para anexar, envie o arquivo em `POST /v1/tickets/{ticketId}/attachments` e passe o id em `attachmentIds`.\n\n`then` decide o que acontece com o ticket depois da resposta: `PAUSE` deixa o atendimento pendente e `COMPLETE` conclui. A resposta é sempre a nota criada — o novo estado do ticket sai em `GET /v1/tickets/{id}`. Com `COMPLETE`, as condições da conclusão (tarefa em aberto, vínculo dependente em aberto, apontamento sem descrição, campo obrigatório para concluir) são conferidas **antes** de gravar: se alguma impede, a resposta é `422 business_rule_violation`, nada é gravado e nenhum e-mail sai — resolva o impedimento e reenvie. Se a conclusão ainda for recusada depois (o ticket mudou entre a conferência e a conclusão), a resposta também é `422 business_rule_violation`, mas a resposta ao contato **já ficou gravada e o e-mail sai**: não a reenvie — conclua o ticket pela ação de conclusão.\n\nNenhum parâmetro de consulta é aceito.",
        "operationId" : "replyTicketNote",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "attachmentIds" : [
                  912
                ],
                "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                "cc" : [
                  "financeiro@acme.com.br"
                ]
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketReplyInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "apiKeyId" : 8,
                  "apiKeyName" : "Integração ERP",
                  "attachmentIds" : [
                    912
                  ],
                  "authorAgentId" : 42,
                  "authorContactId" : null,
                  "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                  "cc" : "financeiro@acme.com.br",
                  "createdAt" : "2026-01-10T14:05:00Z",
                  "id" : 1204,
                  "mentionedAgentIds" : [ ],
                  "origin" : "API",
                  "recipients" : "beatriz.lima@acme.com.br",
                  "sender" : null,
                  "type" : "REPLY",
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "visibility" : "PUBLIC"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketNote"
                }
              }
            },
            "description" : "A resposta registrada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o agente ou o modelo de mensagem não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Responde ao contato do ticket",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/notes/{noteId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Remove a nota e os arquivos vinculados a ela. Nota inexistente ou de outro ticket responde `404 not_found`.",
        "operationId" : "deleteTicketNote",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da nota",
            "example" : 10,
            "in" : "path",
            "name" : "noteId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "Nota excluída",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_not_editable` em ticket concluído ou fechado, ou `ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Exclui uma nota do ticket",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve `404 not_found` quando a nota não existe ou pertence a outro ticket.",
        "operationId" : "getTicketNote",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da nota",
            "example" : 10,
            "in" : "path",
            "name" : "noteId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `type`, `visibility`, `body`, `recipients`, `cc`, `sender`, `origin`, `apiKeyId`, `apiKeyName`, `authorAgentId`, `authorContactId`, `mentionedAgentIds`, `attachmentIds`, `createdAt`, `updatedAt`.",
            "example" : "id,type,visibility",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "apiKeyId" : 8,
                  "apiKeyName" : "Integração ERP",
                  "attachmentIds" : [
                    912
                  ],
                  "authorAgentId" : 42,
                  "authorContactId" : null,
                  "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                  "cc" : "financeiro@acme.com.br",
                  "createdAt" : "2026-01-10T14:05:00Z",
                  "id" : 1204,
                  "mentionedAgentIds" : [ ],
                  "origin" : "API",
                  "recipients" : "beatriz.lima@acme.com.br",
                  "sender" : null,
                  "type" : "REPLY",
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "visibility" : "PUBLIC"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketNote"
                }
              }
            },
            "description" : "A nota",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Busca uma nota do ticket pelo id",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `tickets:write`. JSON Merge Patch (RFC 7396): só os campos enviados mudam. Alteráveis: `body` e `visibility`; qualquer outro campo é `422 validation_failed` com `unknown_field`.\n\nSó a nota simples é editável — resposta e encaminhamento respondem `422 business_rule_violation`, a mesma regra do produto. Um patch que não muda nada devolve `200` sem registrar edição, e essa verificação vem primeiro: reenviar a representação atual de uma resposta devolve `200`, não `422`.",
        "operationId" : "updateTicketNote",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da nota",
            "example" : 10,
            "in" : "path",
            "name" : "noteId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "body" : "<p>Texto corrigido.</p>",
                "visibility" : "PRIVATE"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketNotePatchInput"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "body" : "<p>Texto corrigido.</p>",
                "visibility" : "PRIVATE"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketNotePatchInput"
              }
            }
          },
          "description" : "Campos a alterar na nota",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "apiKeyId" : 8,
                  "apiKeyName" : "Integração ERP",
                  "attachmentIds" : [
                    912
                  ],
                  "authorAgentId" : 42,
                  "authorContactId" : null,
                  "body" : "<p>Olá, Beatriz. Reiniciamos o spooler de impressão e a impressora voltou a responder.</p>",
                  "cc" : "financeiro@acme.com.br",
                  "createdAt" : "2026-01-10T14:05:00Z",
                  "id" : 1204,
                  "mentionedAgentIds" : [ ],
                  "origin" : "API",
                  "recipients" : "beatriz.lima@acme.com.br",
                  "sender" : null,
                  "type" : "REPLY",
                  "updatedAt" : "2026-01-10T14:05:00Z",
                  "visibility" : "PUBLIC"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketNote"
                }
              }
            },
            "description" : "A nota alterada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Altera o texto ou a visibilidade de uma nota",
        "tags" : [
          "Notas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/tasks" : {
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Paginação por cursor opaco (`?cursor=`), nunca por página/offset — use `nextCursor` da resposta anterior. A ordenação padrão é a da aba: `position` crescente, desempatada pelo `id` na mesma direção.\n\n`sort=` aceita só `position`, `deadline` e `id`. `createdAt` e `updatedAt` são filtro e não ordenação: são colunas novas, nulas no que foi registrado antes desta API, e um valor nulo não serve de chave de paginação estável.\n\nOrdenando por `deadline`, a tarefa **sem prazo** vai para o fim da ordem crescente (e para o começo da decrescente); ela continua publicando `deadline: null`. Para separá-las explicitamente, use `filter[deadline][isNull]=true`.\n\n`position` é nula em tarefa anterior a esta API, e ela ordena antes de todas as demais — a mesma ordem que a tela mostra. A posição também pode ser **negativa**: é um número de ordenação relativo, não um índice.\n\n`filter[deadline][gte]` e `filter[deadline][lte]` recebem data e hora **sem fuso** (`2026-12-01T09:30`), porque é isso que a coluna guarda; `filter[createdAt][gte]` e `filter[updatedAt][gte]`, ao contrário, exigem o fuso (`2026-09-23T14:30:00Z`).",
        "operationId" : "listTicketTasks",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[id][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `id` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[id][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `completed` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[completed][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `agentId` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[agentId][eq]",
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Filtra por `agentId` igual a um dos valores informados, separados por vírgula (até 100).",
            "in" : "query",
            "name" : "filter[agentId][in]",
            "schema" : {
              "example" : "1,2,3",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `agentId` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[agentId][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `groupTitle` igual ao valor informado.",
            "in" : "query",
            "name" : "filter[groupTitle][eq]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `deadline` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[deadline][gte]",
            "schema" : {
              "example" : "2026-09-23T14:30",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `deadline` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[deadline][lte]",
            "schema" : {
              "example" : "2026-09-23T14:30",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `deadline` ter ou não valor: `true` sem valor; `false` com valor.",
            "in" : "query",
            "name" : "filter[deadline][isNull]",
            "schema" : {
              "type" : "boolean"
            }
          },
          {
            "description" : "Filtra por `createdAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `createdAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[createdAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` maior ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][gte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Filtra por `updatedAt` menor ou igual ao valor informado.",
            "in" : "query",
            "name" : "filter[updatedAt][lte]",
            "schema" : {
              "format" : "date-time",
              "type" : "string"
            }
          },
          {
            "description" : "Itens por página. 1 a 100; padrão 25.",
            "in" : "query",
            "name" : "limit",
            "schema" : {
              "default" : 25,
              "format" : "int32",
              "maximum" : 100,
              "minimum" : 1,
              "type" : "integer"
            }
          },
          {
            "description" : "Cursor opaco da próxima página, devolvido em `nextCursor` da resposta anterior. Omita na primeira página.",
            "in" : "query",
            "name" : "cursor",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campo de ordenação: `position`, `deadline`, `id` (padrão `position`). Prefixe com `-` para descendente (ex.: `sort=-position`); sempre desempatado por `id` na mesma direção.",
            "example" : "-position",
            "in" : "query",
            "name" : "sort",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `title`, `description`, `completed`, `groupTitle`, `position`, `deadline`, `agentId`, `createdById`, `createdAt`, `updatedAt`.",
            "example" : "id,title,description",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "data" : [
                    {
                      "agentId" : 42,
                      "completed" : false,
                      "createdAt" : "2026-01-10T12:30:00Z",
                      "createdById" : 42,
                      "deadline" : "2026-01-12T09:30:00",
                      "description" : "Conferir se o job noturno terminou sem erro.",
                      "groupTitle" : false,
                      "id" : 512,
                      "position" : 200,
                      "title" : "Validar o backup do servidor",
                      "updatedAt" : "2026-01-10T12:30:00Z"
                    }
                  ],
                  "nextCursor" : "eyJpZCI6MTA0Mn0"
                },
                "schema" : {
                  "properties" : {
                    "data" : {
                      "items" : {
                        "$ref" : "#/components/schemas/PublicTicketTask"
                      },
                      "type" : "array"
                    },
                    "nextCursor" : {
                      "description" : "Cursor opaco da próxima página; `null` quando não há mais páginas.",
                      "nullable" : true,
                      "type" : "string"
                    }
                  },
                  "type" : "object"
                }
              }
            },
            "description" : "Página de tarefas",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Lista as tarefas de um ticket",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. `title` e `agentId` são obrigatórios. O agente informado fica como criador **e** responsável pela tarefa; ele precisa existir, estar ativo e ser da empresa da chave, senão a resposta é `404 not_found` em `agentId`.\n\nA tarefa entra no fim da lista. Não há `position` no corpo: a ordem é do produto, e mudá-la é `POST /v1/tickets/{ticketId}/tasks/{taskId}/move`. Um corpo que envie `position` é recusado com `422 validation_failed` e `unknown_field`.\n\n`deadline` é data e hora **sem fuso**, no formato `yyyy-MM-ddTHH:mm` (os segundos são opcionais). Uma data de calendário que não existe (`2026-02-30T10:00`) responde `422 validation_failed`.\n\n`groupTitle: true` cria um **título de grupo**, que não tem prazo, descrição nem conclusão: enviar `description`, `deadline` ou `completed` junto dele é `422 validation_failed` com `not_applicable`. `agentId` continua obrigatório, porque é o criador, mas um título de grupo não tem responsável — a resposta vem com `createdById` preenchido e `agentId` nulo.\n\nCriar tarefa é permitido em ticket concluído ou fechado. Nenhum parâmetro de consulta é aceito.",
        "operationId" : "createTicketTask",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "deadline" : "2026-01-12T09:30",
                "description" : "Conferir se o job noturno terminou sem erro.",
                "title" : "Validar o backup do servidor"
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketTaskInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "completed" : false,
                  "createdAt" : "2026-01-10T12:30:00Z",
                  "createdById" : 42,
                  "deadline" : "2026-01-12T09:30:00",
                  "description" : "Conferir se o job noturno terminou sem erro.",
                  "groupTitle" : false,
                  "id" : 512,
                  "position" : 200,
                  "title" : "Validar o backup do servidor",
                  "updatedAt" : "2026-01-10T12:30:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketTask"
                }
              }
            },
            "description" : "A tarefa criada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket ou o agente não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Cria uma tarefa no ticket",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/tasks/from-template" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Cria de uma vez as tarefas do modelo, na ordem em que ele as define, e devolve **todas** as tarefas do ticket depois da aplicação — inclusive as que já existiam, que é o que a tela recarrega.\n\nA resposta traz no máximo mil tarefas. Um ticket que passe disso é bem maior do que a aba comporta, e o caminho para lê-lo inteiro é a listagem paginada.\n\n`taskTemplateId` precisa ser um modelo da empresa da chave: um modelo de outra empresa responde `404 not_found` neste campo. `agentId` é obrigatório pelo mesmo motivo do `POST /tasks` — ele fica como criador das tarefas aplicadas.\n\nNenhum parâmetro de consulta é aceito.",
        "operationId" : "createTicketTasksFromTemplate",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "taskTemplateId" : 7
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketTaskFromTemplateInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : [
                  {
                    "agentId" : 42,
                    "completed" : false,
                    "createdAt" : "2026-01-10T12:30:00Z",
                    "createdById" : 42,
                    "deadline" : "2026-01-12T09:30:00",
                    "description" : "Conferir se o job noturno terminou sem erro.",
                    "groupTitle" : false,
                    "id" : 512,
                    "position" : 200,
                    "title" : "Validar o backup do servidor",
                    "updatedAt" : "2026-01-10T12:30:00Z"
                  }
                ],
                "schema" : {
                  "items" : {
                    "$ref" : "#/components/schemas/PublicTicketTask"
                  },
                  "type" : "array"
                }
              }
            },
            "description" : "As tarefas do ticket depois da aplicação",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, o modelo ou o agente não existe nesta empresa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Falha de validação ou regra de negócio",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Aplica um modelo de tarefas ao ticket",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/tasks/{taskId}" : {
      "delete" : {
        "description" : "Escopo exigido: `tickets:write`. Exclusão definitiva: a tarefa não vai para lixeira nenhuma. O histórico do ticket guarda o evento `TASK_REMOVED` com o título que ela tinha.\n\nExcluir tarefa é permitido em ticket concluído ou fechado. Excluir de novo responde `404 not_found`. Nenhum parâmetro de consulta é aceito.\n\nEm ticket na lixeira a resposta é `422 ticket_deleted`, a mesma trava da criação.",
        "operationId" : "deleteTicketTask",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da tarefa",
            "example" : 512,
            "in" : "path",
            "name" : "taskId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "responses" : {
          "204" : {
            "description" : "Tarefa excluída",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`ticket_deleted` em ticket na lixeira",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Exclui uma tarefa do ticket",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      },
      "get" : {
        "description" : "Escopo exigido: `tickets:read`. Devolve `404 not_found` quando a tarefa não existe ou pertence a outro ticket.",
        "operationId" : "getTicketTask",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da tarefa",
            "example" : 512,
            "in" : "path",
            "name" : "taskId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Campos de primeiro nível a retornar, separados por vírgula (`id` sempre volta): `id`, `title`, `description`, `completed`, `groupTitle`, `position`, `deadline`, `agentId`, `createdById`, `createdAt`, `updatedAt`.",
            "example" : "id,title,description",
            "in" : "query",
            "name" : "fields",
            "schema" : {
              "type" : "string"
            }
          },
          {
            "description" : "Objetos a acrescentar à resposta, separados por vírgula, até 3 por requisição: . Sem o escopo exigido de algum item pedido: `403 insufficient_scope`.",
            "example" : "customer,agent",
            "in" : "query",
            "name" : "expand",
            "schema" : {
              "type" : "string"
            }
          }
        ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "completed" : false,
                  "createdAt" : "2026-01-10T12:30:00Z",
                  "createdById" : 42,
                  "deadline" : "2026-01-12T09:30:00",
                  "description" : "Conferir se o job noturno terminou sem erro.",
                  "groupTitle" : false,
                  "id" : 512,
                  "position" : 200,
                  "title" : "Validar o backup do servidor",
                  "updatedAt" : "2026-01-10T12:30:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketTask"
                }
              }
            },
            "description" : "A tarefa",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Busca uma tarefa do ticket pelo id",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:read"
      },
      "patch" : {
        "description" : "Escopo exigido: `tickets:write`. JSON Merge Patch (RFC 7396): só os campos enviados mudam, e o resto da tarefa é reenviado ao produto como está.\n\n`completed: true` conclui a tarefa e grava o evento `TASK_COMPLETED` no histórico do ticket; `completed: false` desfaz a conclusão e **não** grava nada, exatamente como a tela. O evento só sai na transição: concluir o que já estava concluído não repete o registro.\n\n`agentId: null` tira o responsável da tarefa — é a única forma de limpá-lo. O criador não é alterável e por isso não existe neste corpo.\n\n`title`, `completed` e `groupTitle` continuam obrigatórios no RESULTADO do patch: mandá-los como `null` explícito é `422 validation_failed` com `required`, e o valor atual não é apagado. `position` não é editável aqui (use `move`), e enviá-la é `unknown_field`.\n\nTransformar a tarefa em **título de grupo** exige limpar o que não se aplica na mesma requisição: `{\"groupTitle\": true, \"deadline\": null, \"agentId\": null, \"description\": null}`. Mandar só `groupTitle: true` numa tarefa que tem prazo, responsável ou descrição responde `422 validation_failed` com `not_applicable` em cada campo que seria perdido — o produto os descartaria sem avisar.\n\nEditar tarefa é permitido em ticket concluído ou fechado.",
        "operationId" : "updateTicketTask",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da tarefa",
            "example" : 512,
            "in" : "path",
            "name" : "taskId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "agentId" : 42,
                "completed" : true
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketTaskPatchInput"
              }
            },
            "application/merge-patch+json" : {
              "example" : {
                "agentId" : 42,
                "completed" : true
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketTaskPatchInput"
              }
            }
          },
          "description" : "Campos a alterar na tarefa",
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "completed" : false,
                  "createdAt" : "2026-01-10T12:30:00Z",
                  "createdById" : 42,
                  "deadline" : "2026-01-12T09:30:00",
                  "description" : "Conferir se o job noturno terminou sem erro.",
                  "groupTitle" : false,
                  "id" : 512,
                  "position" : 200,
                  "title" : "Validar o backup do servidor",
                  "updatedAt" : "2026-01-10T12:30:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketTask"
                }
              }
            },
            "description" : "A tarefa alterada",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Recurso inexistente, de outra empresa, ou rota inexistente",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: campo obrigatório nulo, campo desconhecido, ou campo que não se aplica a um título de grupo",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Altera uma tarefa do ticket",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    },
    "/v1/tickets/{ticketId}/tasks/{taskId}/move" : {
      "post" : {
        "description" : "Escopo exigido: `tickets:write`. Move a tarefa para entre duas vizinhas, e devolve a tarefa **relida** com a posição que ficou gravada. A posição não é escolhida pelo integrador: o produto pode reescrever a de todas as tarefas do ticket para abrir espaço, e o valor da resposta é o do banco depois disso.\n\nO mapeamento é o da leitura, não o da tela: `afterTaskId` é a tarefa que fica **antes** desta na lista (logo **acima**) e `beforeTaskId` é a que fica **depois** (logo **abaixo**). Numa lista `A, B, C`, mover `C` com `{\"afterTaskId\": A, \"beforeTaskId\": B}` resulta em `A, C, B`.\n\nBasta uma âncora: só `afterTaskId` põe a tarefa logo depois dela, e só `beforeTaskId`, logo antes — a outra vizinha é a que está ao lado da âncora hoje. Para levar ao topo, envie só `beforeTaskId` com a primeira tarefa; ao fim, só `afterTaskId` com a última. Os dois nulos não dizem para onde mover: a resposta é `422 validation_failed` com `required` em `afterTaskId`. Com as duas, elas precisam ser vizinhas e nessa ordem; as duas iguais, a própria tarefa como âncora, âncoras invertidas ou com outra tarefa entre elas respondem `422 validation_failed` com `inconsistent_reference` no campo, e nada muda. Uma âncora que pertença a outro ticket responde `404 not_found` no campo que a enviou.\n\nNenhum parâmetro de consulta é aceito.",
        "operationId" : "moveTicketTask",
        "parameters" : [
          {
            "description" : "ID do ticket",
            "example" : 1,
            "in" : "path",
            "name" : "ticketId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "ID da tarefa",
            "example" : 512,
            "in" : "path",
            "name" : "taskId",
            "required" : true,
            "schema" : {
              "format" : "int64",
              "type" : "integer"
            }
          },
          {
            "description" : "Garante que repetir a mesma requisição não duplique o efeito. 1 a 255 caracteres ASCII visíveis. Repetir a mesma chave devolve a mesma resposta (cabeçalho `Idempotent-Replayed: true`); a mesma chave com um corpo diferente é `422 idempotency_key_reused`. A resposta repetida é a original: o corpo mantém o `requestId` e o idioma da primeira requisição; o cabeçalho `X-Request-Id` é o da requisição nova. A repetição também consome o limite de uso.",
            "in" : "header",
            "name" : "Idempotency-Key",
            "required" : false,
            "schema" : {
              "maxLength" : 255,
              "type" : "string"
            }
          }
        ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "afterTaskId" : 511,
                "beforeTaskId" : 513
              },
              "schema" : {
                "$ref" : "#/components/schemas/PublicTicketTaskMoveInput"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "agentId" : 42,
                  "completed" : false,
                  "createdAt" : "2026-01-10T12:30:00Z",
                  "createdById" : 42,
                  "deadline" : "2026-01-12T09:30:00",
                  "description" : "Conferir se o job noturno terminou sem erro.",
                  "groupTitle" : false,
                  "id" : 512,
                  "position" : 200,
                  "title" : "Validar o backup do servidor",
                  "updatedAt" : "2026-01-10T12:30:00Z"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PublicTicketTask"
                }
              }
            },
            "description" : "A tarefa com a posição nova",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Requisição malformada ou parâmetros de consulta inválidos",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Chave de API ausente, inválida, revogada ou expirada"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Acesso negado: empresa inativa (`account_inactive`), API pública desabilitada para a empresa (`public_api_disabled`), escopo liberado só com a API pública (`scope_requires_public_api`) ou escopo insuficiente (`insufficient_scope`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`not_found`: o ticket, a tarefa ou uma das âncoras não pertence a este ticket",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Conflito — unicidade, recurso em uso, ou Idempotency-Key em execução",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "413" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Corpo da requisição acima de 1 MB",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "415" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Content-Type não suportado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`validation_failed`: nenhuma âncora (`required`), ou âncoras incoerentes (`inconsistent_reference`)",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Limite de uso atingido (`rate_limited`); o campo `layer` indica a camada: `ip`, `company`, `key`, `operation` ou `concurrency`",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              },
              "Retry-After" : {
                "$ref" : "#/components/headers/Retry-After"
              }
            }
          },
          "500" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "Erro interno inesperado",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          },
          "503" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Problem"
                }
              }
            },
            "description" : "`idempotency_unavailable`: Redis indisponível para avaliar o cabeçalho Idempotency-Key presente na requisição.",
            "headers" : {
              "RateLimit-Limit" : {
                "$ref" : "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining" : {
                "$ref" : "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset" : {
                "$ref" : "#/components/headers/RateLimit-Reset"
              }
            }
          }
        },
        "summary" : "Reordena uma tarefa do ticket",
        "tags" : [
          "Tarefas do ticket"
        ],
        "x-required-scope" : "tickets:write"
      }
    }
  },
  "security" : [
    {
      "bearer" : [ ]
    }
  ],
  "servers" : [
    {
      "url" : "https://public-api.mspdesk.com.br"
    }
  ],
  "tags" : [
    {
      "description" : "Tarefas de um ticket: a lista de afazeres que o atendimento vai marcando. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`, e uma tarefa que não pertence ao ticket da rota responde o mesmo.\n\n`agentId` é obrigatório ao criar (avulsa ou por modelo): ele é ao mesmo tempo o **criador** e o **responsável** da tarefa. O criador não é opcional no produto — é parte da chave da tabela —, e a chave de API não é uma pessoa, então quem escolhe o agente é o integrador. A escrita continua nascendo com origem `API` e guardando o identificador da chave no histórico do ticket.\n\nLer continua permitido em ticket na lixeira; escrever, não (`422 ticket_deleted`). Em ticket concluído ou fechado **todas** as operações de tarefa continuam permitidas, como na tela: a aba de tarefas é a única que o produto não tranca no encerramento.\n\nUma linha pode ser um **título de grupo** (`groupTitle: true`): um separador que organiza as tarefas abaixo dele. Um título de grupo não tem prazo, responsável, descrição nem conclusão, e enviar qualquer um desses campos junto dele responde `422 validation_failed` com `not_applicable` — o produto os descartaria em silêncio, e esta API prefere recusar a devolver um estado diferente do que foi pedido.\n\n`deadline` **não tem fuso**: é um valor de parede, como o agente o digita. Quem carrega instante de verdade são `createdAt` e `updatedAt`, carimbos do servidor — e eles são nulos em tarefa anterior a esta API, que nunca recebeu carga retroativa.",
      "name" : "Tarefas do ticket"
    },
    {
      "description" : "Arquivos anexados a um ticket: o que a aba Anexos mostra, mais o envio e a exclusão. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`, e um anexo que não pertence ao ticket da rota responde o mesmo.\n\nUm anexo pode estar **solto** no ticket, preso a uma **nota** ou preso a um **apontamento** — um escopo só, nunca dois. É a única rota desta API que recebe `multipart/form-data`, e por isso a única cujo corpo pode passar de 1 MB.\n\nLer continua permitido em ticket na lixeira; escrever, não (`422 ticket_deleted`). Em ticket **concluído ou fechado**, enviar e excluir anexo respondem `422 ticket_not_editable`: na tela as duas operações exigem a permissão de editar ticket fechado, que uma chave de API não tem como receber. A saída é reabrir o ticket.\n\nO anexo é **imutável**: não há `PATCH`. Trocar o arquivo é excluir e enviar de novo.",
      "name" : "Anexos do ticket"
    },
    {
      "description" : "Notas, respostas e encaminhamentos registrados em um ticket. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`, e uma nota que não pertence ao ticket da rota responde o mesmo.\n\nToda nota escrita por aqui nasce com origem `API` e guarda o identificador da chave usada, que voltam em `origin` e `apiKeyId`. O autor humano é opcional: com `agentId` a nota é assinada por aquele agente — e só assim ela dispara a automação de fluxo por comentário de agente; sem ele a nota fica sem autor, como as automáticas.\n\nLer continua permitido em ticket na lixeira; escrever, não (`422 ticket_deleted`). Em ticket concluído ou fechado, criar nota segue a regra do produto, mas editar e excluir respondem `422 ticket_not_editable` — a chave não tem como ganhar a permissão de editar ticket encerrado.\n\n`GET /v1/tickets/{ticketId}/message-templates/{templateId}` fica nesta aba porque é o que prepara o corpo de uma nota, de uma resposta ou de um encaminhamento: ele devolve o texto do modelo com os placeholders já trocados pelos dados do ticket, e só isso — o produto não tem assunto no modelo nem anexa os arquivos dele.",
      "name" : "Notas do ticket"
    },
    {
      "description" : "Colunas, contagem e execução dos relatórios personalizados criados em Relatórios no MSP Desk. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.",
      "name" : "Relatórios"
    },
    {
      "description" : "Tags que podem ser aplicadas a tickets, artigos da base de conhecimento, clientes e contatos. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.",
      "name" : "Tags"
    },
    {
      "description" : "Produtos e serviços lançados em um ticket: o que a aba Itens mostra, mais lançar, editar e excluir. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`.\n\n**O preço é o do momento do lançamento.** O item copia e trava o preço do produto quando nasce, e `totalPrice` é `quantity × unitPrice`. Mudar o catálogo depois não mexe em item nenhum já lançado — é o que torna a fatura reproduzível.\n\n**Item que já entrou em uma fatura só se edita pela fatura.** Enquanto `invoiceId` for nulo, o `PATCH` e o `DELETE` desta aba valem; a partir do momento em que o item está em uma fatura, os dois respondem `422 business_rule_violation` dizendo para editá-lo pela fatura. Para listar só o que ainda se edita por aqui: `filter[invoiceId][isNull]=true`.\n\n**Lançar** continua permitido em ticket concluído ou fechado, como na tela; **editar** e **excluir** respondem `422 ticket_not_editable` nesse estado. Em ticket na lixeira, ler continua permitido e toda escrita responde `422 ticket_deleted`.",
      "name" : "Itens faturáveis do ticket"
    },
    {
      "description" : "Agentes que acompanham um ticket: o que a aba Seguidores mostra, mais adicionar e remover. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`.\n\nO seguidor **não tem id próprio**: a chave do vínculo é o par (ticket, agente), e dentro de um ticket o `agentId` identifica o seguidor sozinho — é ele que vai na rota de remoção e é por ele que a listagem ordena e pagina.\n\nO vínculo **não é editável**: não há `PATCH`. Ele existe ou não existe, e por isso as duas escritas são idempotentes — adicionar quem já segue devolve `201` com o mesmo corpo, e remover quem não segue devolve `204`.\n\nSeguir continua permitido em ticket **concluído ou fechado**, como na tela. Em ticket na lixeira, ler continua permitido e escrever responde `422 ticket_deleted`.\n\nNão há rota de agentes elegíveis: ela depende de um agente logado para decidir elegibilidade, e uma chave de API não é uma pessoa. Um agente que não alcança o ticket é recusado na adição, com a mensagem da regra.",
      "name" : "Seguidores do ticket"
    },
    {
      "description" : "Apontamentos de um ticket: as horas de atendimento registradas por um agente. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`, e um apontamento que não pertence ao ticket da rota responde o mesmo.\n\n`agentId` é obrigatório na criação: o apontamento é hora de trabalho de alguém, e é por ele que o total por agente e os relatórios de desempenho somam. A escrita continua nascendo com origem `API` e guardando o identificador da chave no histórico do ticket.\n\nLer continua permitido em ticket na lixeira; escrever, não (`422 ticket_deleted`). Em ticket concluído ou fechado, **criar** apontamento é permitido — é assim que o agente lança a hora que trabalhou depois do encerramento —, mas editar e excluir respondem `422 ticket_not_editable`, porque a chave não tem como ganhar a permissão de editar ticket encerrado.\n\nAs datas e horas do apontamento (`date`, `startTime`, `endTime`, `timeSpent`) **não têm fuso**: são valores de parede, como o agente os digita. Quem carrega instante de verdade são `createdAt` e `updatedAt`, carimbos do servidor — e eles são nulos em apontamento anterior a esta API, que nunca recebeu carga retroativa.",
      "name" : "Apontamentos do ticket"
    },
    {
      "description" : "O que aconteceu em um ticket: a linha do tempo da aba Atividades e os alertas de RMM vinculados a ele. As duas rotas são somente de leitura — o histórico é escrito pelas operações que o produzem, e os alertas pelas integrações. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`. Ler o histórico e os alertas de um ticket na lixeira continua permitido.\n\n**A origem dos alertas é escolhida pela integração ativa da empresa**, Datto RMM ou NinjaRMM, e nunca vêm misturadas: o campo `source` diz qual é. Cada origem tem campos que a outra não tem, e a `description` de cada um desses campos diz em qual origem ele existe e que na outra ele vem nulo.\n\n**A chave enxerga o ticket inteiro.** A tela recorta o histórico pela carteira e pelos grupos de serviço do agente; uma chave de API não é um agente e vale para a empresa toda, então a única restrição aqui é o ticket da rota.",
      "name" : "Atividades e alertas do ticket"
    },
    {
      "description" : "Tickets da empresa da chave. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\n## Escrita e ações\n\nCriar, alterar e acionar um ticket ficam registrados na linha do tempo dele como feitos pela integração: a origem é `API` e o autor é o nome da chave usada — nenhuma escrita da API tem usuário do produto por trás. As notificações e as automações disparam exatamente como quando a mesma ação é feita na tela do produto.\n\nNenhuma operação de escrita aceita parâmetros de consulta: tudo vai no corpo. A única exceção é o `DELETE`, que não tem corpo e recebe `associationStrategy` e `cancelOpenInvoices` na URL. Um parâmetro a mais numa escrita é `400 invalid_query`.\n\nToda escrita e toda ação devolvem o ticket inteiro, lido depois de gravar — o mesmo corpo do `GET /v1/tickets/{id}`, sem precisar de uma leitura extra. Duas ressalvas sobre esse corpo:\n\n- `lastActivityAt` é atualizado fora da transação da escrita e pode voltar com o valor anterior por alguns milissegundos. Quem depende dele relê o ticket em seguida.\n- Aviso de automação não aparece na resposta. Uma automação de etapa que não pôde rodar (por exemplo, a que atribui o ticket a um agente que não é mais do grupo) não impede a ação: a resposta continua `200` e o aviso fica na linha do tempo do ticket, como registro do tipo `AUTOMATION`. Quem precisa auditar isso lê a linha do tempo.\n\nCorpo inválido em um ticket que está na lixeira: as duas respostas são `422`, mas a ordem de verificação muda conforme a ação. `start`, `pause`, `end-appointment`, `stage`, `sla-pause` e `merge` validam o corpo primeiro e respondem `validation_failed`; `workflow` verifica a lixeira primeiro e responde `ticket_deleted`. Campo desconhecido no corpo é recusado antes de tudo, em qualquer ação.",
      "name" : "Tickets"
    },
    {
      "description" : "Conversas do MSP Talks vinculadas a um ticket: o que a aba Chat mostra, mais vincular, trocar a conversa principal, desvincular, anotar no atendimento e iniciar uma conversa. Toda requisição exige o cabeçalho `Authorization: Bearer <chave de API>`.\n\nO ticket da rota é sempre resolvido na empresa da chave antes de qualquer outra verificação: um ticket de outra empresa, ou inexistente, responde `404 not_found`.\n\n**As escritas falam com o MSP Talks dentro da requisição.** Vincular confirma a conversa do outro lado antes de gravar, anotar escreve na conversa e iniciar manda a mensagem. Três consequências: a latência é a do fornecedor; a integração precisa estar configurada e ativa na empresa, senão a operação responde `422 business_rule_violation` (é condição permanente — ligar a integração resolve, repetir não); e uma falha do próprio fornecedor responde `503 service_unavailable`, o único erro destas rotas que vale repetir.\n\n**Iniciar conversa custa dinheiro** (a Meta cobra por conversa iniciada), e por isso a rota nunca responde erro depois de a mensagem ter saído: se o envio foi aceito e o resto falhar, a resposta é `202`. Use `Idempotency-Key` — a repetição devolve a resposta original, `201` ou `202`, sem mandar uma segunda mensagem.\n\nQuem age vai **explícito** em `agentId` ao vincular e ao iniciar: o vínculo registra quem o criou, e uma chave de API não é uma pessoa. Trocar a principal, desvincular e anotar não têm ator — nem na tela.\n\nVincular a mesma conversa a **dois tickets é permitido** (um atendimento longo vira dois chamados): a resposta do vínculo traz `alsoLinkedToTicketId` como aviso, não como erro.\n\nEscrever continua permitido em ticket **concluído ou fechado**, como na tela. Em ticket na lixeira, ler continua permitido e escrever responde `422 ticket_deleted`.\n\nNão há busca de conversas candidatas, abertura da conversa no navegador nem resumo por IA: a primeira é consulta ao diretório da conta do MSP Talks (o integrador já conhece o `sessionId`), a segunda devolve um endereço autenticado que só faz sentido dentro da tela, e a API pública não publica rota de IA.",
      "name" : "Chat do ticket"
    }
  ]
}
