https://api.atys.pro/api/v1/omnichat/,
respondem JSON e têm contrato estável: mudanças incompatíveis só entram numa versão nova.
Como funciona
Tudo o que a equipe faz no atendimento da Atys também pode ser feito pela API: acompanhar as
conversas de todos os canais (WhatsApp, Instagram, Messenger, Telegram, e-mail…), atribuir a um
atendente, transferir, encerrar, ler o histórico e enviar mensagens. Cada chamada passa pelas mesmas
regras da plataforma: a tela dos atendentes atualiza na hora, as automações disparam e os
webhooks omnichat.* são enviados.
Uma conversa é o contato num canal de atendimento da sua empresa. Ela nasce quando o
contato escreve ou quando você o cadastra num canal pela API de
Contatos; o id da conversa é o mesmo
channelId de lá.
- Encontrar as conversas — listar com filtros, contador de não lidas e detalhe.
- Atender — atribuir, transferir, fixar, arquivar, marcar como lida e pausar a automação.
- Conversar — histórico, enviar texto, mídia e templates, editar e apagar mensagens.
- Encerrar — encerrar com motivo e pesquisa de satisfação, e reabrir.
Autenticação e permissões
Use uma chave de API com as permissões de Omnichat que a integração precisa:
| Permissão da chave | Libera |
|---|---|
| Consultar conversas e mensagens | Todos os GET: conversas, contador, participantes, histórico, templates e respostas rápidas. |
| Atender conversas e enviar mensagens | Atribuir, transferir, fixar, arquivar, marcar como lida, pausar automação, encerrar e reabrir; enviar, editar e apagar mensagens. |
A chave representa a empresa: enxerga as conversas de todos os canais, setores e atendentes, sem precisar que o usuário API seja atendente de cada canal. Ações por usuário — fixar, arquivar só para mim, não lidas — valem para o usuário API.
Conversas: como funcionam
Uma conversa é o contato num canal de atendimento da empresa (um número de WhatsApp, o
Instagram, o Telegram…) — a linha da lista do Omnichat. O id da conversa é o mesmo
channelId dos canais do contato e o
contact_channel_id das rotas de mensagens e dos webhooks omnichat.conversation.*.
Cada ação desta seção faz o mesmo que o item correspondente da tela: grava o comentário na conversa
("Ana atribuiu a conversa…"), atualiza as telas abertas em tempo real, dispara os webhooks e as automações.
- Visibilidade — com a chave de API, a integração enxerga todas as conversas da empresa. Com o token de login de um usuário, vale a regra da tela: setor, atendente e canais que ele atende. Conversa de outra empresa ou fora do alcance responde
404. - Permissões — as mesmas da plataforma: encerrar e reabrir pedem encerrar conversas, transferir pede atribuir conversas, arquivar pede arquivar conversas e pausar a automação pede pausar automação (ou acesso ao módulo de Workflows). Sem a permissão,
403 forbidden. - Dados do contato — nome, número e e-mail seguem as permissões do usuário API: sem ver nome completo só o primeiro nome, sem ver número o identificador mascarado e sem ver e-mail só o domínio.
- Por usuário — fixar, arquivar para mim e o contador de não lidas são do usuário autenticado (o usuário API da chave), como na tela. Os campos
is_pinnedeis_archived_for_mese referem a ele.
| Campo | Descrição |
|---|---|
status | open ou closed (encerrada: resolvida, cancelada, spam). |
status_id | Status detalhado: 66 nova, 67 em andamento, 68 resolvida, 69 cancelada, 70 spam; null = aberta sem status. |
assigned_user / sector | Atendente e setor da conversa (null = sem atendente / sem setor). Grupos não têm atendente. |
unread_count | Mensagens do contato ainda não lidas. |
is_archived_for_all | Arquivada para toda a equipe. |
automation_paused | O chatbot/automação está pausado nesta conversa. |
tags | Etiquetas de atendimento da conversa. |
last_message_id / last_message_at | Última mensagem (inclui os comentários internos das ações). O histórico fica nas rotas de mensagens. |
Listar conversas
As conversas visíveis, da mais recente (última mensagem) para a mais antiga — por padrão as abertas e não arquivadas, como a aba principal da tela. Os filtros só estreitam essa lista.
| Parâmetro | Tipo | Descrição |
|---|---|---|
status | string | open (default), closed ou all. |
archived | string | none (default: nem arquivada para todos nem para mim), for_me, for_all ou any. |
q | string | Busca da tela: cada palavra no nome da conversa ou no nome/e-mail do contato, sem diferenciar acento; ou o número (com e sem o 9º dígito). |
company_channel_id | integer | Canal da empresa (catálogo). |
sector_id / user_id | integer | Setor ou atendente (catálogos). |
unassigned | boolean | 1 = só as sem atendente. |
contact_id | integer | Conversas de um contato. |
tag_ids[] | integer[] | Conversas com alguma destas etiquetas (catálogo); etiqueta que o usuário não pode usar responde 422 invalid_tag. |
unread | boolean | 1 = com mensagens não lidas; 0 = sem. |
pinned | boolean | 1 = só as fixadas pelo usuário autenticado; 0 = as não fixadas. |
is_group | boolean | 1 = só grupos; 0 = só conversas individuais. |
updated_since | data ISO 8601 | Conversas alteradas a partir desta data (atribuição, status, mensagem nova…) — para sincronização incremental. |
page / per_page | integer | Paginação; per_page de 1 a 100 (default 25). |
Exemplos de código — listar conversas
curl "https://api.atys.pro/api/v1/omnichat/conversations?status=open&unread=1&company_channel_id=44&per_page=25" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations?status=open&unread=1&company_channel_id=44&per_page=25', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations?status=open&unread=1&company_channel_id=44&per_page=25',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations?status=open&unread=1&company_channel_id=44&per_page=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'query' => [
'status' => 'open',
'unread' => 1,
'company_channel_id' => 44,
'per_page' => 25
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations?status=open&unread=1&company_channel_id=44&per_page=25", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": [
{
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": null,
"assigned_user": null,
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991204,
"last_message_at": "2026-11-04T15:20:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:20:00-03:00"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"last_page": 1
}
}
Contador de não lidas
O número do badge do menu Atendimento: conversas abertas, não arquivadas e com mensagens não lidas que ninguém está com aberta na tela — na visibilidade do usuário autenticado.
Exemplos de código — contar conversas não lidas
curl "https://api.atys.pro/api/v1/omnichat/conversations/unread-count" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/unread-count', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/unread-count',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/unread-count');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/unread-count', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/unread-count", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"unread_conversations": 12
}
}
Ver uma conversa
A conversa com o estado do atendimento. Encerrada ou arquivada continua acessível pelo id.
Exemplos de código — detalhe da conversa
curl "https://api.atys.pro/api/v1/omnichat/conversations/77120" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/77120',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/77120', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/77120", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": null,
"assigned_user": null,
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991204,
"last_message_at": "2026-11-04T15:20:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:20:00-03:00"
}
}
Abrir uma conversa nova
Não há um endpoint próprio: como no botão Nova conversa da tela, a conversa nasce quando o
contato passa a existir naquele canal. Crie o contato com o canal (POST /api/v1/contacts) ou
adicione o canal a um contato existente (POST /api/v1/contacts/{id}/channels) — veja
Contatos. O id do canal
devolvido é o id da conversa; em seguida envie a primeira mensagem pelas rotas de mensagens
(no WhatsApp oficial, fora da janela de 24 h, com um template).
Atribuir atendente e setor
Define o atendente (user_id, obrigatório — null tira o atendente) e, opcionalmente,
o setor (sector_id; null tira o setor; ausente mantém). É o "Atribuir" e o
"Atender" da tela: atribuir a outra pessoa exige a permissão atribuir conversas; sem ela, o usuário
só pode puxar a conversa para si, num setor que ele enxerga. O atendente precisa ser um usuário ativo da
empresa (422 invalid_user) e o setor, da empresa (422 invalid_sector). Grupos não
têm atendente (422 group_not_assignable). Repetir o mesmo atendente e setor devolve a conversa
sem alterar nada.
Exemplos de código — atribuir conversa
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/assign" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"user_id": 81,
"sector_id": 6
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/assign', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"user_id": 81,
"sector_id": 6
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/assign',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'user_id': 81,
'sector_id': 6
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/assign');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'user_id' => 81,
'sector_id' => 6
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/assign', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'user_id' => 81,
'sector_id' => 6
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"user_id": 81,
"sector_id": 6
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/assign", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Transferir para outro canal
Move a conversa para outro número/canal da empresa do mesmo tipo — o "Transferir conversa" da tela. Com transfer_messages: true o histórico
passa a constar no canal de destino. Se o contato já tem uma conversa no destino, a resposta
é 409 merge_required; repita com confirm_merge: true para fundir as duas — a
conversa que fica é a do destino (confira o id da resposta). Para trocar só o atendente ou o
setor, use atribuir.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
company_channel_id | integer | Sim | Canal da empresa de destino. |
transfer_messages | boolean | Não | Leva o histórico de mensagens junto (default false). |
confirm_merge | boolean | Não | Confirma a fusão quando o contato já tem conversa no destino. |
Exemplos de código — transferir conversa
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/transfer" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"company_channel_id": 45,
"transfer_messages": true
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/transfer', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"company_channel_id": 45,
"transfer_messages": true
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/transfer',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'company_channel_id': 45,
'transfer_messages': True
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/transfer');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'company_channel_id' => 45,
'transfer_messages' => true
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/transfer', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'company_channel_id' => 45,
'transfer_messages' => true
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"company_channel_id": 45,
"transfer_messages": true
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/transfer", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 45,
"name": "WhatsApp Comercial"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991241,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Erros específicos: 422 invalid_company_channel (canal não é da empresa),
422 same_company_channel, 422 incompatible_channel_type,
422 group_not_transferable, 409 merge_required e
403 company_channel_forbidden — o usuário não atende o canal de destino e não tem a permissão
transferir para qualquer canal.
Fixar e desafixar
Fixa a conversa no topo da lista do usuário autenticado (até 200 por usuário —
422 pin_limit_reached). Fixar de novo não duplica. Encerrar ou arquivar desafixa.
Exemplos de código — fixar conversa
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/pin" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/pin', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/pin',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/pin');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/pin', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/pin", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": true,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Exemplos de código — desafixar conversa
curl -X DELETE "https://api.atys.pro/api/v1/omnichat/conversations/77120/pin" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/pin', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
console.log(response.status); // 204 = excluído
import os
import requests
response = requests.delete(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/pin',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
print(response.status_code) # 204 = excluído
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/pin');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('DELETE', 'v1/omnichat/conversations/77120/pin', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.atys.pro/api/v1/omnichat/conversations/77120/pin", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Arquivar para todos
Tira a conversa da lista de toda a equipe e encerra as automações em andamento nela — o "Arquivar para
todos" da tela. Uma mensagem nova do contato não desarquiva sozinha: use o DELETE. Liste as
arquivadas com archived=for_all.
Exemplos de código — arquivar para todos
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/archive',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/archive', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": true,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Exemplos de código — desarquivar para todos
curl -X DELETE "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
console.log(response.status); // 204 = excluído
import os
import requests
response = requests.delete(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/archive',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
print(response.status_code) # 204 = excluído
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('DELETE', 'v1/omnichat/conversations/77120/archive', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Arquivar só para mim
Esconde a conversa só da lista do usuário autenticado — os outros continuam vendo. Liste com
archived=for_me.
Exemplos de código — arquivar para mim
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/archive-for-me', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": true,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Exemplos de código — desarquivar para mim
curl -X DELETE "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
console.log(response.status); // 204 = excluído
import os
import requests
response = requests.delete(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
print(response.status_code) # 204 = excluído
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('DELETE', 'v1/omnichat/conversations/77120/archive-for-me', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.atys.pro/api/v1/omnichat/conversations/77120/archive-for-me", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Marcar como lida ou não lida
read zera as não lidas e, no WhatsApp e no Instagram, envia a confirmação de leitura ao contato
(os "dois tiques azuis"), como abrir a conversa na tela. unread volta a marcar como não lida
(pelo menos 1), sincronizando com o celular no WhatsApp quando possível.
Exemplos de código — marcar como lida
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/read" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/read', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/read',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/read');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/read', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/read", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 0,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Exemplos de código — marcar como não lida
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/unread" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/unread', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/unread',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/unread');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/unread', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/unread", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Pausar e retomar a automação
Pausa o chatbot e as automações de mensagem recebida nesta conversa — o botão do robô no
cabeçalho da tela —, para um atendente humano assumir sem o robô responder. resume volta a
ligar. Não vale para grupos (422 automation_not_available_for_group). O estado aparece em
automation_paused.
Exemplos de código — pausar automação
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/pause" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/pause', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/pause',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/pause');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/automation/pause', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/pause", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": true,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Exemplos de código — retomar automação
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/resume" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/resume', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/resume',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/resume');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/automation/resume', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/automation/resume", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 66,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": {
"id": 81,
"name": "Ana Atendente"
},
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991230,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Participantes de um grupo
Os participantes de uma conversa de grupo (is_group: true), com quem é administrador. A lista é
atualizada com o WhatsApp/Telegram quando tem mais de 24 h. Conversa que não é grupo responde
422 not_a_group. Nome e número seguem as mesmas máscaras dos dados de contato.
Exemplos de código — listar participantes do grupo
curl "https://api.atys.pro/api/v1/omnichat/conversations/77190/participants" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77190/participants', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/77190/participants',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77190/participants');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/77190/participants', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/77190/participants", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": [
{
"jid": "5511900001111@s.whatsapp.net",
"name": "Paulo Souza",
"is_admin": true
},
{
"jid": "5511900002222@s.whatsapp.net",
"name": "Rita Lima",
"is_admin": false
}
]
}
Etiquetas da conversa
As etiquetas de atendimento ficam no canal do contato, que é a própria conversa: use
PUT /api/v1/contacts/{id}/channels/{channelId}/tags com o contact.id e o
id da conversa — veja Etiquetas do canal.
A mensagem
Toda mensagem da v1 tem o mesmo formato, no histórico e nas respostas de envio. Os campos que mais importam:
| Campo | Descrição |
|---|---|
direction | inbound (o contato escreveu), outbound (saiu pela empresa: atendente, robô, campanha, API) ou internal (comentário interno, que o contato não vê). |
type | text, image, audio, video, document, sticker, location, contact, contacts, link, template, internal_note, deleted, audio_call, video_call, button, list, interactive, quick_reply, instagram_comment, instagram_story_reply… type_id traz o número interno. |
status | Entrega das mensagens enviadas: pending (na fila), sent, delivered, read, failed (com o motivo em error) ou uncertain (o canal não confirmou). O status muda depois do envio; acompanhe pelos webhooks ou consultando a mensagem. |
author | Quem escreveu: type = contact, user (atendente ou o usuário da chave), ai_agent (com o nome do agente), chatbot, workflow, campaign, api, other_device (celular da empresa) ou system. source é a origem bruta. |
media | Arquivo da mensagem (nome, tipo MIME, tamanho, dimensões, duração, páginas, se é áudio de voz e a transcrição, quando houver). download_url baixa o arquivo com a sua chave. |
reactions | Reações à mensagem; from_company diz se saiu de um número da empresa. |
content | Conteúdo estruturado de localização, cartão de contato, link com pré-visualização, botões e listas, como o canal entregou. |
Datas em ISO 8601. sent_at é a hora da mensagem no canal; created_at, quando
ela entrou na Atys.
Histórico da conversa
As mensagens de uma conversa, da mais recente para a mais antiga — as mesmas que o chat mostra. A
conversa precisa estar ao alcance do usuário (veja permissões);
de outra forma a resposta é 404.
A paginação é por cursor, pelo id da mensagem: para carregar mensagens mais antigas,
repita a chamada com before igual a meta.next_before enquanto
meta.has_more for true. Para buscar só o que chegou depois da última
mensagem que você já tem, use after. Se ainda houver mais (has_more),
continue com o mesmo after e before = next_before.
| Parâmetro | Tipo | Descrição |
|---|---|---|
before | integer | Só mensagens com id menor que este (mais antigas). |
after | integer | Só mensagens com id maior que este (mais novas). |
type | string | Um ou mais tipos separados por vírgula, por exemplo image,video,document. Tipo desconhecido responde 422 invalid_type. |
direction | string | inbound, outbound ou internal. |
per_page | integer | De 1 a 100 (padrão 50). |
Exemplos de código — histórico da conversa
curl "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages?per_page=50&before=918280" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages?per_page=50&before=918280', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages?per_page=50&before=918280',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages?per_page=50&before=918280');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/77120/messages', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'query' => [
'per_page' => 50,
'before' => 918280
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages?per_page=50&before=918280", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": [
{
"id": 918275,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "text",
"type_id": 1,
"text": "Saiu sim! Chega amanhã.",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": null,
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
},
{
"id": 918274,
"conversation_id": 77120,
"external_id": "3EB0A1B2C3D4E5F6",
"direction": "inbound",
"type": "text",
"type_id": 1,
"text": "Oi! Meu pedido já saiu?",
"status": "read",
"status_id": 9,
"error": null,
"author": {
"type": "contact",
"source": "contact",
"id": 5120,
"name": "Maria Cliente"
},
"reply_to_message_id": null,
"media": null,
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:20:00-03:00",
"created_at": "2026-11-04T15:20:01-03:00",
"updated_at": "2026-11-04T15:20:01-03:00"
}
],
"meta": {
"per_page": 50,
"has_more": true,
"next_before": 918274
}
}
Ver uma mensagem e baixar o arquivo
Uma mensagem da conversa, por exemplo para acompanhar o status de um envio. Mensagem
que não é desta conversa responde 404.
Exemplos de código — ver mensagem
curl "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/77120/messages/918277', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918277,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "document",
"type_id": 5,
"text": "Segue o boleto",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": {
"file_name": "boleto.pdf",
"mime_type": "application/pdf",
"size": 48211,
"url": "https://files.atys.pro/storage/files/company-12/messages/boleto.pdf",
"download_url": "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media",
"duration": null,
"width": null,
"height": null,
"pages": 1,
"voice_note": false,
"transcription": null
},
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
O arquivo de uma mensagem de mídia (imagem, áudio, vídeo, documento, figurinha) é baixado pelo
endpoint abaixo, que devolve os bytes com o Content-Type e o nome do arquivo. Funciona
também com arquivos guardados no Google Drive da empresa. Mensagem sem arquivo responde 404.
Exemplos de código — baixar arquivo da mensagem
curl "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/77120/messages/918277/media', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
Enviar texto
Envia uma mensagem na conversa, como o botão Enviar do chat, por qualquer canal: WhatsApp, Instagram, Messenger, Telegram e Minichat. A mensagem fica no nome do usuário da chave, entra no histórico e dispara os mesmos webhooks e automações de uma mensagem de atendente. Se a conversa não tem atendente, ela passa a ser do usuário da chave, como na plataforma. Se havia um robô atendendo, ele para.
A resposta é 201 com status: "pending": a entrega ao canal acontece logo
em seguida, e o resultado (sent, delivered, read ou
failed) chega pelos webhooks ou na consulta da mensagem.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
text | string (4096) | Sim | Texto da mensagem. No Instagram, até 1000 caracteres (text_too_long). |
reply_to_message_id | integer | Não | Responde (cita) uma mensagem desta conversa. Veja responder. |
quick_reply_id | integer | Não | Marca o envio como uso de uma resposta rápida, o que dispara as automações de “mensagem rápida enviada”. O texto continua sendo o de text. |
Exemplos de código — enviar texto
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"text": "Saiu sim! Chega amanhã."
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"text": "Saiu sim! Chega amanhã."
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'text': 'Saiu sim! Chega amanhã.'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Saiu sim! Chega amanhã.'
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/messages', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'text' => 'Saiu sim! Chega amanhã.'
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"text": "Saiu sim! Chega amanhã."
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918275,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "text",
"type_id": 1,
"text": "Saiu sim! Chega amanhã.",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": null,
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
No WhatsApp Oficial, a Meta só aceita mensagem livre até 24 horas depois da última
mensagem do contato. Fora dessa janela, a API recusa antes de enviar, com
422 whatsapp_window_closed, e nada é gravado. Nesse caso, envie um
template.
Responder a uma mensagem
Com reply_to_message_id, a mensagem vai citando outra, como o “Responder” do chat. O
id precisa ser de uma mensagem desta conversa (senão, 422 invalid_reply_to). Vale para
texto e para mídia.
Exemplos de código — responder mensagem
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"text": "O código de rastreio é BR123456789.",
"reply_to_message_id": 918274
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"text": "O código de rastreio é BR123456789.",
"reply_to_message_id": 918274
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'text': 'O código de rastreio é BR123456789.',
'reply_to_message_id': 918274
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'text' => 'O código de rastreio é BR123456789.',
'reply_to_message_id' => 918274
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/messages', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'text' => 'O código de rastreio é BR123456789.',
'reply_to_message_id' => 918274
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"text": "O código de rastreio é BR123456789.",
"reply_to_message_id": 918274
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918276,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "text",
"type_id": 1,
"text": "O código de rastreio é BR123456789.",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": 918274,
"media": null,
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
Enviar mídia por URL
Envia uma imagem, um vídeo, um áudio ou um documento que está num endereço público. A Atys baixa o
arquivo, guarda uma cópia no armazenamento da empresa (ele fica no histórico) e envia pelo canal da
conversa. O tipo é detectado pelo conteúdo do arquivo; use media_type para forçar um
tipo, por exemplo mandar uma imagem como documento.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
media_url | URL http(s) | Sim | Endereço público do arquivo, até 100 MB. Endereços internos ou privados respondem invalid_media_url. |
media_type | string | Não | image, video, audio ou document. |
file_name | string | Não | Nome do arquivo que o contato vê (documentos). Padrão: o nome que está na URL. |
caption | string (4096) | Não | Legenda. Áudio com legenda vai como documento, porque o WhatsApp não aceita legenda em áudio. |
voice_note | boolean | Não | Com media_type: "audio", envia como mensagem de voz (o arquivo é convertido para o formato do WhatsApp). |
reply_to_message_id | integer | Não | Responde a uma mensagem da conversa. |
Exemplos de código — enviar documento por url
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"media_url": "https://minhaloja.com.br/boletos/4521.pdf",
"file_name": "boleto.pdf",
"caption": "Segue o boleto"
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"media_url": "https://minhaloja.com.br/boletos/4521.pdf",
"file_name": "boleto.pdf",
"caption": "Segue o boleto"
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'media_url': 'https://minhaloja.com.br/boletos/4521.pdf',
'file_name': 'boleto.pdf',
'caption': 'Segue o boleto'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'media_url' => 'https://minhaloja.com.br/boletos/4521.pdf',
'file_name' => 'boleto.pdf',
'caption' => 'Segue o boleto'
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/messages', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'media_url' => 'https://minhaloja.com.br/boletos/4521.pdf',
'file_name' => 'boleto.pdf',
'caption' => 'Segue o boleto'
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"media_url": "https://minhaloja.com.br/boletos/4521.pdf",
"file_name": "boleto.pdf",
"caption": "Segue o boleto"
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918277,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "document",
"type_id": 5,
"text": "Segue o boleto",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": {
"file_name": "boleto.pdf",
"mime_type": "application/pdf",
"size": 48211,
"url": "https://files.atys.pro/storage/files/company-12/messages/boleto.pdf",
"download_url": "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/media",
"duration": null,
"width": null,
"height": null,
"pages": 1,
"voice_note": false,
"transcription": null
},
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
No WhatsApp Oficial, os limites de tamanho da Meta são conferidos antes do envio:
imagem 5 MB, áudio e vídeo 16 MB e documento 100 MB (media_too_large). Se não for
possível baixar o arquivo, a resposta é media_download_failed.
Enviar arquivo (upload)
Envia um arquivo do seu sistema em multipart/form-data, no campo file
(até 100 MB). Os outros campos são os mesmos do envio por URL:
caption, media_type, voice_note,
reply_to_message_id e quick_reply_id. A janela de 24 horas do WhatsApp
Oficial vale igual.
Exemplos de código — enviar arquivo
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/media" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-F "caption=Nosso catálogo" \
-F "file=@catalogo.jpg"
const form = new FormData();
form.append('caption', 'Nosso catálogo');
form.append('file', fileInput.files[0]); // ou new Blob([...]), 'catalogo.jpg'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/media', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
},
body: form // não defina Content-Type: o navegador/Node põe o boundary
});
const { data, error } = await response.json();
import os
import requests
with open('catalogo.jpg', 'rb') as f:
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/media',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
files={'file': f},
data={'caption': 'Nosso catálogo'}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/media');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
CURLOPT_POSTFIELDS => [
'caption' => 'Nosso catálogo',
'file' => new CURLFile('catalogo.jpg'),
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/messages/media', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'multipart' => [
['name' => 'caption', 'contents' => 'Nosso catálogo'],
['name' => 'file', 'contents' => fopen('catalogo.jpg', 'r'), 'filename' => 'catalogo.jpg'],
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
var body bytes.Buffer
form := multipart.NewWriter(&body)
form.WriteField("caption", "Nosso catálogo")
part, _ := form.CreateFormFile("file", "catalogo.jpg")
file, _ := os.Open("catalogo.jpg")
defer file.Close()
io.Copy(part, file)
form.Close()
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/media", &body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", form.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918278,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "image",
"type_id": 2,
"text": "Nosso catálogo",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": {
"file_name": "catalogo.jpg",
"mime_type": "image/jpeg",
"size": 182044,
"url": "https://files.atys.pro/storage/files/company-12/messages/catalogo.jpg",
"download_url": "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918278/media",
"duration": null,
"width": 1080,
"height": 1350,
"pages": null,
"voice_note": false,
"transcription": null
},
"template": null,
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
Templates do WhatsApp Oficial
Os templates aprovados pela Meta que podem ser enviados nesta conversa — os mesmos do botão
Enviar template do chat, do WABA do número da conversa. Em conversas de outros
canais, a lista vem vazia. Em components está o texto registrado na Meta: cada
{{1}}, {{2}}… (ou {{nome}}, quando
parameter_format é named) é uma variável do envio.
Exemplos de código — templates da conversa
curl "https://api.atys.pro/api/v1/omnichat/conversations/77131/templates" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77131/templates', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/conversations/77131/templates',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77131/templates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/conversations/77131/templates', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/conversations/77131/templates", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": [
{
"id": 312,
"name": "pedido_enviado",
"language": "pt_BR",
"category": "UTILITY",
"parameter_format": "positional",
"has_buttons": false,
"components": [
{
"type": "BODY",
"text": "Olá {{1}}, seu pedido {{2}} foi enviado.",
"example": {
"body_text": [
[
"Maria",
"4521"
]
]
}
}
]
}
]
}
Enviar template
Fora da janela de 24 horas, o template é a única forma de falar com o contato no WhatsApp Oficial.
Informe o template por id ou por name (com language, se o
mesmo nome existir em mais de um idioma). Ele precisa ser aprovado, estar entre os
templates da conversa e ser do número dela (senão,
invalid_template). Em conversa que não é do WhatsApp Oficial, a resposta é
templates_not_supported.
| Campo | Tipo | Descrição |
|---|---|---|
template.id / template.name | integer / string | Um dos dois é obrigatório. |
template.language | string | Código do idioma, por exemplo pt_BR. |
template.variables | string[] | Valores das variáveis numeradas, na ordem (o primeiro preenche a variável 1). Variável sem valor recebe, nesta ordem, o nome, o telefone e o e-mail do contato. |
template.named_variables | objeto | Para templates com variáveis por nome: {"nome": "Maria"}. |
template.button_variables | objeto | Sufixos de botões de URL dinâmica, por índice do botão: {"0": ["4521"]}. |
template.header_media_url | URL http(s) | Troca a imagem, o vídeo ou o documento do cabeçalho só neste envio. |
template.header_media_filename | string | Nome do documento do cabeçalho. |
Exemplos de código — enviar template
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77131/messages" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"template": {
"name": "pedido_enviado",
"language": "pt_BR",
"variables": ["Maria", "4521"]
}
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77131/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"template": {
"name": "pedido_enviado",
"language": "pt_BR",
"variables": ["Maria", "4521"]
}
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77131/messages',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'template': {
'name': 'pedido_enviado',
'language': 'pt_BR',
'variables': ['Maria', '4521']
}
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77131/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'template' => [
'name' => 'pedido_enviado',
'language' => 'pt_BR',
'variables' => ['Maria', '4521']
]
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77131/messages', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'template' => [
'name' => 'pedido_enviado',
'language' => 'pt_BR',
'variables' => ['Maria', '4521']
]
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"template": {
"name": "pedido_enviado",
"language": "pt_BR",
"variables": ["Maria", "4521"]
}
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77131/messages", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918279,
"conversation_id": 77131,
"external_id": null,
"direction": "outbound",
"type": "template",
"type_id": 24,
"text": "Olá Maria, seu pedido 4521 foi enviado.",
"status": "pending",
"status_id": 6,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": null,
"template": {
"name": "pedido_enviado",
"language": "pt_BR"
},
"content": null,
"reactions": [],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
Num mesmo envio, use só um conteúdo: text, media_url ou
template. Combinações respondem 422 validation_failed.
Editar mensagem
Troca o texto de uma mensagem enviada pela empresa, como o “Editar” do chat. Funciona nos canais que permitem edição (incluindo o Minichat), só em mensagens de texto e só nos primeiros 15 minutos depois do envio. O contato vê a mensagem marcada como editada.
Exemplos de código — editar mensagem
curl -X PATCH "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"text": "Saiu sim! Chega amanhã até as 18h."
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"text": "Saiu sim! Chega amanhã até as 18h."
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.patch(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'text': 'Saiu sim! Chega amanhã até as 18h.'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Saiu sim! Chega amanhã até as 18h.'
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('PATCH', 'v1/omnichat/conversations/77120/messages/918275', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'text' => 'Saiu sim! Chega amanhã até as 18h.'
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"text": "Saiu sim! Chega amanhã até as 18h."
}`)
req, _ := http.NewRequest("PATCH", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918275,
"conversation_id": 77120,
"external_id": null,
"direction": "outbound",
"type": "text",
"type_id": 1,
"text": "Saiu sim! Chega amanhã até as 18h.",
"status": "delivered",
"status_id": 8,
"error": null,
"author": {
"type": "user",
"source": "user",
"id": 81,
"name": "Integração ERP"
},
"reply_to_message_id": null,
"media": null,
"template": null,
"content": null,
"reactions": [],
"edited": true,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:22:00-03:00",
"created_at": "2026-11-04T15:22:00-03:00",
"updated_at": "2026-11-04T15:22:00-03:00"
}
}
Erros específicos (422): message_not_editable (mensagem do contato,
template, mídia sem texto, localização, canal que não edita), edit_window_expired
(mais de 15 minutos) e edit_failed (o canal recusou a edição).
Apagar mensagem
Apaga uma mensagem enviada pela empresa. Por padrão (scope=all), apaga para todos: o
WhatsApp remove a mensagem do celular do contato, e no histórico da Atys ela fica como
deleted. Isso só funciona nos canais que permitem apagar para todos. Nos outros canais
(WhatsApp Oficial, Instagram, Messenger, Telegram, Minichat), use
scope=me, que só remove a mensagem do histórico da Atys. Templates e mensagens do
contato não podem ser apagados (message_not_deletable).
| Parâmetro | Tipo | Descrição |
|---|---|---|
scope | string | all (padrão) ou me. |
remove_media | boolean | Com scope=all, pede ao WhatsApp para remover também a mídia do aparelho do contato. |
Exemplos de código — apagar para todos
curl -X DELETE "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
console.log(response.status); // 204 = excluído
import os
import requests
response = requests.delete(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
print(response.status_code) # 204 = excluído
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('DELETE', 'v1/omnichat/conversations/77120/messages/918275', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918275", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
Erros específicos (422): revoke_not_supported (o canal não apaga para
todos) e revoke_failed (o canal recusou, por exemplo porque passou o prazo do WhatsApp).
Reagir a uma mensagem
Reage com um emoji a uma mensagem da conversa, pelo número da empresa. Uma nova reação substitui a
anterior, como no WhatsApp. A resposta é a mensagem com as reações atualizadas.
Remover responde 204; se o canal não confirmar a remoção (número desconectado, por exemplo),
responde 422 com unreact_failed: a reação já saiu da Atys, mas pode continuar
visível para o contato.
Exemplos de código — reagir
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"emoji": "👍"
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"emoji": "👍"
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'emoji': '👍'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'emoji' => '👍'
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/messages/918274/reactions', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'emoji' => '👍'
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"emoji": "👍"
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 918274,
"conversation_id": 77120,
"external_id": "3EB0A1B2C3D4E5F6",
"direction": "inbound",
"type": "text",
"type_id": 1,
"text": "Oi! Meu pedido já saiu?",
"status": "read",
"status_id": 9,
"error": null,
"author": {
"type": "contact",
"source": "contact",
"id": 5120,
"name": "Maria Cliente"
},
"reply_to_message_id": null,
"media": null,
"template": null,
"content": null,
"reactions": [
{
"emoji": "👍",
"sender_name": "Integração ERP",
"from_company": true,
"reacted_at": "2026-11-04T15:23:00-03:00"
}
],
"edited": false,
"forwarded": false,
"deleted": false,
"sent_at": "2026-11-04T15:20:00-03:00",
"created_at": "2026-11-04T15:20:01-03:00",
"updated_at": "2026-11-04T15:20:01-03:00"
}
}
Exemplos de código — remover reação
curl -X DELETE "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
console.log(response.status); // 204 = excluído
import os
import requests
response = requests.delete(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
print(response.status_code) # 204 = excluído
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('DELETE', 'v1/omnichat/conversations/77120/messages/918274/reactions', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918274/reactions", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
Não dá para reagir a mensagens apagadas nem a comentários internos (message_not_reactable).
Encaminhar mensagem
Encaminha a mensagem (com a mídia, se houver) para até 20 outras conversas, como o “Encaminhar” do
chat. Ela sai pelo canal da empresa em company_channel_id; por padrão, o canal da
conversa de origem. Esse canal precisa ser do mesmo tipo das conversas de destino.
Exemplos de código — encaminhar mensagem
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/forward" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"conversation_ids": [77131, 77140],
"company_channel_id": 44
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/forward', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"conversation_ids": [77131, 77140],
"company_channel_id": 44
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/forward',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'conversation_ids': [77131, 77140],
'company_channel_id': 44
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/forward');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'conversation_ids' => [77131, 77140],
'company_channel_id' => 44
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/messages/918277/forward', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'conversation_ids' => [77131, 77140],
'company_channel_id' => 44
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"conversation_ids": [77131, 77140],
"company_channel_id": 44
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/messages/918277/forward", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"sent": [
{
"message_id": 918290,
"status": "sent"
}
],
"skipped": [
{
"conversation_id": 77140,
"reason": "group.not_member"
}
]
}
}
Grupos em que o número não participa ou não pode enviar aparecem em skipped, com o
motivo. Erros específicos (422): invalid_conversation (destino não
encontrado, com conversation_ids), invalid_company_channel,
channel_mismatch e message_not_forwardable (comentário interno, reação,
mensagem apagada).
Respostas rápidas
As mensagens rápidas que a equipe usa com /atalho no chat, cadastradas em
Configurações > Atendimento. company_channel_ids limita a resposta a alguns canais;
vazio significa disponível em todos. Com o filtro company_channel_id, a lista traz as
do canal e as que valem para todos, como no chat. Pela API, as respostas rápidas são só de texto.
Arquivos anexados pela plataforma são mantidos e aparecem em files.
| Parâmetro | Tipo | Descrição |
|---|---|---|
q | string | Busca no atalho e no texto. |
company_channel_id | integer | Respostas disponíveis neste canal da empresa. |
page / per_page | integer | Paginação; per_page de 1 a 100 (padrão 25). |
Exemplos de código — listar respostas rápidas
curl "https://api.atys.pro/api/v1/omnichat/quick-replies?company_channel_id=44" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/quick-replies?company_channel_id=44', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.get(
'https://api.atys.pro/api/v1/omnichat/quick-replies?company_channel_id=44',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/quick-replies?company_channel_id=44');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('GET', 'v1/omnichat/quick-replies', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'query' => [
'company_channel_id' => 44
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.atys.pro/api/v1/omnichat/quick-replies?company_channel_id=44", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": [
{
"id": 58,
"shortcut": "prazo",
"text": "Entregamos em até 2 dias úteis para capitais.",
"company_channel_ids": [
44
],
"files": [],
"created_at": "2026-11-04T15:20:00-03:00",
"updated_at": "2026-11-04T15:20:00-03:00"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"last_page": 1
}
}
Exemplos de código — criar resposta rápida
curl -X POST "https://api.atys.pro/api/v1/omnichat/quick-replies" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"shortcut": "prazo",
"text": "Entregamos em até 2 dias úteis para capitais.",
"company_channel_ids": [44]
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/quick-replies', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"shortcut": "prazo",
"text": "Entregamos em até 2 dias úteis para capitais.",
"company_channel_ids": [44]
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/quick-replies',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'shortcut': 'prazo',
'text': 'Entregamos em até 2 dias úteis para capitais.',
'company_channel_ids': [44]
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/quick-replies');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'shortcut' => 'prazo',
'text' => 'Entregamos em até 2 dias úteis para capitais.',
'company_channel_ids' => [44]
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/quick-replies', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'shortcut' => 'prazo',
'text' => 'Entregamos em até 2 dias úteis para capitais.',
'company_channel_ids' => [44]
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"shortcut": "prazo",
"text": "Entregamos em até 2 dias úteis para capitais.",
"company_channel_ids": [44]
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/quick-replies", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 58,
"shortcut": "prazo",
"text": "Entregamos em até 2 dias úteis para capitais.",
"company_channel_ids": [
44
],
"files": [],
"created_at": "2026-11-04T15:20:00-03:00",
"updated_at": "2026-11-04T15:20:00-03:00"
}
}
Exemplos de código — editar resposta rápida
curl -X PATCH "https://api.atys.pro/api/v1/omnichat/quick-replies/58" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"text": "Entregamos em até 3 dias úteis.",
"company_channel_ids": []
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/quick-replies/58', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"text": "Entregamos em até 3 dias úteis.",
"company_channel_ids": []
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.patch(
'https://api.atys.pro/api/v1/omnichat/quick-replies/58',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'text': 'Entregamos em até 3 dias úteis.',
'company_channel_ids': []
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/quick-replies/58');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Entregamos em até 3 dias úteis.',
'company_channel_ids' => []
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('PATCH', 'v1/omnichat/quick-replies/58', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'text' => 'Entregamos em até 3 dias úteis.',
'company_channel_ids' => []
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"text": "Entregamos em até 3 dias úteis.",
"company_channel_ids": []
}`)
req, _ := http.NewRequest("PATCH", "https://api.atys.pro/api/v1/omnichat/quick-replies/58", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 58,
"shortcut": "prazo",
"text": "Entregamos em até 3 dias úteis.",
"company_channel_ids": [],
"files": [],
"created_at": "2026-11-04T15:20:00-03:00",
"updated_at": "2026-11-04T15:20:00-03:00"
}
}
Exemplos de código — excluir resposta rápida
curl -X DELETE "https://api.atys.pro/api/v1/omnichat/quick-replies/58" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/quick-replies/58', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
console.log(response.status); // 204 = excluído
import os
import requests
response = requests.delete(
'https://api.atys.pro/api/v1/omnichat/quick-replies/58',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
print(response.status_code) # 204 = excluído
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/quick-replies/58');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('DELETE', 'v1/omnichat/quick-replies/58', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.atys.pro/api/v1/omnichat/quick-replies/58", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
Na edição, só os campos enviados mudam; company_channel_ids substitui a lista inteira.
Canal que não é da empresa responde 422 invalid_company_channel.
Assistente de IA
As ações do botão de IA do chat, com o provedor de IA configurado na empresa. Sem provedor ativo, ou
se a conversa não tiver mensagens suficientes, a resposta é 422 ai_unavailable, com o
motivo em message.
- Sugestões: de 1 a 5 respostas (
count, padrão 3) com base nas últimas mensagens. Nada é enviado nem gravado. - Resumo: resume a conversa (pontos-chave, pendências, próximo passo) e grava o resumo como comentário interno (
internal_note_id). - Melhorar redação: reescreve um rascunho (
text) no tom da conversa. Nada é enviado.
Exemplos de código — sugerir respostas
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/suggestions" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"count": 2
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/suggestions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"count": 2
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/suggestions',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'count': 2
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/suggestions');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'count' => 2
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/ai/suggestions', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'count' => 2
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"count": 2
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/suggestions", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"suggestions": [
"Seu pedido saiu hoje e chega amanhã.",
"Posso te enviar o código de rastreio?"
]
}
}
Exemplos de código — resumir conversa
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/summary" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/summary', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/summary',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/summary');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/ai/summary', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/summary", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"summary": "Pontos-chave: cliente quer saber do pedido 4521.\nPendências: enviar rastreio.\nPróximo passo: confirmar entrega amanhã.",
"internal_note_id": 918300
}
}
Exemplos de código — melhorar redação
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/improve-writing" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"text": "oi, seu pedido ja saiu, chega amanha"
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/improve-writing', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"text": "oi, seu pedido ja saiu, chega amanha"
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/improve-writing',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'text': 'oi, seu pedido ja saiu, chega amanha'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/improve-writing');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'text' => 'oi, seu pedido ja saiu, chega amanha'
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/ai/improve-writing', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'text' => 'oi, seu pedido ja saiu, chega amanha'
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"text": "oi, seu pedido ja saiu, chega amanha"
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/ai/improve-writing", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"text": "Olá! Seu pedido já saiu e chega amanhã."
}
}
Encerrar conversa
O "Encerrar conversa" da tela: fecha o atendimento com um motivo, tira o atendente, desfixa, encerra as
automações em andamento e grava o comentário. Os motivos são por canal — liste-os em
Motivos de encerramento
(422 invalid_close_reason se o motivo não for da empresa). Se o canal tem pesquisa de
satisfação configurada para o motivo, ela é enviada ao contato, como na tela; envie
send_satisfaction_survey: false para não enviar. Conversa já encerrada responde
422 conversation_already_closed.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
close_reason_id | integer | Sim | Motivo de encerramento. |
send_satisfaction_survey | boolean | Não | Default true: envia a pesquisa quando o canal/motivo tem uma configurada. |
Exemplos de código — encerrar conversa
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/close" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"close_reason_id": 812,
"send_satisfaction_survey": false
}'
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/close', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"close_reason_id": 812,
"send_satisfaction_survey": false
})
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/close',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
},
json={
'close_reason_id': 812,
'send_satisfaction_survey': False
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/close');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'close_reason_id' => 812,
'send_satisfaction_survey' => false
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/close', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
'json' => [
'close_reason_id' => 812,
'send_satisfaction_survey' => false
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"bytes"
"net/http"
"os"
)
func main() {
body := []byte(`{
"close_reason_id": 812,
"send_satisfaction_survey": false
}`)
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/close", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "closed",
"status_id": 68,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": null,
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991260,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Reabrir conversa
Reabre uma conversa encerrada (status em andamento, novo atendimento), como o "Reabrir" da tela.
Conversa aberta responde 422 conversation_not_closed. Uma mensagem nova do contato também
reabre a conversa automaticamente.
Exemplos de código — reabrir conversa
curl -X POST "https://api.atys.pro/api/v1/omnichat/conversations/77120/reopen" \
-H "Authorization: Bearer atys_live_SUA_CHAVE" \
-H "Accept: application/json"
const response = await fetch('https://api.atys.pro/api/v1/omnichat/conversations/77120/reopen', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ATYS_API_KEY}`,
'Accept': 'application/json'
}
});
const { data, error } = await response.json();
import os
import requests
response = requests.post(
'https://api.atys.pro/api/v1/omnichat/conversations/77120/reopen',
headers={
'Authorization': f"Bearer {os.environ['ATYS_API_KEY']}",
'Accept': 'application/json'
}
)
result = response.json()
<?php
$ch = curl_init('https://api.atys.pro/api/v1/omnichat/conversations/77120/reopen');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('ATYS_API_KEY'),
'Accept: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.atys.pro/api/']);
$response = $client->request('POST', 'v1/omnichat/conversations/77120/reopen', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ATYS_API_KEY'),
'Accept' => 'application/json',
],
]);
$result = json_decode($response->getBody(), true);
package main
import (
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.atys.pro/api/v1/omnichat/conversations/77120/reopen", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ATYS_API_KEY"))
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
{
"data": {
"id": 77120,
"contact": {
"id": 5120,
"name": "Maria Cliente",
"email": "maria@cliente.com.br"
},
"name": "Maria Cliente",
"key": "5511988887777",
"is_group": false,
"channel_type": {
"id": 3,
"name": "CHANNEL_TYPE_OFC_WHATSAPP",
"description": "Whatsapp oficial"
},
"company_channel": {
"id": 44,
"name": "WhatsApp da Loja"
},
"status": "open",
"status_id": 67,
"sector": {
"id": 6,
"name": "Comercial"
},
"assigned_user": null,
"unread_count": 3,
"is_pinned": false,
"is_archived_for_me": false,
"is_archived_for_all": false,
"automation_paused": false,
"tags": [
{
"id": 9,
"name": "VIP",
"color": "#f59e0b"
}
],
"last_message_id": 991275,
"last_message_at": "2026-11-04T15:31:00-03:00",
"first_attendant_message_at": null,
"created_at": "2026-10-28T09:12:00-03:00",
"updated_at": "2026-11-04T15:31:00-03:00"
}
}
Erros
Todo erro da v1 tem o mesmo formato: {"error": {"code", "message", "details"}}. Use o
code no seu tratamento; a message é para leitura humana.
422 validation_failed — dados inválidos
Campo obrigatório ausente ou com formato errado. details traz os erros por campo.
{
"error": {
"code": "validation_failed",
"message": "The text field is required.",
"details": { "text": ["The text field is required."] }
}
}
422 invalid_user / invalid_sector / invalid_company_channel / invalid_close_reason / invalid_tag
Algum id não é da empresa ou não pode ser usado pela chave.
422 conversation_already_closed / conversation_not_closed / pin_limit_reached
A conversa já está no estado pedido, ou o limite de conversas fixadas foi atingido.
422 same_company_channel / incompatible_channel_type / group_not_assignable / group_not_transferable / not_a_group
Transferência para o mesmo canal ou para um tipo de canal diferente, ou ação que não vale para grupos.
422 whatsapp_window_closed / invalid_template / templates_not_supported
No WhatsApp Oficial, fora da janela de 24 horas só é possível enviar um template aprovado do canal da conversa.
422 invalid_media_url / media_too_large / media_download_failed / text_too_long
Mídia inacessível ou acima do limite do canal, ou texto maior do que o canal aceita (Instagram: 1000 caracteres).
422 message_not_editable / edit_window_expired / message_not_deletable / revoke_not_supported
Só mensagens de texto enviadas pela empresa, em até 15 minutos e nos canais que permitem, podem ser editadas; apagar para todos depende do canal.
422 invalid_reply_to / invalid_quick_reply / channel_mismatch / send_failed / ai_unavailable
Mensagem de referência ou resposta rápida inválida, encaminhamento entre canais de tipos diferentes, falha do canal ao enviar, ou assistente de IA indisponível.
409 merge_required
O contato já tem conversa no canal de destino. Repita a transferência com "confirm_merge": true para unir as duas.
404 not_found
A conversa ou a mensagem não existe ou não é visível para a chave.
403 forbidden / company_channel_forbidden
A chave não tem a permissão necessária, ou o usuário API não pode usar o canal de destino.
401 unauthenticated
Chave ausente, inválida, revogada ou expirada.