Ordens de serviço
Referência das oito rotas de ordens de serviço da API do ChatISP: consulte etapas e tipos do quadro, liste e acompanhe ordens de serviço com a linha do tempo completa, e abra, mova, atribua e comente ordens de serviço a partir do seu ERP, do sistema de monitoramento ou do portal do assinante.
Visão geral
OS é a demanda interna da equipe do provedor: visita técnica, reparo de rede, instalação, ajuste financeiro. Ele vive no quadro de Ordens de serviço do painel, passa por etapas até ser resolvido ou cancelado e pode estar ligado a um atendimento do WhatsApp. Pela API, outro sistema enxerga e opera o mesmo quadro, com as mesmas regras do painel: prazo, avisos à equipe, rastro no atendimento de origem e webhooks.
Casos típicos de integração:
- Monitoramento e NOC: o sistema que detecta a queda de um cliente corporativo ou de uma caixa de atendimento abre a OS de reparo já com prioridade, endereço e descrição técnica.
- ERP: a ordem de serviço criada no ERP vira OS no quadro da equipe, e a conclusão no ChatISP volta para o ERP pelo webhook.
- Equipe de campo: o aplicativo do técnico move a OS para a etapa de execução, comenta o que foi feito e marca como resolvido.
- Painel próprio e BI: listagem de atrasados, ordens de serviço por responsável e sincronização incremental pelo marco de atualização.
Rotas
| Rota | Método | Permissão da chave | O que faz |
|---|---|---|---|
tickets/etapas | GET | Consultar ordens de serviço | Etapas do quadro, com a natureza de cada uma. |
tickets/tipos | GET | Consultar ordens de serviço | Tipos de OS, com prioridade e prazo padrão. |
tickets/listar | GET | Consultar ordens de serviço | Lista paginada com filtros. |
tickets/consultar | GET | Consultar ordens de serviço | Uma OS com a linha do tempo inteira. |
tickets/criar | POST | Gerenciar ordens de serviço | Abre uma OS. |
tickets/mover | POST | Gerenciar ordens de serviço | Leva a OS para outra etapa. |
tickets/atribuir | POST | Gerenciar ordens de serviço | Define ou retira o responsável. |
tickets/comentar | POST | Gerenciar ordens de serviço | Comenta na linha do tempo. |
A permissão é marcada na chave, em Integrações, card API do ChatISP. Gerenciar ordens de serviço não inclui a leitura: para abrir uma OS e depois acompanhá-lo, marque as duas. Autenticação, formato das chamadas, paginação e erros comuns a todas as rotas estão na Introdução.
Quem aparece como autor
A chave de API não é um usuário da equipe. Por isso, nas ações feitas pela API:
- O OS aberta pela API nasce com
origemigual aapie, na linha do tempo, ganha um evento de sistema com o textoAPI: <nome da chave>, logo depois do evento de abertura. - Comentários entram com o prefixo
[API: <nome da chave>]no texto, para a equipe saber de onde vieram. - Mudanças de etapa feitas pela API registram no evento o texto
[API: <nome da chave>], seguido do comentário quando houver. - Os eventos registrados pela API têm
autor_idnulo eautorvazio; a origem fica no texto. - As notas que a OS deixa no atendimento vinculado citam a chave como autora (por exemplo, "movido para a etapa Em execução por API: ERP").
Dê à chave um nome que a equipe reconheça, como ERP, NOC ou App de campo. É esse nome que aparece no quadro, na linha do tempo e no atendimento.
Visão da casa inteira
A chave enxerga todos as ordens de serviço, de todos os departamentos e responsáveis. As regras de visibilidade dos perfis de acesso (quem vê só as ordens de serviço da própria equipe) valem para as pessoas no painel, não para a API.
O objeto OS
Todas as rotas que devolvem uma OS usam o mesmo formato. Datas em ISO 8601 com fuso; campo sem valor vem null (datas, ids) ou texto vazio (nomes).
| Campo | Tipo | Descrição |
|---|---|---|
id | inteiro | Identificador interno da OS. Use nas chamadas como ticket_id. |
numero | texto | Número que a equipe vê no quadro, no formato OS-000128. Também serve para localizar a OS nas chamadas (parâmetro numero). |
titulo | texto | Título curto, até 160 caracteres. |
descricao | texto | Descrição livre; vazia quando não foi preenchida. |
tipo | objeto ou null | {"id", "nome"} do tipo de OS; null quando a OS não tem tipo. |
etapa | objeto | {"id", "nome", "natureza"} da etapa atual. A natureza diz como o sistema trata a etapa: veja Naturezas, prioridades e prazo. |
concluido | booleano | true quando a etapa atual é final (natureza resolvido ou cancelado). |
prioridade | texto | baixa, normal, alta ou urgente. |
origem | texto | De onde a OS veio: manual (aberto no quadro), chat (aberto a partir de um atendimento), ia (aberto pela IA), copiloto (aberto pelo Copiloto) ou api. |
conversa_id | inteiro ou null | Atendimento vinculado, quando existe. |
protocolo | texto ou null | Protocolo do atendimento vinculado. |
cliente | objeto | {"telefone", "nome", "endereco"}. Telefone com DDI, só dígitos. Os três podem vir vazios em OS interna, sem cliente. |
departamento_id / departamento | inteiro ou null / texto | Equipe dona da OS. |
responsavel_id / responsavel | inteiro ou null / texto | Pessoa responsável. null e vazio quando a OS está sem dono. |
prazo_em | data ou null | Prazo para resolver. null quando a OS não tem prazo. |
prazo_situacao | texto | sem_prazo, ok, atencao, vencido ou concluido. Calculado no momento da chamada. |
resumo_ia | texto ou null | Resumo do atendimento vinculado feito pela IA para quem vai executar a OS. Chega alguns instantes depois da abertura; null enquanto não existe ou quando não há atendimento vinculado. |
total_comentarios | inteiro | Quantidade de comentários na linha do tempo. |
total_anexos | inteiro | Quantidade de arquivos anexados pela equipe. |
erp | objeto ou null | A OS no ERP do provedor (veja No ERP do provedor na documentação do sistema). null quando a OS não tem cliente do ERP vinculado nem registro em ERP algum. Traz erp_id (ERP do cliente vinculado, ou null), id_externo_cliente e id_externo_contrato (identificadores do cliente e do contrato no ERP, texto ou null) e ordens, a lista das OS abertas no ERP para esta OS: zero ou uma por ERP, com os campos da tabela seguinte. |
aberto_em | data | Quando a OS foi aberto. |
iniciado_em | data ou null | Primeira vez que a OS entrou numa etapa de natureza andamento. |
resolvido_em | data ou null | Quando entrou numa etapa resolvido. |
fechado_em | data ou null | Quando entrou numa etapa final (resolvido ou cancelado). |
ultima_atividade_em | data | Último registro na linha do tempo (abertura, etapa, comentário, anexo, edição, resumo). É o campo usado pelo filtro atualizados_desde e pela ordem da listagem. |
Campos de erp.ordens[]
| Campo | Tipo | Descrição |
|---|---|---|
erp_id / erp | inteiro / texto | Identificador e nome do ERP, como cadastrado em Integrações. |
tipo_erp | texto | ixc, hubsoft, sgp, gesprov ou pipesoft. |
id | texto | Identificador interno da OS no ERP. |
numero | texto | Número da OS como o ERP mostra para a equipe de lá. |
protocolo | texto ou null | Protocolo da ocorrência ou do chamado, nos ERPs que trabalham com protocolo além do número. |
situacao | texto | Situação no vocabulário comum do ChatISP: aberta, em_analise, agendada, em_execucao, aguardando, concluida ou desconhecida (o ERP devolveu algo que o ChatISP não reconhece). |
situacao_erp | texto ou null | A situação crua, como o ERP a chama. |
tecnico | texto ou null | Técnico atribuído no ERP, quando informado. |
agendado_em / concluido_em | data ou null | Agendamento e conclusão lidos do ERP. |
reaproveitada | booleano | true quando a OS daqui foi ligada a uma OS que já estava aberta no ERP para o mesmo cliente e tipo, em vez de abrir outra. |
acompanha | booleano | true quando o ChatISP consulta o ERP periodicamente e conclui a OS daqui quando o ERP conclui; false no Gesprov, que só permite abrir. |
ultima_consulta_em | data ou null | Última consulta ao ERP com sucesso. |
{
"id": 128,
"numero": "OS-000128",
"titulo": "Sem sinal na Rua das Palmeiras",
"descricao": "ONU sem luz PON desde 09:40. Cliente informa que o vizinho também está sem internet.",
"tipo": {"id": 2, "nome": "Reparo de rede"},
"etapa": {"id": 1, "nome": "Aberto", "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": "Suporte 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"
}Naturezas, prioridades e prazo
As etapas do quadro têm nome e cor livres, configurados por cada provedor. O que o sistema entende de cada uma é a natureza. Integre sempre pela natureza, nunca pelo nome: "Resolvido" num provedor pode ser "Finalizado" em outro.
Naturezas de etapa
| Natureza | Rótulo no painel | O que o sistema faz |
|---|---|---|
inicial | Inicial (entrada) | Onde a OS nasce. O OS nova entra na primeira etapa ativa de natureza inicial (pela ordem do quadro); sem nenhuma, na primeira etapa ativa. |
andamento | Em andamento | A primeira entrada numa etapa assim grava iniciado_em. |
aguardando | Aguardando terceiros | OS parado à espera de algo externo (cliente, fornecedor). O prazo continua correndo. |
resolvido | Final: resolvido | Etapa final: grava resolvido_em e fechado_em, para o prazo e avisa quem abriu a OS. |
cancelado | Final: cancelado | Etapa final: grava fechado_em, para o prazo e avisa quem abriu a OS. |
Tirar uma OS de uma etapa final para uma etapa não final é uma reabertura: resolvido_em e fechado_em voltam a null, o prazo volta a correr e a linha do tempo registra um evento reaberto.
Prioridades
| Valor | Rótulo no painel |
|---|---|
baixa | Baixa |
normal | Normal |
alta | Alta |
urgente | Urgente |
Na abertura sem prioridade, vale a prioridade padrão do tipo; sem tipo, normal.
Situação do prazo
prazo_situacao | Quando |
|---|---|
sem_prazo | OS aberta sem prazo definido. |
ok | Prazo no futuro, com folga. |
atencao | Faltam 2 horas ou menos, ou menos de 25% do tempo total entre a abertura e o prazo. |
vencido | O prazo passou e a OS não está numa etapa final. |
concluido | A OS está numa etapa final: o prazo deixou de correr. |
Quando o prazo vence com a OS ainda aberto, o sistema registra uma única vez o evento de sistema "Prazo vencido sem conclusão." na linha do tempo e avisa pelo WhatsApp o responsável (ou a equipe do departamento, se a OS estiver sem dono). Esse evento atualiza ultima_atividade_em.
Etapas do quadro
/api_publica.php?r=tickets/etapasDevolve todas as etapas do quadro, na ordem das colunas, inclusive as desativadas. Sem parâmetros. Use para descobrir o etapa_id que tickets/mover pede, sempre escolhendo pela natureza.
Campo de etapas[] | Descrição |
|---|---|
id | Identificador da etapa. |
nome | Nome da coluna no quadro. |
natureza | inicial, andamento, aguardando, resolvido ou cancelado. |
cor | Cor da coluna em hexadecimal. |
ativa | false quando a etapa foi desativada. Etapa desativada não aceita OS novas nem movimentação. |
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \ -H "Authorization: Bearer $CHATISP_CHAVE" \ --data-urlencode "r=tickets/etapas"
<?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);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(){
"ok": true,
"etapas": [
{"id": 1, "nome": "Aberto", "natureza": "inicial", "cor": "#38bdf8", "ativa": true},
{"id": 2, "nome": "Em análise", "natureza": "andamento", "cor": "#8b5cf6", "ativa": true},
{"id": 3, "nome": "Em execução", "natureza": "andamento", "cor": "#f59e0b", "ativa": true},
{"id": 4, "nome": "Aguardando cliente", "natureza": "aguardando", "cor": "#64748b", "ativa": true},
{"id": 5, "nome": "Resolvido", "natureza": "resolvido", "cor": "#10b981", "ativa": true},
{"id": 6, "nome": "Cancelado", "natureza": "cancelado", "cor": "#d23939", "ativa": true}
]
}Os ids mudam de uma instalação para outra e o provedor pode criar, renomear e reordenar etapas. Guarde em cache por algumas horas e consulte de novo se receber etapa_invalida.
Tipos de OS
/api_publica.php?r=tickets/tiposDevolve os tipos de OS cadastrados em Configurações do módulo, inclusive os desativados. Sem parâmetros. O tipo define a prioridade, o prazo e a equipe que a OS recebe quando a chamada de abertura não informa esses campos.
Campo de tipos[] | Descrição |
|---|---|
id | Identificador do tipo, usado em tipo_id. |
nome | Nome do tipo. |
ativo | false quando desativado. Tipo desativado é recusado na abertura (tipo_invalido). |
prioridade_padrao | Prioridade aplicada quando a abertura não informa uma. |
prazo_horas | Horas até o prazo, contadas da abertura. 0 significa sem prazo automático. |
departamento_id | Equipe que recebe a OS quando a abertura não informa departamento_id; null se o tipo não tem equipe. |
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \ -H "Authorization: Bearer $CHATISP_CHAVE" \ --data-urlencode "r=tickets/tipos"
<?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);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(){
"ok": true,
"tipos": [
{"id": 1, "nome": "Visita técnica", "ativo": true, "prioridade_padrao": "alta", "prazo_horas": 24, "departamento_id": 3},
{"id": 2, "nome": "Reparo de rede", "ativo": true, "prioridade_padrao": "urgente", "prazo_horas": 8, "departamento_id": 3},
{"id": 3, "nome": "Instalação", "ativo": true, "prioridade_padrao": "normal", "prazo_horas": 48, "departamento_id": null},
{"id": 4, "nome": "Financeiro", "ativo": true, "prioridade_padrao": "normal", "prazo_horas": 24, "departamento_id": 2},
{"id": 5, "nome": "Outro", "ativo": true, "prioridade_padrao": "normal", "prazo_horas": 24, "departamento_id": null}
]
}Listar ordens de serviço
/api_publica.php?r=tickets/listarLista paginada de ordens de serviço, do mais recentemente movimentado para o mais antigo (ordem de ultima_atividade_em). Todos os filtros são opcionais e se combinam (todos precisam valer ao mesmo tempo). Sem filtro, vêm todos as ordens de serviço, abertos e concluídos.
| Parâmetro | Tipo | Descrição |
|---|---|---|
situacao | texto | todos (padrão), abertos (etapa não final) ou concluidos (resolvidos e cancelados). |
etapa_id | inteiro | Só as ordens de serviço dessa etapa. |
tipo_id | inteiro | Só os desse tipo. |
departamento_id | inteiro | Só os dessa equipe. |
conversa_id | inteiro | Só os vinculados a esse atendimento. |
responsavel_id | inteiro | Só os dessa pessoa. Com 0, só as ordens de serviço sem dono. |
prioridade | texto | baixa, normal, alta ou urgente. |
atrasados | booleano | 1 (ou true): só os OS abertas com prazo vencido. |
telefone | texto | Só os do cliente desse número. Mesma regra de telefone do resto da API (sem +, é brasileiro); o número é procurado com e sem o nono dígito. |
abertos_desde / abertos_ate | data | Faixa da data de abertura. Data sem hora em abertos_ate vale até 23:59:59 do dia. |
atualizados_desde | data | Só os que tiveram qualquer registro na linha do tempo a partir desse instante. Base da sincronização incremental. |
busca | texto | Procura no número, título, descrição, nome do cliente e endereço (até 120 caracteres). |
pagina / limite | inteiro | Paginação numerada: limite de 1 a 100 (padrão 50). |
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
$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);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(){
"ok": true,
"tickets": [
{
"id": 121,
"numero": "OS-000121",
"titulo": "Troca de conector na CTO 14",
"etapa": {"id": 3, "nome": "Em execução", "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",
"...": "demais campos do objeto ticket"
}
],
"paginacao": {"pagina": 1, "limite": 20, "total": 1, "paginas": 1}
}Sincronização incremental
Para manter um espelho das ordens de serviço no seu sistema, guarde o instante de cada rodada e, na seguinte, peça atualizados_desde com esse instante (de preferência com alguns minutos de folga, gravando por id para não duplicar). Abertura, mudança de etapa, troca de responsável, comentário, anexo, edição, resumo da IA e prazo vencido atualizam o marco. A hora certa do servidor está em servidor.agora da rota chave/info.
Se o seu sistema só precisa reagir quando algo muda, o webhook é mais eficiente que consultar de tempos em tempos: os eventos ticket_criado e ticket_atualizado chegam na hora. Veja Webhooks.
Consultar uma OS
/api_publica.php?r=tickets/consultarDevolve a OS e a linha do tempo completa, do evento mais antigo para o mais recente.
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ticket_id | inteiro | um dos dois | Id da OS (também aceito como id). |
numero | texto | um dos dois | Número da OS, como OS-000128. Útil quando o número foi digitado por uma pessoa. |
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \ -H "Authorization: Bearer $CHATISP_CHAVE" \ --data-urlencode "r=tickets/consultar" \ --data-urlencode "numero=T-000128"
<?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);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(){
"ok": true,
"ticket": {"id": 128, "numero": "OS-000128", "...": "objeto ticket completo"},
"eventos": [
{
"id": 901, "tipo": "aberto", "autor_id": null, "autor": "", "texto": "",
"dados": {"origem": "api", "etapa": "Aberto"}, "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": "Equipe a caminho",
"dados": {"de": 1, "de_nome": "Aberto", "de_cor": "#38bdf8", "para": 3, "para_nome": "Em execução",
"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 rompida no poste 32. Emenda feita, sinal normalizado.",
"dados": [], "anexos": [{"nome": "emenda.jpg", "tamanho": 284113}],
"criado_em": "2026-10-01T12:05:51-03:00"
}
]
}Campo de eventos[] | Descrição |
|---|---|
id | Identificador do evento (crescente). |
tipo | Tipo do evento: tabela abaixo. |
autor_id / autor | Quem fez. null e vazio para o sistema, a IA e as ações feitas pela API. |
texto | Texto do comentário, do resumo da IA, do comentário que acompanhou a mudança de etapa ou da mensagem de sistema. |
dados | Detalhes estruturados do evento (objeto); lista vazia quando não há. |
anexos | Arquivos anexados junto com o evento: {"nome", "tamanho"} (tamanho em bytes). O download do anexo é feito pelo painel. |
criado_em | Quando aconteceu. |
Tipos de evento da linha do tempo
tipo | Quando aparece | Conteúdo de dados e texto |
|---|---|---|
aberto | Abertura da OS. | origem e etapa (nome da etapa inicial). |
responsavel | Responsável definido, trocado ou retirado; também quando alguém da equipe move uma OS sem dono para uma etapa de trabalho e passa a ser o dono. | de, de_nome, para, para_nome. para nulo = OS ficou sem dono. |
etapa | Mudança de etapa. | de, de_nome, de_cor, para, para_nome, para_cor, natureza (da etapa de destino). O comentário que acompanhou a mudança vem em texto. |
reaberto | Saída de uma etapa final para uma etapa não final. | Mesmos campos de etapa. |
comentario | Comentário da equipe ou da API. | Texto em texto; arquivos do comentário em anexos. |
anexo | Arquivo anexado sem comentário, enviado do computador ou trazido do atendimento. | nome do arquivo, ou origem igual a conversa quando veio do chat. |
tipo | Tipo da OS trocado no painel. | de_nome, para_nome. |
prioridade | Prioridade trocada no painel. | de, para. |
prazo | Prazo trocado no painel. | de, para, como texto curto de data e hora (o formato que a tela mostra). |
editado | Outros campos editados no painel (título, descrição, cliente, endereço, equipe). | campos (lista dos campos alterados) e detalhe. |
ia | Resumo do atendimento vinculado, gerado pela IA. | Resumo em texto. |
erp | O que aconteceu no ERP do provedor: abertura, vínculo a uma OS que já existia, falha ao abrir, mudança de situação, técnico ou agenda, e conclusão. | dados.acao (aberta, vinculada, falha, situacao ou concluida), dados.erp_nome, dados.os_numero e, conforme a ação, a situação nova, o técnico, a agenda ou o motivo da falha (erro e mensagem). |
sistema | Registro automático: a marca API: <nome da chave> na abertura pela API, ou "Prazo vencido sem conclusão.". | Texto em texto; no prazo vencido, dados.prazo. |
Trate tipos de evento desconhecidos sem quebrar a integração: novos tipos podem surgir com a evolução do quadro. Mostre o texto quando houver e ignore o resto.
Abrir uma OS
/api_publica.php?r=tickets/criarAbre uma OS na etapa inicial do quadro. Só o título é obrigatório; o resto completa a OS e, quando omitido, é preenchido pelo tipo ou pelo atendimento vinculado.
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
titulo | texto | sim | De 1 a 160 caracteres. |
descricao | texto | não | Até 20.000 caracteres. Coloque aqui tudo o que o técnico precisa: sintomas, equipamento, sinal, referências do endereço. |
tipo_id | inteiro | não | Tipo da OS (ordens de serviço/tipos). Tipo inexistente ou desativado dá tipo_invalido. |
prioridade | texto | não | baixa, normal, alta ou urgente. Sem ela, vale a do tipo; sem tipo, normal. |
prazo_em | data | não | Prazo explícito. Sem ele, o prazo é a abertura mais as prazo_horas do tipo (tipo com 0 = sem prazo); sem tipo, 24 horas. |
conversa_id | inteiro | não | Atendimento de origem. Vincula a OS à conversa e completa telefone e nome do cliente quando não informados. |
telefone | texto | não | WhatsApp do cliente. Mesma regra de telefone do resto da API. |
nome_cliente | texto | não | Nome do cliente, até 190 caracteres. |
endereco | texto | não | Endereço do serviço, até 255 caracteres. |
departamento_id | inteiro | não | Equipe dona. Sem ela, vale a equipe do tipo. Departamento inexistente dá departamento_invalido. |
responsavel_id | inteiro | não | Pessoa responsável (atendentes/listar). Sem ela, a OS nasce sem dono. Usuário inexistente ou inativo dá atendente_invalido. |
erp_abrir | 0 ou 1 | não | Abertura da OS também no ERP do provedor. 1 pede a abertura nos tipos com postura Perguntar ao abrir; 0 segura a abertura nos tipos com Sempre: abre no ERP junto. Omitido, vale a postura do tipo (Sempre abre, Perguntar não abre). Só tem efeito com as ordens de serviço ligadas no cartão do ERP, o tipo mapeado para o ERP e um cliente do ERP identificado (pelo conversa_id de um atendimento com assinante reconhecido). O resultado volta em erp. |
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": "Sem sinal na Rua das Palmeiras", "descricao": "ONU sem luz PON desde 09:40. Vizinho também sem internet.", "tipo_id": 2, "prioridade": "urgente", "telefone": "44999990000", "nome_cliente": "Maria Souza", "endereco": "Rua das Palmeiras, 120, Centro", "departamento_id": 3}'<?php
$dados = [
'titulo' => 'Sem sinal na Rua das Palmeiras',
'descricao' => 'ONU sem luz PON desde 09:40. Vizinho também sem 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);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": "Sem sinal na Rua das Palmeiras", "descricao": "ONU sem luz PON desde 09:40. Vizinho também sem internet.", "tipo_id": 2, "prioridade": "urgente", "telefone": "44999990000", "nome_cliente": "Maria Souza", "endereco": "Rua das Palmeiras, 120, Centro", "departamento_id": 3},
timeout=30,
).json()A resposta traz a OS completo no formato do objeto OS:
{
"ok": true,
"ticket": {
"id": 128,
"numero": "OS-000128",
"titulo": "Sem sinal na Rua das Palmeiras",
"etapa": {"id": 1, "nome": "Aberto", "natureza": "inicial"},
"prioridade": "urgente",
"origem": "api",
"prazo_em": "2026-10-01T18:15:00-03:00",
"prazo_situacao": "ok",
"...": "demais campos do objeto ticket"
}
}O que acontece ao abrir
- Número e etapa: a OS recebe o número
T-e entra na etapa inicial do quadro. A linha do tempo registra o eventoaberto(comorigemigual aapi) e o evento de sistemaAPI: <nome da chave>. - Prazo e prioridade pelo tipo: sem
prazo_eme semprioridade, valem os padrões do tipo. O tipo Reparo de rede de fábrica, por exemplo, dá prioridade urgente e 8 horas de prazo. - Responsável: com
responsavel_idválido, a linha do tempo registra o eventoresponsavel. - Avisos à equipe: com responsável, ele recebe pelo WhatsApp "OS atribuída a você". Sem responsável e com equipe, as pessoas do departamento recebem "Nova OS para a equipe". O aviso pelo WhatsApp vale para quem tem o WhatsApp verificado e os avisos ligados em Minha conta.
- Rastro no atendimento vinculado: com
conversa_id, a linha do tempo do atendimento ganha o registro da OS (número e título) e, com a IA configurada e o atendimento tendo alguma conversa de fato, a IA prepara o resumo do atendimento para o técnico, que aparece emresumo_iae como eventoiana linha do tempo da OS. O cliente não vê nada disso. - OS no ERP: conforme a postura do tipo e
erp_abrir, a OS é aberta também no ERP do provedor. Antes, o ChatISP confere se o cliente já tem OS aberta do mesmo tipo lá e, se tiver, liga a OS daqui a ela (reaproveitada: true) em vez de abrir outra. Número e situação voltam emerp.ordens; falha ao abrir não impede a criação da OS aqui e fica registrada na linha do tempo como eventoerp. Depois, cada mudança no ERP vira um eventoerpe disparaticket_atualizado; a conclusão no ERP move a OS para a etapa de naturezaresolvido. - Webhook: sai o evento
ticket_criadopara os webhooks inscritos nele.
A OS é interno: nada é enviado ao cliente. Para avisar o cliente que a equipe técnica foi acionada, envie uma mensagem pela rota mensagens/enviar. A receita NOC abre OS e avisa o cliente mostra o fluxo completo.
Mover de etapa
/api_publica.php?r=tickets/moverLeva a OS para outra etapa do quadro, com um comentário opcional. É a mesma ação de arrastar o cartão no painel.
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ticket_id ou numero | inteiro / texto | sim | Qual OS. |
etapa_id | inteiro | sim | Etapa de destino (ordens de serviço/etapas). Precisa estar ativa. |
comentario | texto | não | Até 1.900 caracteres. Fica no evento da mudança de etapa, depois da marca [API: <nome da chave>], e, resumido, na nota do atendimento vinculado. |
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": "Emenda feita no poste 32, sinal normalizado."}'<?php
$dados = [
'numero' => 'OS-000128',
'etapa_id' => 5,
'comentario' => 'Emenda feita no poste 32, sinal normalizado.',
];
$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);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": "Emenda feita no poste 32, sinal normalizado."},
timeout=30,
).json(){
"ok": true,
"ticket": {
"id": 128,
"numero": "OS-000128",
"etapa": {"id": 5, "nome": "Resolvido", "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",
"...": "demais campos do objeto ticket"
}
}Regras da movimentação
- A chave não vira dona. No painel, quem move uma OS sem dono para uma etapa de trabalho passa a ser o responsável. Pela API isso não acontece: a OS continua sem dono até alguém assumir ou até você chamar ordens de serviço/atribuir.
- Mesma etapa: mover para a etapa em que a OS já está não registra nada e devolve a OS como está.
- Datas: a primeira entrada em etapa
andamentogravainiciado_em; etaparesolvidogravaresolvido_emefechado_em;canceladogravafechado_em. Sair de etapa final é reabertura (eventoreaberto). - Avisos: ao entrar em etapa final, quem abriu a OS pelo painel recebe aviso pelo WhatsApp. OS abertas pela API não têm uma pessoa como autora, então esse aviso não sai.
- Atendimento vinculado: enquanto o atendimento estiver aberto, ganha uma nota interna "OS OS-000128 movido para a etapa Resolvido por API: <nome da chave>." seguida do comentário. Atendimento encerrado não recebe nota.
- Webhook: sai
ticket_atualizadocommudancaigual aetapa(oureaberto).
Para concluir uma OS sem depender do nome da etapa, procure em tickets/etapas a primeira etapa ativa com natureza resolvido e use o id dela.
Atribuir responsável
/api_publica.php?r=tickets/atribuirDefine, troca ou retira o responsável pela OS.
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ticket_id ou numero | inteiro / texto | sim | Qual OS. |
responsavel_id | inteiro | sim | Id da pessoa (atendentes/listar), que precisa estar ativa. 0 tira o dono: a OS volta a ficar sem responsável. |
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
$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);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(){
"ok": true,
"ticket": {
"id": 128,
"numero": "OS-000128",
"responsavel_id": 7,
"responsavel": "Carlos Lima",
"...": "demais campos do objeto ticket"
}
}- Atribuir à pessoa que já é a responsável não registra nada.
- A nova pessoa responsável recebe pelo WhatsApp "OS atribuída a você" (se tiver o WhatsApp verificado e os avisos ligados).
- A linha do tempo registra o evento
responsavel; o atendimento vinculado, se aberto, ganha a nota interna correspondente. - Sai o webhook
ticket_atualizadocommudancaigual aresponsavel.
Comentar
/api_publica.php?r=tickets/comentarAcrescenta um comentário na linha do tempo da OS, sem mudar etapa nem responsável. Bom para devolver ao quadro o que aconteceu no seu sistema: OS fechada no ERP, leitura de sinal coletada pelo monitoramento, retorno do fornecedor.
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
ticket_id ou numero | inteiro / texto | sim | Qual OS. |
texto | texto | sim | De 1 a 19.000 caracteres. Gravado com o prefixo [API: <nome da chave>]. |
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": "Sinal da ONU normalizado: -19,8 dBm às 12:04."}'<?php
$dados = [
'numero' => 'OS-000128',
'texto' => 'Sinal da ONU normalizado: -19,8 dBm às 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);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": "Sinal da ONU normalizado: -19,8 dBm às 12:04."},
timeout=30,
).json(){
"ok": true,
"evento_id": 933,
"ticket": {
"id": 128,
"numero": "OS-000128",
"total_comentarios": 2,
"...": "demais campos do objeto ticket"
}
}O atendimento vinculado, se aberto, recebe uma nota interna com o começo do comentário (até 200 caracteres). Sai o webhook ticket_atualizado com mudanca igual a comentario e o campo comentario com até 2.000 caracteres do texto.
Anexar arquivos à OS é uma ação do painel. Pela API, registre o link do arquivo no texto do comentário.
Webhooks de ordens de serviço
Dois eventos cobrem o ciclo da OS, venha a mudança do painel, da IA, do Copiloto ou da própria API:
| Evento | Quando | mudanca |
|---|---|---|
ticket_criado | OS aberta. | (não tem) |
ticket_atualizado | Mudança de etapa, reabertura, troca de responsável ou comentário. | etapa, reaberto, responsavel ou comentario (este último com o campo comentario). |
O corpo traz um resumo estável da OS em dados: ticket_id, numero, titulo, etapa_id, etapa, natureza, prioridade, origem, conversa_id, telefone, nome_cliente, departamento_id, responsavel_id, responsavel e prazo_em.
{
"evento": "ticket_atualizado",
"emitido_em": "2026-10-01T12:06:10-03:00",
"dados": {
"ticket_id": 128,
"numero": "OS-000128",
"titulo": "Sem sinal na Rua das Palmeiras",
"etapa_id": 5,
"etapa": "Resolvido",
"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"
}
}Edições feitas no painel (título, tipo, prioridade, prazo, cliente), anexos e o resumo da IA não geram webhook; para elas, use tickets/listar com atualizados_desde. O conteúdo completo está em Dados dos eventos de OS; assinatura, entrega e retentativas, em Webhooks.
Erros das rotas de ordens de serviço
Além dos erros comuns a toda a API (autenticação, permissão, plano, cota, método), descritos em Erros:
error | HTTP | Rotas | Causa |
|---|---|---|---|
permissao | 403 | todas | A chave não tem Consultar ordens de serviço (leitura) ou Gerenciar ordens de serviço (escrita). O campo escopo diz qual falta. |
identificador_obrigatorio | 400 | consultar, mover, atribuir, comentar | Faltou ticket_id e numero. |
nao_encontrado | 404 | consultar, mover, atribuir, comentar | Nenhum OS com esse id ou número. |
titulo_invalido | 400 | criar | Título vazio ou com mais de 160 caracteres. |
conversa_invalida | 400 | criar | conversa_id não existe. |
telefone_invalido | 400 | criar, listar | O telefone não é um número de WhatsApp válido. |
sem_etapas | 409 | criar | O quadro não tem nenhuma etapa ativa para receber a OS. |
etapa_invalida | 400 | mover | Etapa inexistente ou desativada. |
parametro_obrigatorio | 400 | mover, atribuir | Faltou etapa_id ou responsavel_id (veja campo). |
tipo_invalido | 400 | criar | Tipo inexistente ou desativado. |
departamento_invalido | 400 | criar | Departamento inexistente. |
atendente_invalido | 400 | criar, atribuir | Usuário inexistente ou inativo. |
texto_invalido | 400 | comentar | Texto vazio ou acima de 19.000 caracteres. |
parametro_invalido | 400 | listar, criar | Valor fora do aceito: situacao ou prioridade desconhecida (a lista vem em aceitos), número com letras, descrição acima de 20.000 caracteres, limite acima de 100. |
data_invalida | 400 | listar, criar | Data que não pôde ser lida (veja campo). |
{"ok": false, "error": "etapa_invalida"}