Órdenes de servicio

Referencia de las ocho rutas de órdenes de servicio de la API de ChatISP: consulte las etapas y los tipos del tablero, liste y siga las OS con la línea de tiempo completa, y abra, mueva, asigne y comente OS desde su ERP, su sistema de monitoreo o el portal del suscriptor.

Visión general

La orden de servicio (OS) es la tarea interna del equipo del proveedor de internet: visita técnica, reparación de red, instalación, ajuste financiero. Vive en el tablero de Órdenes de servicio del panel, pasa por etapas hasta quedar resuelta o cancelada y puede estar vinculada a una atención de WhatsApp. Por la API, otro sistema ve y opera el mismo tablero, con las mismas reglas del panel: plazo, avisos al equipo, rastro en la atención de origen y webhooks.

Casos típicos de integración:

  • Monitoreo y NOC: el sistema que detecta la caída de un cliente corporativo o de una caja de distribución abre la OS de reparación ya con prioridad, dirección y descripción técnica.
  • ERP: la orden de servicio creada en el ERP se convierte en OS en el tablero del equipo, y la conclusión en ChatISP vuelve al ERP por el webhook.
  • Equipo de campo: la aplicación del técnico mueve la OS a la etapa de ejecución, comenta lo realizado y la marca como resuelta.
  • Panel propio y BI: listado de atrasadas, OS por responsable y sincronización incremental por la marca de actualización.

Rutas

RutaMétodoPermiso de la claveQué hace
tickets/etapasGETConsultar órdenes de servicioEtapas del tablero, con la naturaleza de cada una.
tickets/tiposGETConsultar órdenes de servicioTipos de OS, con prioridad y plazo predeterminados.
tickets/listarGETConsultar órdenes de servicioLista paginada con filtros.
tickets/consultarGETConsultar órdenes de servicioUna OS con toda su línea de tiempo.
tickets/criarPOSTGestionar órdenes de servicioAbre una OS.
tickets/moverPOSTGestionar órdenes de servicioLleva la OS a otra etapa.
tickets/atribuirPOSTGestionar órdenes de servicioDefine o quita el responsable.
tickets/comentarPOSTGestionar órdenes de servicioComenta en la línea de tiempo.

El permiso se marca en la clave, en Integraciones, tarjeta API de ChatISP. Gestionar órdenes de servicio no incluye la lectura: para abrir una OS y después seguirla, marque los dos. La autenticación, el formato de las llamadas, la paginación y los errores comunes a todas las rutas están en la Introducción.

Quién aparece como autor

La clave de API no es un usuario del equipo. Por eso, en las acciones realizadas por la API:

  • La OS abierta por la API nace con origem igual a api y, en la línea de tiempo, recibe un evento de sistema con el texto API: <nombre de la clave>, justo después del evento de apertura.
  • Los comentarios entran con el prefijo [API: <nombre de la clave>] en el texto, para que el equipo sepa de dónde vinieron.
  • Los cambios de etapa hechos por la API registran en el evento el texto [API: <nombre de la clave>], seguido del comentario cuando lo hay.
  • Los eventos registrados por la API tienen autor_id nulo y autor vacío; el origen queda en el texto.
  • Las notas que la OS deja en la atención vinculada citan la clave como autora (por ejemplo, "movida a la etapa En ejecución por API: ERP").

Dé a la clave un nombre que el equipo reconozca, como ERP, NOC o App de campo. Ese es el nombre que aparece en el tablero, en la línea de tiempo y en la atención.

Visión de toda la empresa

La clave ve todas las OS, de todos los departamentos y responsables. Las reglas de visibilidad de los perfiles de acceso (quién ve solo las OS de su propio equipo) valen para las personas en el panel, no para la API.


El objeto orden de servicio

Todas las rutas que devuelven una OS usan el mismo formato. Fechas en ISO 8601 con zona horaria; un campo sin valor viene como null (fechas, ids) o texto vacío (nombres).

CampoTipoDescripción
identeroIdentificador interno de la OS. Úselo en las llamadas como ticket_id.
numerotextoNúmero que el equipo ve en el tablero, en el formato OS-000128. También sirve para localizar la OS en las llamadas (parámetro numero).
titulotextoTítulo corto, de hasta 160 caracteres.
descricaotextoDescripción libre; vacía cuando no se completó.
tipoobjeto o null{"id", "nome"} del tipo de OS; null cuando la OS no tiene tipo.
etapaobjeto{"id", "nome", "natureza"} de la etapa actual. La naturaleza indica cómo el sistema trata la etapa: vea Naturalezas, prioridades y plazo.
concluidobooleanotrue cuando la etapa actual es final (naturaleza resolvido o cancelado).
prioridadetextobaixa, normal, alta o urgente.
origemtextoDe dónde vino la OS: manual (abierta en el tablero), chat (abierta desde una atención), ia (abierta por la IA), copiloto (abierta por el Copiloto) o api.
conversa_identero o nullAtención vinculada, cuando existe.
protocolotexto o nullProtocolo de la atención vinculada.
clienteobjeto{"telefone", "nome", "endereco"}. Teléfono con código de país, solo dígitos. Los tres pueden venir vacíos en una OS interna, sin cliente.
departamento_id / departamentoentero o null / textoEquipo dueño de la OS.
responsavel_id / responsavelentero o null / textoPersona responsable. null y vacío cuando la OS no tiene responsable.
prazo_emfecha o nullPlazo para resolver. null cuando la OS no tiene plazo.
prazo_situacaotextosem_prazo, ok, atencao, vencido o concluido. Calculado en el momento de la llamada.
resumo_iatexto o nullResumen de la atención vinculada hecho por la IA para quien va a ejecutar la OS. Llega unos instantes después de la apertura; null mientras no existe o cuando no hay atención vinculada.
total_comentariosenteroCantidad de comentarios en la línea de tiempo.
total_anexosenteroCantidad de archivos adjuntados por el equipo.
aberto_emfechaCuándo se abrió la OS.
iniciado_emfecha o nullPrimera vez que la OS entró en una etapa de naturaleza andamento.
resolvido_emfecha o nullCuándo entró en una etapa resolvido.
fechado_emfecha o nullCuándo entró en una etapa final (resuelto o cancelado).
ultima_atividade_emfechaÚltimo registro en la línea de tiempo (apertura, etapa, comentario, adjunto, edición, resumen). Es el campo que usa el filtro atualizados_desde y el orden del listado.
erpobjeto o nullLa OS en el ERP del proveedor (vea En el ERP del proveedor en la documentación del sistema). null cuando la OS no tiene cliente del ERP vinculado ni registro en ningún ERP. Trae erp_id (ERP del cliente vinculado, o null), id_externo_cliente e id_externo_contrato (identificadores del cliente y del contrato en el ERP, texto o null) y ordens, la lista de las OS abiertas en el ERP para esta OS: cero o una por ERP, con los campos de la tabla siguiente.

Campos de erp.ordens[]

CampoTipoDescripción
erp_id / erpentero / textoIdentificador y nombre del ERP, como está registrado en Integraciones.
tipo_erptextoixc, hubsoft, sgp, gesprov o pipesoft.
idtextoIdentificador interno de la OS en el ERP.
numerotextoNúmero de la OS tal como el ERP lo muestra al equipo de allá.
protocolotexto o nullProtocolo de la ocurrencia o del "chamado", en los ERPs que trabajan con protocolo además del número.
situacaotextoSituación en el vocabulario común de ChatISP: aberta, em_analise, agendada, em_execucao, aguardando, concluida o desconhecida (el ERP devolvió algo que ChatISP no reconoce).
situacao_erptexto o nullLa situación cruda, tal como la llama el ERP.
tecnicotexto o nullTécnico asignado en el ERP, cuando se informa.
agendado_em / concluido_emfecha o nullAgendamiento y conclusión leídos del ERP.
reaproveitadabooleanotrue cuando la OS de aquí se ligó a una OS que ya estaba abierta en el ERP para el mismo cliente y tipo, en vez de abrir otra.
acompanhabooleanotrue cuando ChatISP consulta el ERP periódicamente y concluye la OS de aquí cuando el ERP la concluye; false en Gesprov, que solo permite abrir.
ultima_consulta_emfecha o nullÚltima consulta al ERP con éxito.
JSON (objeto orden de servicio)
{
  "id": 128,
  "numero": "OS-000128",
  "titulo": "Sin señal en la Rua das Palmeiras",
  "descricao": "ONU sin luz PON desde las 09:40. La clienta informa que el vecino también está sin internet.",
  "tipo": {"id": 2, "nome": "Reparación de red"},
  "etapa": {"id": 1, "nome": "Abierto", "natureza": "inicial"},
  "concluido": false,
  "prioridade": "urgente",
  "origem": "api",
  "conversa_id": 5310,
  "protocolo": "20261001-0042",
  "cliente": {
    "telefone": "5544999990000",
    "nome": "Maria Souza",
    "endereco": "Rua das Palmeiras, 120, Centro"
  },
  "departamento_id": 3,
  "departamento": "Soporte técnico",
  "responsavel_id": null,
  "responsavel": "",
  "prazo_em": "2026-10-01T18:15:00-03:00",
  "prazo_situacao": "ok",
  "resumo_ia": null,
  "total_comentarios": 0,
  "total_anexos": 0,
  "erp": {
    "erp_id": 1,
    "id_externo_cliente": "8841",
    "id_externo_contrato": "9120",
    "ordens": [
      {
        "erp_id": 1,
        "erp": "IXC Provedor",
        "tipo_erp": "ixc",
        "id": "4521",
        "numero": "4521",
        "protocolo": null,
        "situacao": "aberta",
        "situacao_erp": "A",
        "tecnico": null,
        "agendado_em": null,
        "concluido_em": null,
        "reaproveitada": false,
        "acompanha": true,
        "ultima_consulta_em": "2026-10-01T10:15:05-03:00"
      }
    ]
  },
  "aberto_em": "2026-10-01T10:15:00-03:00",
  "iniciado_em": null,
  "resolvido_em": null,
  "fechado_em": null,
  "ultima_atividade_em": "2026-10-01T10:15:00-03:00"
}

Naturalezas, prioridades y plazo

Las etapas del tablero tienen nombre y color libres, configurados por cada proveedor. Lo que el sistema entiende de cada una es la naturaleza. Integre siempre por la naturaleza, nunca por el nombre: "Resuelto" en un proveedor puede ser "Finalizado" en otro.

Naturalezas de etapa

NaturalezaEtiqueta en el panelQué hace el sistema
inicialInicial (entrada)Donde nace la OS. La OS nueva entra en la primera etapa activa de naturaleza inicial (según el orden del tablero); si no hay ninguna, en la primera etapa activa.
andamentoEn cursoLa primera entrada en una etapa así registra iniciado_em.
aguardandoEsperando a tercerosOS detenida a la espera de algo externo (cliente, proveedor). El plazo sigue corriendo.
resolvidoFinal: resueltoEtapa final: registra resolvido_em y fechado_em, detiene el plazo y avisa a quien abrió la OS.
canceladoFinal: canceladoEtapa final: registra fechado_em, detiene el plazo y avisa a quien abrió la OS.

Sacar una OS de una etapa final hacia una etapa no final es una reapertura: resolvido_em y fechado_em vuelven a null, el plazo vuelve a correr y la línea de tiempo registra un evento reaberto.

Prioridades

ValorEtiqueta en el panel
baixaBaja
normalNormal
altaAlta
urgenteUrgente

En la apertura sin prioridade, vale la prioridad predeterminada del tipo; sin tipo, normal.

Situación del plazo

prazo_situacaoCuándo
sem_prazoOS abierta sin plazo definido.
okPlazo en el futuro, con margen.
atencaoFaltan 2 horas o menos, o menos del 25% del tiempo total entre la apertura y el plazo.
vencidoEl plazo pasó y la OS no está en una etapa final.
concluidoLa OS está en una etapa final: el plazo dejó de correr.

Cuando el plazo vence con la OS aún abierta, el sistema registra una única vez el evento de sistema "Plazo vencido sin conclusión." en la línea de tiempo y avisa por WhatsApp al responsable (o al equipo del departamento, si la OS no tiene responsable). Ese evento actualiza ultima_atividade_em.


Etapas del tablero

GET/api_publica.php?r=tickets/etapas

Devuelve todas las etapas del tablero, en el orden de las columnas, incluidas las desactivadas. Sin parámetros. Úsela para descubrir el etapa_id que pide tickets/mover, eligiendo siempre por la natureza.

Campo de etapas[]Descripción
idIdentificador de la etapa.
nomeNombre de la columna en el tablero.
naturezainicial, andamento, aguardando, resolvido o cancelado.
corColor de la columna en hexadecimal.
ativafalse cuando la etapa fue desactivada. Una etapa desactivada no acepta OS nuevas ni movimientos.
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=tickets/etapas"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'tickets/etapas',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/etapas"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "etapas": [
    {"id": 1, "nome": "Abierto", "natureza": "inicial", "cor": "#38bdf8", "ativa": true},
    {"id": 2, "nome": "En análisis", "natureza": "andamento", "cor": "#8b5cf6", "ativa": true},
    {"id": 3, "nome": "En ejecución", "natureza": "andamento", "cor": "#f59e0b", "ativa": true},
    {"id": 4, "nome": "Esperando al cliente", "natureza": "aguardando", "cor": "#64748b", "ativa": true},
    {"id": 5, "nome": "Resuelto", "natureza": "resolvido", "cor": "#10b981", "ativa": true},
    {"id": 6, "nome": "Cancelado", "natureza": "cancelado", "cor": "#d23939", "ativa": true}
  ]
}

Los ids cambian de una instalación a otra y el proveedor puede crear, renombrar y reordenar etapas. Guárdelos en caché por algunas horas y vuelva a consultar si recibe etapa_invalida.


Tipos de OS

GET/api_publica.php?r=tickets/tipos

Devuelve los tipos de OS registrados en la Configuración del módulo, incluidos los desactivados. Sin parámetros. El tipo define la prioridad, el plazo y el equipo que recibe la OS cuando la llamada de apertura no informa esos campos.

Campo de tipos[]Descripción
idIdentificador del tipo, usado en tipo_id.
nomeNombre del tipo.
ativofalse cuando está desactivado. Un tipo desactivado se rechaza en la apertura (tipo_invalido).
prioridade_padraoPrioridad aplicada cuando la apertura no informa una.
prazo_horasHoras hasta el plazo, contadas desde la apertura. 0 significa sin plazo automático.
departamento_idEquipo que recibe la OS cuando la apertura no informa departamento_id; null si el tipo no tiene equipo.
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=tickets/tipos"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'tickets/tipos',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/tipos"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "tipos": [
    {"id": 1, "nome": "Visita técnica", "ativo": true, "prioridade_padrao": "alta", "prazo_horas": 24, "departamento_id": 3},
    {"id": 2, "nome": "Reparación de red", "ativo": true, "prioridade_padrao": "urgente", "prazo_horas": 8, "departamento_id": 3},
    {"id": 3, "nome": "Instalación", "ativo": true, "prioridade_padrao": "normal", "prazo_horas": 48, "departamento_id": null},
    {"id": 4, "nome": "Financiero", "ativo": true, "prioridade_padrao": "normal", "prazo_horas": 24, "departamento_id": 2},
    {"id": 5, "nome": "Otro", "ativo": true, "prioridade_padrao": "normal", "prazo_horas": 24, "departamento_id": null}
  ]
}

Listar órdenes de servicio

GET/api_publica.php?r=tickets/listar

Lista paginada de OS, de la movida más recientemente a la más antigua (orden de ultima_atividade_em). Todos los filtros son opcionales y se combinan (todos deben cumplirse al mismo tiempo). Sin filtro, vienen todas las OS, abiertas y concluidas.

ParámetroTipoDescripción
situacaotextotodos (predeterminado), abertos (etapa no final) o concluidos (resueltos y cancelados).
etapa_identeroSolo las OS de esa etapa.
tipo_identeroSolo las de ese tipo.
departamento_identeroSolo las de ese equipo.
conversa_identeroSolo las vinculadas a esa atención.
responsavel_identeroSolo las de esa persona. Con 0, solo las OS sin responsable.
prioridadetextobaixa, normal, alta o urgente.
atrasadosbooleano1 (o true): solo las OS abiertas con plazo vencido.
telefonetextoSolo las del cliente de ese número. Misma regla de teléfono que el resto de la API (sin +, se considera brasileño); el número se busca con y sin el noveno dígito.
abertos_desde / abertos_atefechaRango de la fecha de apertura. Una fecha sin hora en abertos_ate vale hasta las 23:59:59 del día.
atualizados_desdefechaSolo las que tuvieron cualquier registro en la línea de tiempo a partir de ese instante. Base de la sincronización incremental.
buscatextoBusca en el número, título, descripción, nombre del cliente y dirección (hasta 120 caracteres).
pagina / limiteenteroPaginación numerada: limite de 1 a 100 (predeterminado 50).
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=tickets/listar" \
  --data-urlencode "situacao=abertos" \
  --data-urlencode "departamento_id=3" \
  --data-urlencode "atrasados=1" \
  --data-urlencode "limite=20"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'tickets/listar',
    'situacao' => 'abertos',
    'departamento_id' => 3,
    'atrasados' => '1',
    'limite' => 20,
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/listar", "situacao": "abertos", "departamento_id": 3, "atrasados": "1", "limite": 20},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "tickets": [
    {
      "id": 121,
      "numero": "OS-000121",
      "titulo": "Cambio de conector en la CTO 14",
      "etapa": {"id": 3, "nome": "En ejecución", "natureza": "andamento"},
      "concluido": false,
      "prioridade": "alta",
      "responsavel_id": 7,
      "responsavel": "Carlos Lima",
      "prazo_em": "2026-10-01T08:00:00-03:00",
      "prazo_situacao": "vencido",
      "ultima_atividade_em": "2026-10-01T09:12:44-03:00",
      "...": "demás campos del objeto orden de servicio"
    }
  ],
  "paginacao": {"pagina": 1, "limite": 20, "total": 1, "paginas": 1}
}

Sincronización incremental

Para mantener un espejo de las OS en su sistema, guarde el instante de cada ronda y, en la siguiente, pida atualizados_desde con ese instante (de preferencia con algunos minutos de margen, guardando por id para no duplicar). La apertura, el cambio de etapa, el cambio de responsable, el comentario, el adjunto, la edición, el resumen de la IA y el plazo vencido actualizan la marca. La hora exacta del servidor está en servidor.agora de la ruta chave/info.

Si su sistema solo necesita reaccionar cuando algo cambia, el webhook es más eficiente que consultar cada cierto tiempo: los eventos ticket_criado y ticket_atualizado llegan en el momento. Vea Webhooks.


Consultar una OS

GET/api_publica.php?r=tickets/consultar

Devuelve la OS y la línea de tiempo completa, del evento más antiguo al más reciente.

ParámetroTipoObligatorioDescripción
ticket_identerouno de los dosId de la OS (también aceptado como id).
numerotextouno de los dosNúmero de la OS, como OS-000128. Útil cuando el número lo escribió una persona.
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=tickets/consultar" \
  --data-urlencode "numero=OS-000128"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'tickets/consultar',
    'numero' => 'OS-000128',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/consultar", "numero": "OS-000128"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "ticket": {"id": 128, "numero": "OS-000128", "...": "objeto orden de servicio completo"},
  "eventos": [
    {
      "id": 901, "tipo": "aberto", "autor_id": null, "autor": "", "texto": "",
      "dados": {"origem": "api", "etapa": "Abierto"}, "anexos": [],
      "criado_em": "2026-10-01T10:15:00-03:00"
    },
    {
      "id": 902, "tipo": "sistema", "autor_id": null, "autor": "", "texto": "API: NOC",
      "dados": [], "anexos": [], "criado_em": "2026-10-01T10:15:00-03:00"
    },
    {
      "id": 910, "tipo": "responsavel", "autor_id": 4, "autor": "Paula Andrade", "texto": "",
      "dados": {"de": null, "de_nome": "", "para": 7, "para_nome": "Carlos Lima"}, "anexos": [],
      "criado_em": "2026-10-01T10:31:20-03:00"
    },
    {
      "id": 915, "tipo": "etapa", "autor_id": 7, "autor": "Carlos Lima", "texto": "Equipo en camino",
      "dados": {"de": 1, "de_nome": "Abierto", "de_cor": "#38bdf8", "para": 3, "para_nome": "En ejecución",
                "para_cor": "#f59e0b", "natureza": "andamento"},
      "anexos": [], "criado_em": "2026-10-01T10:40:02-03:00"
    },
    {
      "id": 921, "tipo": "comentario", "autor_id": 7, "autor": "Carlos Lima",
      "texto": "Fibra rota en el poste 32. Empalme hecho, señal normalizada.",
      "dados": [], "anexos": [{"nome": "emenda.jpg", "tamanho": 284113}],
      "criado_em": "2026-10-01T12:05:51-03:00"
    }
  ]
}
Campo de eventos[]Descripción
idIdentificador del evento (creciente).
tipoTipo del evento: tabla a continuación.
autor_id / autorQuién lo hizo. null y vacío para el sistema, la IA y las acciones hechas por la API.
textoTexto del comentario, del resumen de la IA, del comentario que acompañó el cambio de etapa o del mensaje de sistema.
dadosDetalles estructurados del evento (objeto); lista vacía cuando no hay.
anexosArchivos adjuntados junto con el evento: {"nome", "tamanho"} (tamaño en bytes). La descarga del adjunto se hace por el panel.
criado_emCuándo ocurrió.

Tipos de evento de la línea de tiempo

tipoCuándo apareceContenido de dados y texto
abertoApertura de la OS.origem y etapa (nombre de la etapa inicial).
responsavelResponsable definido, cambiado o quitado; también cuando alguien del equipo mueve una OS sin responsable a una etapa de trabajo y pasa a ser el responsable.de, de_nome, para, para_nome. para nulo = la OS quedó sin responsable.
etapaCambio de etapa.de, de_nome, de_cor, para, para_nome, para_cor, natureza (de la etapa de destino). El comentario que acompañó el cambio viene en texto.
reabertoSalida de una etapa final hacia una etapa no final.Los mismos campos de etapa.
comentarioComentario del equipo o de la API.Texto en texto; archivos del comentario en anexos.
anexoArchivo adjuntado sin comentario, enviado desde la computadora o traído de la atención.nome del archivo, u origem igual a conversa cuando vino del chat.
tipoTipo de la OS cambiado en el panel.de_nome, para_nome.
prioridadePrioridad cambiada en el panel.de, para.
prazoPlazo cambiado en el panel.de, para, como texto corto de fecha y hora (el formato que muestra la pantalla).
editadoOtros campos editados en el panel (título, descripción, cliente, dirección, equipo).campos (lista de los campos modificados) y detalhe.
iaResumen de la atención vinculada, generado por la IA.Resumen en texto.
erpLo que ocurrió en el ERP del proveedor: apertura, vínculo a una OS que ya existía, falla al abrir, cambio de situación, técnico o agenda, y conclusión.dados.acao (aberta, vinculada, falha, situacao o concluida), dados.erp_nome, dados.os_numero y, según la acción, la situación nueva, el técnico, la agenda o el motivo de la falla (erro y mensagem).
sistemaRegistro automático: la marca API: <nombre de la clave> en la apertura por la API, o "Plazo vencido sin conclusión.".Texto en texto; en el plazo vencido, dados.prazo.

Trate los tipos de evento desconocidos sin romper la integración: pueden surgir tipos nuevos con la evolución del tablero. Muestre el texto cuando exista e ignore el resto.


Abrir una OS

POST/api_publica.php?r=tickets/criar

Abre una OS en la etapa inicial del tablero. Solo el título es obligatorio; el resto completa la OS y, cuando se omite, se llena a partir del tipo o de la atención vinculada.

ParámetroTipoObligatorioDescripción
titulotextosíDe 1 a 160 caracteres.
descricaotextonoHasta 20.000 caracteres. Coloque aquí todo lo que el técnico necesita: síntomas, equipo, señal, referencias de la dirección.
tipo_identeronoTipo de la OS (tickets/tipos). Un tipo inexistente o desactivado devuelve tipo_invalido.
prioridadetextonobaixa, normal, alta o urgente. Sin ella, vale la del tipo; sin tipo, normal.
prazo_emfechanoPlazo explícito. Sin él, el plazo es la apertura más las prazo_horas del tipo (tipo con 0 = sin plazo); sin tipo, 24 horas.
conversa_identeronoAtención de origen. Vincula la OS a la conversación y completa el teléfono y el nombre del cliente cuando no se informan.
telefonetextonoWhatsApp del cliente. Misma regla de teléfono que el resto de la API.
nome_clientetextonoNombre del cliente, hasta 190 caracteres.
enderecotextonoDirección del servicio, hasta 255 caracteres.
departamento_identeronoEquipo dueño. Sin él, vale el equipo del tipo. Un departamento inexistente devuelve departamento_invalido.
responsavel_identeronoPersona responsable (atendentes/listar). Sin ella, la OS nace sin responsable. Un usuario inexistente o inactivo devuelve atendente_invalido.
erp_abrir0 o 1noApertura de la OS también en el ERP del proveedor. 1 pide la apertura en los tipos con postura Preguntar al abrir; 0 retiene la apertura en los tipos con Siempre: se abre en el ERP también. Omitido, vale la postura del tipo (Siempre abre, Preguntar no abre). Solo tiene efecto con las órdenes de servicio activadas en la tarjeta del ERP, el tipo mapeado para el ERP y un cliente del ERP identificado (por el conversa_id de una atención con abonado reconocido). El resultado vuelve en erp.
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/criar" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"titulo": "Sin señal en la Rua das Palmeiras", "descricao": "ONU sin luz PON desde las 09:40. Vecino también sin internet.", "tipo_id": 2, "prioridade": "urgente", "telefone": "44999990000", "nome_cliente": "Maria Souza", "endereco": "Rua das Palmeiras, 120, Centro", "departamento_id": 3}'
PHP
<?php
$dados = [
    'titulo' => 'Sin señal en la Rua das Palmeiras',
    'descricao' => 'ONU sin luz PON desde las 09:40. Vecino también sin internet.',
    'tipo_id' => 2,
    'prioridade' => 'urgente',
    'telefone' => '44999990000',
    'nome_cliente' => 'Maria Souza',
    'endereco' => 'Rua das Palmeiras, 120, Centro',
    'departamento_id' => 3,
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/criar');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/criar"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"titulo": "Sin señal en la Rua das Palmeiras", "descricao": "ONU sin luz PON desde las 09:40. Vecino también sin internet.", "tipo_id": 2, "prioridade": "urgente", "telefone": "44999990000", "nome_cliente": "Maria Souza", "endereco": "Rua das Palmeiras, 120, Centro", "departamento_id": 3},
    timeout=30,
).json()

La respuesta trae la OS completa en el formato del objeto orden de servicio:

Respuesta
{
  "ok": true,
  "ticket": {
    "id": 128,
    "numero": "OS-000128",
    "titulo": "Sin señal en la Rua das Palmeiras",
    "etapa": {"id": 1, "nome": "Abierto", "natureza": "inicial"},
    "prioridade": "urgente",
    "origem": "api",
    "prazo_em": "2026-10-01T18:15:00-03:00",
    "prazo_situacao": "ok",
    "...": "demás campos del objeto orden de servicio"
  }
}

Qué sucede al abrir

  1. Número y etapa: la OS recibe el número OS- y entra en la etapa inicial del tablero. La línea de tiempo registra el evento aberto (con origem igual a api) y el evento de sistema API: <nombre de la clave>.
  2. Plazo y prioridad según el tipo: sin prazo_em y sin prioridade, valen los valores predeterminados del tipo. El tipo Reparación de red de fábrica, por ejemplo, da prioridad urgente y 8 horas de plazo.
  3. Responsable: con un responsavel_id válido, la línea de tiempo registra el evento responsavel.
  4. Avisos al equipo: con responsable, este recibe por WhatsApp "OS asignada a usted". Sin responsable y con equipo, las personas del departamento reciben "Nueva OS para el equipo". El aviso por WhatsApp llega a quien tiene el WhatsApp verificado y los avisos activados en Mi cuenta.
  5. Rastro en la atención vinculada: con conversa_id, la línea de tiempo de la atención recibe el registro de la OS (número y título) y, con la IA configurada y la atención con alguna conversación de hecho, la IA prepara el resumen de la atención para el técnico, que aparece en resumo_ia y como evento ia en la línea de tiempo de la OS. El cliente no ve nada de esto.
  6. OS en el ERP: según la postura del tipo y erp_abrir, la OS se abre también en el ERP del proveedor. Antes, ChatISP verifica si el cliente ya tiene una OS abierta del mismo tipo allá y, si la tiene, liga la OS de aquí a ella (reaproveitada: true) en vez de abrir otra. El número y la situación vuelven en erp.ordens; una falla al abrir no impide la creación de la OS aquí y queda registrada en la línea de tiempo como evento erp. Después, cada cambio en el ERP se convierte en un evento erp y dispara ticket_atualizado; la conclusión en el ERP mueve la OS a la etapa de naturaleza resolvido.
  7. Webhook: sale el evento ticket_criado hacia los webhooks suscritos a él.

La OS es interna: no se envía nada al cliente. Para avisar al cliente que el equipo técnico fue activado, envíe un mensaje por la ruta mensagens/enviar. La receta El NOC abre una OS y avisa al cliente muestra el flujo completo.


Mover de etapa

POST/api_publica.php?r=tickets/mover

Lleva la OS a otra etapa del tablero, con un comentario opcional. Es la misma acción de arrastrar la tarjeta en el panel.

ParámetroTipoObligatorioDescripción
ticket_id o numeroentero / textosíQué OS.
etapa_identerosíEtapa de destino (tickets/etapas). Debe estar activa.
comentariotextonoHasta 1.900 caracteres. Queda en el evento del cambio de etapa, después de la marca [API: <nombre de la clave>], y, resumido, en la nota de la atención vinculada.
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/mover" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"numero": "OS-000128", "etapa_id": 5, "comentario": "Empalme hecho en el poste 32, señal normalizada."}'
PHP
<?php
$dados = [
    'numero' => 'OS-000128',
    'etapa_id' => 5,
    'comentario' => 'Empalme hecho en el poste 32, señal normalizada.',
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/mover');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/mover"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"numero": "OS-000128", "etapa_id": 5, "comentario": "Empalme hecho en el poste 32, señal normalizada."},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "ticket": {
    "id": 128,
    "numero": "OS-000128",
    "etapa": {"id": 5, "nome": "Resuelto", "natureza": "resolvido"},
    "concluido": true,
    "prazo_situacao": "concluido",
    "resolvido_em": "2026-10-01T12:06:10-03:00",
    "fechado_em": "2026-10-01T12:06:10-03:00",
    "...": "demás campos del objeto orden de servicio"
  }
}

Reglas del movimiento

  • La clave no se convierte en responsable. En el panel, quien mueve una OS sin responsable a una etapa de trabajo pasa a ser el responsable. Por la API eso no sucede: la OS sigue sin responsable hasta que alguien la asuma o hasta que usted llame a tickets/atribuir.
  • Misma etapa: mover a la etapa en la que la OS ya está no registra nada y devuelve la OS tal como está.
  • Fechas: la primera entrada en una etapa andamento registra iniciado_em; una etapa resolvido registra resolvido_em y fechado_em; cancelado registra fechado_em. Salir de una etapa final es una reapertura (evento reaberto).
  • Avisos: al entrar en una etapa final, quien abrió la OS por el panel recibe un aviso por WhatsApp. Las OS abiertas por la API no tienen una persona como autora, así que ese aviso no sale.
  • Atención vinculada: mientras la atención esté abierta, recibe una nota interna "OS OS-000128 movida a la etapa Resuelto por API: <nombre de la clave>." seguida del comentario. Una atención cerrada no recibe nota.
  • Webhook: sale ticket_atualizado con mudanca igual a etapa (o reaberto).

Para concluir una OS sin depender del nombre de la etapa, busque en tickets/etapas la primera etapa activa con naturaleza resolvido y use su id.


Asignar responsable

POST/api_publica.php?r=tickets/atribuir

Define, cambia o quita el responsable de la OS.

ParámetroTipoObligatorioDescripción
ticket_id o numeroentero / textosíQué OS.
responsavel_identerosíId de la persona (atendentes/listar), que debe estar activa. 0 quita el responsable: la OS vuelve a quedar sin responsable.
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/atribuir" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"ticket_id": 128, "responsavel_id": 7}'
PHP
<?php
$dados = [
    'ticket_id' => 128,
    'responsavel_id' => 7,
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/atribuir');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/atribuir"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"ticket_id": 128, "responsavel_id": 7},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "ticket": {
    "id": 128,
    "numero": "OS-000128",
    "responsavel_id": 7,
    "responsavel": "Carlos Lima",
    "...": "demás campos del objeto orden de servicio"
  }
}
  • Asignar a la persona que ya es la responsable no registra nada.
  • La nueva persona responsable recibe por WhatsApp "OS asignada a usted" (si tiene el WhatsApp verificado y los avisos activados).
  • La línea de tiempo registra el evento responsavel; la atención vinculada, si está abierta, recibe la nota interna correspondiente.
  • Sale el webhook ticket_atualizado con mudanca igual a responsavel.

Comentar

POST/api_publica.php?r=tickets/comentar

Agrega un comentario a la línea de tiempo de la OS, sin cambiar la etapa ni el responsable. Útil para devolver al tablero lo que ocurrió en su sistema: orden de servicio cerrada en el ERP, lectura de señal tomada por el monitoreo, respuesta del proveedor.

ParámetroTipoObligatorioDescripción
ticket_id o numeroentero / textosíQué OS.
textotextosíDe 1 a 19.000 caracteres. Se guarda con el prefijo [API: <nombre de la clave>].
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/comentar" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"numero": "OS-000128", "texto": "Señal de la ONU normalizada: -19,8 dBm a las 12:04."}'
PHP
<?php
$dados = [
    'numero' => 'OS-000128',
    'texto' => 'Señal de la ONU normalizada: -19,8 dBm a las 12:04.',
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=tickets/comentar');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "tickets/comentar"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"numero": "OS-000128", "texto": "Señal de la ONU normalizada: -19,8 dBm a las 12:04."},
    timeout=30,
).json()
Respuesta
{
  "ok": true,
  "evento_id": 933,
  "ticket": {
    "id": 128,
    "numero": "OS-000128",
    "total_comentarios": 2,
    "...": "demás campos del objeto orden de servicio"
  }
}

La atención vinculada, si está abierta, recibe una nota interna con el comienzo del comentario (hasta 200 caracteres). Sale el webhook ticket_atualizado con mudanca igual a comentario y el campo comentario con hasta 2.000 caracteres del texto.

Adjuntar archivos a la OS es una acción del panel. Por la API, registre el enlace del archivo en el texto del comentario.


Webhooks de órdenes de servicio

Dos eventos cubren el ciclo de la OS, venga el cambio del panel, de la IA, del Copiloto o de la propia API:

EventoCuándomudanca
ticket_criadoOS abierta.(no tiene)
ticket_atualizadoCambio de etapa, reapertura, cambio de responsable o comentario.etapa, reaberto, responsavel o comentario (este último con el campo comentario).

El cuerpo trae un resumen estable de la OS en dados: ticket_id, numero, titulo, etapa_id, etapa, natureza, prioridade, origem, conversa_id, telefone, nome_cliente, departamento_id, responsavel_id, responsavel y prazo_em.

Cuerpo del webhook (ticket_atualizado)
{
  "evento": "ticket_atualizado",
  "emitido_em": "2026-10-01T12:06:10-03:00",
  "dados": {
    "ticket_id": 128,
    "numero": "OS-000128",
    "titulo": "Sin señal en la Rua das Palmeiras",
    "etapa_id": 5,
    "etapa": "Resuelto",
    "natureza": "resolvido",
    "prioridade": "urgente",
    "origem": "api",
    "conversa_id": 5310,
    "telefone": "5544999990000",
    "nome_cliente": "Maria Souza",
    "departamento_id": 3,
    "responsavel_id": 7,
    "responsavel": "Carlos Lima",
    "prazo_em": "2026-10-01T18:15:00-03:00",
    "mudanca": "etapa"
  }
}

Las ediciones hechas en el panel (título, tipo, prioridad, plazo, cliente), los adjuntos y el resumen de la IA no generan webhook; para ellas, use tickets/listar con atualizados_desde. El contenido completo está en Datos de los eventos de orden de servicio; la firma, la entrega y los reintentos, en Webhooks.


Errores de las rutas de órdenes de servicio

Además de los errores comunes a toda la API (autenticación, permiso, plan, cuota, método), descritos en Errores:

errorHTTPRutasCausa
permissao403todasLa clave no tiene Consultar órdenes de servicio (lectura) o Gestionar órdenes de servicio (escritura). El campo escopo indica cuál falta.
identificador_obrigatorio400consultar, mover, atribuir, comentarFaltan ticket_id y numero.
nao_encontrado404consultar, mover, atribuir, comentarNinguna OS con ese id o número.
titulo_invalido400criarTítulo vacío o con más de 160 caracteres.
conversa_invalida400criarconversa_id no existe.
telefone_invalido400criar, listarEl teléfono no es un número de WhatsApp válido.
sem_etapas409criarEl tablero no tiene ninguna etapa activa para recibir la OS.
etapa_invalida400moverEtapa inexistente o desactivada.
parametro_obrigatorio400mover, atribuirFalta etapa_id o responsavel_id (vea campo).
tipo_invalido400criarTipo inexistente o desactivado.
departamento_invalido400criarDepartamento inexistente.
atendente_invalido400criar, atribuirUsuario inexistente o inactivo.
texto_invalido400comentarTexto vacío o de más de 19.000 caracteres.
parametro_invalido400listar, criarValor fuera de lo aceptado: situacao o prioridade desconocida (la lista viene en aceitos), número con letras, descripción de más de 20.000 caracteres, limite mayor que 100.
data_invalida400listar, criarFecha que no se pudo interpretar (vea campo).
Ejemplo de error
{"ok": false, "error": "etapa_invalida"}