Atualizar Ticket
Endpoint para atualizar campos de tickets e movê-los entre estágios do pipeline
Visão Geral
O endpoint /api/externalAPIs/public/tickets/updateTicket permite atualizar campos de tickets existentes e movê-los entre diferentes estágios do pipeline, com rastreamento automático de eventos de auditoria.
Este endpoint suporta duas operações: atualização de campos OU movimentação de estágio, ou ambas combinadas. A movimentação é executada após a atualização quando ambas são solicitadas.
Características Principais
- Operações Flexíveis: Atualização de campos, movimentação de estágio, ou ambas
 - Campos Completos: Todos os campos do ticket podem ser atualizados
 - Movimentação Inteligente: Move tickets entre estágios com rastreamento de motivos
 - Eventos Automáticos: Cria automaticamente eventos de auditoria para todas as mudanças
 - Integração HubSpot: Sincroniza estágios quando habilitado
 
Casos de Uso
- Atualizar informações do ticket durante o progresso do workflow
 - Mover tickets entre estágios do pipeline
 - Atribuir tickets a usuários específicos
 - Fechar/abrir tickets com documentação adequada
 - Operações automatizadas com workflows
 
Endpoint
POST /api/externalAPIs/public/tickets/updateTicket
Autenticação
- Header: 
Authorization: Bearer <token> - Content-Type: 
application/json - Middleware: 
tolkyAuthMiddleware(injetahostId/hostSlugautomaticamente) 
Parâmetros
Obrigatórios
| Parâmetro | Tipo | Descrição | 
|---|---|---|
ticketId | string (UUID) | ID único do ticket a ser atualizado | 
Campos de Atualização (Opcionais)
| Parâmetro | Tipo | Descrição | 
|---|---|---|
subject | string | Assunto do ticket | 
description | string | Descrição detalhada do problema | 
definitionOfDone | string | Definição de pronto (DOD) | 
status | object | Status do ticket | 
status.label | string | Nome do status | 
status.level | number | Nível numérico do status | 
status.tickets_levels_id | string (UUID) | ID do nível (preferencial) | 
importance | object | Importância do ticket | 
importance.importance_level | number | Nível de importância (1=baixa, 4=urgente) | 
importance.importance_label | string | Label da importância | 
assignedUser | object | Usuário responsável | 
assignedUser.hostPeopleId | string (UUID) | ID do usuário no host | 
assignedUser.name | string | Nome do usuário (opcional, para histórico) | 
closed | boolean | Status de fechamento do ticket | 
Campos de Movimentação (Opcionais)
| Parâmetro | Tipo | Descrição | 
|---|---|---|
newLevel | string | UUID | Nome/nível ou ID do nível de destino | 
reason | string | Motivo da movimentação (cria evento “Motivo”) | 
conversationId | string (UUID) | ID da conversa (para eventos no chat) | 
isAutomaticMove | boolean | Indica se é movimentação automática (default: false) | 
Contexto/Segurança (Opcionais)
| Parâmetro | Tipo | Descrição | 
|---|---|---|
authUserId | string (UUID) | ID do usuário autenticado (para vincular eventos) | 
globalData | object | Contexto adicional da requisição | 
Regras de Negócio
- Obrigatório: 
ticketIddeve ser fornecido - Operação Mínima: Pelo menos uma operação (atualização OU movimentação)
 - Ordem de Execução: Se ambas operações forem solicitadas, a atualização é executada primeiro, depois a movimentação
 - Permissões: Respeita permissões do host via 
tolkyAuthMiddleware - Prioridade de Nível: 
status.tickets_levels_idé preferencial para trocar status 
Exemplos de Requisição
Apenas Atualização
{
  "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
  "subject": "Atualizar orçamento",
  "description": "Cliente solicitou revisão do escopo",
  "importance": { 
    "importance_level": 3, 
    "importance_label": "Alta" 
  },
  "assignedUser": { 
    "hostPeopleId": "4a6b9f6e-0f2f-4e2b-9a77-98b0d64c4d11" 
  }
}
Apenas Movimentação
{
  "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
  "newLevel": "3fb2a9f0-5aa3-4f6d-8d37-c2a0b1d7b9a2",
  "reason": "Aprovado pelo gerente",
  "isAutomaticMove": false
}
Atualização + Movimentação
{
  "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
  "subject": "Orçamento aprovado",
  "newLevel": "Concluído",
  "reason": "Entregue ao cliente",
  "authUserId": "d7b5d8a9-3f4c-4ed3-9c77-22f577d25f10"
}
Atualização de Status com ID Específico
{
  "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
  "status": {
    "label": "Em Progresso",
    "level": 2,
    "tickets_levels_id": "3fb2a9f0-5aa3-4f6d-8d37-c2a0b1d7b9a2"
  },
  "closed": false
}
Resposta de Sucesso
{
  "success": true,
  "message": "Ticket updated and moved successfully",
  "data": {
    "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
    "operationsPerformed": { 
      "updated": true, 
      "moved": true 
    },
    "updateResult": {
      "id": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
      "protocol": "ABCD-1234",
      "subject": "Orçamento aprovado",
      "description": "Cliente solicitou revisão do escopo",
      "status": {
        "name": "Em Progresso",
        "level": 2,
        "color": "#F6AD55",
        "isClosed": false
      },
      "importance": 3,
      "importanceColor": "#F6AD55",
      "assignedUser": {
        "id": "4a6b9f6e-0f2f-4e2b-9a77-98b0d64c4d11",
        "name": "João Silva"
      }
    },
    "moveResult": {
      "data": {
        "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
        "previousLevel": { 
          "name": "Em Progresso", 
          "level": 2, 
          "id": "3fb2a9f0-5aa3-4f6d-8d37-c2a0b1d7b9a2" 
        },
        "newLevel": { 
          "name": "Concluído", 
          "level": 3, 
          "id": "4fb2a9f0-5aa3-4f6d-8d37-c2a0b1d7b9a3",
          "color": "#68D391", 
          "external_id": "completed" 
        },
        "updatedTicket": { ...registro completo do ticket... }
      }
    },
    "finalTicketState": { ...estado final do ticket... }
  }
}
Códigos de Erro
| Código | Erro | Descrição | Solução | 
|---|---|---|---|
400 | MissingTicketId | Ticket ID não fornecido | Incluir ticketId na requisição | 
400 | NoOperationSpecified | Nenhuma operação especificada | Fornecer pelo menos um campo para atualizar ou newLevel | 
403 | Invalid credentials | Credenciais inválidas | Verificar token de autenticação | 
500 | UpdateTicketError | Erro na atualização | Contatar suporte técnico | 
500 | MoveTicketError | Erro na movimentação | Contatar suporte técnico | 
Exemplo com cURL
curl -X POST "$BASE_URL/api/externalAPIs/public/tickets/updateTicket" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ticketId": "b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a",
    "newLevel": "Concluído",
    "reason": "Entregue ao cliente"
  }'
Exemplo de Integração Completa
class TicketUpdater {
  constructor(apiToken, baseUrl) {
    this.apiToken = apiToken;
    this.baseUrl = baseUrl;
  }
  async updateTicket(ticketId, updates) {
    try {
      const response = await fetch(`${this.baseUrl}/api/externalAPIs/public/tickets/updateTicket`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${this.apiToken}`
        },
        body: JSON.stringify({
          ticketId,
          ...updates
        })
      });
      if (!response.ok) {
        const error = await response.json();
        throw new Error(`Erro ${response.status}: ${error.message}`);
      }
      return await response.json();
    } catch (error) {
      console.error('Erro ao atualizar ticket:', error);
      throw error;
    }
  }
  // Atualizar apenas campos
  async updateFields(ticketId, fields) {
    return await this.updateTicket(ticketId, fields);
  }
  // Mover apenas estágio
  async moveToLevel(ticketId, newLevel, reason, isAutomatic = false) {
    return await this.updateTicket(ticketId, {
      newLevel,
      reason,
      isAutomaticMove: isAutomatic
    });
  }
  // Atualizar e mover
  async updateAndMove(ticketId, fields, newLevel, reason) {
    return await this.updateTicket(ticketId, {
      ...fields,
      newLevel,
      reason
    });
  }
  // Fechar ticket
  async closeTicket(ticketId, reason, authUserId) {
    return await this.updateTicket(ticketId, {
      closed: true,
      newLevel: "Concluído",
      reason,
      authUserId
    });
  }
  // Atribuir ticket
  async assignTicket(ticketId, hostPeopleId, userName) {
    return await this.updateTicket(ticketId, {
      assignedUser: {
        hostPeopleId,
        name: userName
      }
    });
  }
}
// Uso da classe
const ticketUpdater = new TicketUpdater('seu_token_aqui', 'https://api.tolky.to');
// Exemplos de uso
async function examples() {
  try {
    // Atualizar apenas campos
    await ticketUpdater.updateFields('b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a', {
      subject: 'Novo assunto',
      importance: { importance_level: 4, importance_label: 'Urgente' }
    });
    // Mover apenas estágio
    await ticketUpdater.moveToLevel('b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a', 'Concluído', 'Aprovado pelo cliente');
    // Atualizar e mover
    await ticketUpdater.updateAndMove('b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a', 
      { subject: 'Orçamento finalizado' }, 
      'Concluído', 
      'Entregue ao cliente'
    );
    // Fechar ticket
    await ticketUpdater.closeTicket('b8c9f8c4-0b6a-4b2a-8f8f-0c9d9e2f5a1a', 'Resolvido', 'd7b5d8a9-3f4c-4ed3-9c77-22f577d25f10');
  } catch (error) {
    console.error('Erro:', error.message);
  }
}
Considerações Importantes
Movimentação de Níveis
newLevelaceita:- UUID de 
tickets_levels.id(preferido) - Nome/nível resolvido por host (fallback)
 
- UUID de 
 status.tickets_levels_idé o caminho preferencial para trocar status
Eventos Automáticos
- Eventos de histórico são criados automaticamente (status, info, motivo se enviado)
 - Eventos são vinculados ao 
authUserIdquando fornecido - Eventos podem ser escritos no chat via 
conversationId 
Integração HubSpot
- Se habilitada no avatar/host, a movimentação sincroniza estágio automaticamente
 - Sincronização ocorre quando aplicável ao estágio de destino
 
Importante: Sempre forneça o ticketId válido. Tentativas de atualização com IDs inexistentes resultarão em erro 404.
Dica: Use status.tickets_levels_id para mudanças de status mais precisas, especialmente em integrações automatizadas.
Nota: A movimentação é executada após a atualização quando ambas operações são solicitadas na mesma requisição.