Integração de API Meta e Instagram
Referência para construção de um aplicativo Instagram na Plataforma SMSBAT ChatHub: autenticação, Conversas do Instagram Direct, comentários em postagens e Momentos, respostas de histórias, webhooks e enquetes.
Fontes
Esta página mescla a especificação interna da API Meta Comments com a OpenAPI ativa
definições em https://chatapi.smsbat.com/swagger/v1/swagger.json e
https://restapi.smsbat.com/swagger/v1/swagger.json. Onde os dois discordam, o
a diferença é destacada in-line e listada em Perguntas abertas.
1. URLs básicos
| Finalidade | URL |
|---|---|
| API de bate-papo + MetaAPI | https://chatapi.smsbat.com |
| UI Swagger / OpenAPI | https://chatapi.smsbat.com/index.html · …/swagger/v1/swagger.json |
| API REST (organizações, URLs de retorno de chamada) | https://restapi.smsbat.com |
| Arrogância da API REST | https://restapi.smsbat.com/swagger/v1/swagger.json |
| Painel web do operador | https://chat.smsbat.com |
2. Autenticação
O esquema de autenticação depende do grupo de endpoints. Misturá-los é a causa mais comum de 401.
| Grupo | Cabeçalho |
|---|---|
chatapi.smsbat.com/api/meta/* (postagens, comentários) | X-Authorization-Key: <organization token> |
chatapi.smsbat.com/api/chat/*, /api/company/*, /api/operator/* | Authorization: Bearer <JWT> |
restapi.smsbat.com/* | X-Authorization-Key · Authorization: Bearer · Autenticação Básica |
O token de organização para X-Authorization-Key é emitido no painel em Perfil.
Os JWTs da empresa e da operadora vêm de /api/company/get-token e /api/operator/get-token.
Discrepância
O documento chatapi OpenAPI declara um único esquema de segurança — Bearer — e o aplica
globalmente. X-Authorization-Key não é declarado lá, embora o Meta interno
A especificação da API de comentários nomeia-o como /api/meta/*. Provavelmente é tratado por
middleware que não é refletido no Swagger. Confirme empiricamente antes de enviar.
2.1 Token da empresa
POST https://chatapi.smsbat.com/api/company/get-token
Content-Type: application/json
{ "login": "company_login", "password": "company_password" }
200 OK retorna uma string de token simples.
2.2 Organizações
GET https://chatapi.smsbat.com/api/company/organization
Authorization: Bearer <company_token>
[ { "id": 24, "name": "My Instagram Store" } ]
2.3 Operadores em uma organização
GET https://chatapi.smsbat.com/api/operator?organizationId=24
Authorization: Bearer <company_token>
[
{
"id": 21,
"name": "Jane Doe",
"status": 0,
"organization": { "id": 24, "name": "My Instagram Store" }
}
]
Status do operador: 0 Ativo, 1 Inativo, 2 Excluído.
2.4 Adicionar/sincronizar operadores
POST https://chatapi.smsbat.com/api/operator/synchronize
Authorization: Bearer <company_token>
Content-Type: application/json
[ { "organizationId": 24, "name": "John Operator" } ]
200 OK → [ { "id": 21, "status": 0, "name": "John Operator" } ]
2.5 Operador JWT
POST https://chatapi.smsbat.com/api/operator/get-token
Authorization: Bearer <company_token>
Content-Type: application/json
{ "id": 21, "expiresAt": "2026-12-31T23:59:59.000Z" }
200 OK retorna o JWT como uma string.
2.6 Validar um token de operador
POST https://chatapi.smsbat.com/api/operator/validate-token
Authorization: Bearer <company_token>
Content-Type: application/json
"eyJhbGciOi..."
{
"isValid": true,
"operatorId": 21,
"clientId": 0,
"expiresAt": "2026-12-31T23:59:59.000Z",
"error": null
}
Quando inválido: { "isValid": false, "error": "Invalid token" }.
2.7 Incorporar o painel de bate-papo do operador
<script type="module" id="operator-chat-panel-script"
src="https://widget.smsbat.com/operator-chat-panel/widget-script.js"
token="YOUR_OPERATOR_JWT_TOKEN"></script>
3. Links diretos para o painel de bate-papo
Um sistema externo (CRM, ERP, site) pode abrir uma conversa específica em
https://chat.smsbat.com/. O operador é autorizado por um JWT passado como parâmetro de consulta.
https://chat.smsbat.com/?chat_raw_id=<chat_id>&token=<jwt>
https://chat.smsbat.com/?phone=<phone>&token=<jwt>
https://chat.smsbat.com/?from=<bm_id>&phone=<phone>&token=<jwt>
https://chat.smsbat.com/?source=7&from=<bm_id>&phone=<phone>&token=<jwt>
| Parâmetro | Descrição |
|---|---|
chat_raw_id | ID do bate-papo |
phone | Número de telefone em formato internacional |
from | Identificador de marca/conta comercial (bm_id) |
source | Fonte de bate-papo — 7 para Instagram, consulte §8.1 |
token | Operador JWT válido e não expirado com acesso a chats |
Um JWT inválido leva o visitante à tela de login do painel do operador.
4. Conversas diretas do Instagram
4.1 Listar bate-papos
GET https://chatapi.smsbat.com/api/chat/chats?source=7&page=1&per_page=20
Authorization: Bearer <token>
Note
A paginação aqui é per_page (snake_case). Sob /api/meta/* e a votação
ponto final é perPage (camelCase). Isso não é um erro de digitação — a API usa ambos.
Parâmetros de consulta, todos opcionais:
| Parâmetro | Tipo | Descrição |
|---|---|---|
source | ChatSource | 7 restringe resultados ao Instagram |
entityId | int | ID da conta comercial. Aplicado apenas em conjunto com source |
instagram_user_id | int | ID de usuário do Instagram no ChatHub |
facebook_user_id | int | ID de usuário do Facebook no ChatHub |
page / per_page | int | Paginação, padrões 1 / 20 |
status | ChatStatus[] | Status do bate-papo, repetível |
search | string | Pesquisa de texto livre (nome, telefone, …) |
organizationId | int | ID da organização |
operatorId | int[] | Filtrar por operadores atribuídos |
date | string[] | Dois limites: ?date=…&date=… |
isChain | bool | Retornar chats como correntes, transportando mensagens de chats anteriores |
isUnread, starMark, isOperator, isAIAgent | bool | Filtros adicionais |
phone, email, contactId, clientId, tagIds, rate, sortedBy | — | Outros filtros |
200 OK retorna GetChatsResponse:
{
"total": 1,
"newMessagesCount": 2,
"items": [
{
"id": 1867,
"theme": null,
"messSource": 7,
"chatStatus": 1,
"countUnread": 2,
"metaUserId": "1585775752382460",
"instaAccount": { "id": 12, "name": "my_instagram_shop", "photo": "https://..." },
"instagramUser": { "id": 123, "name": "marianna_cat", "photo": "https://..." },
"operator": { "id": 21, "name": "Jane", "photo": "https://..." },
"client": { "id": 55, "name": "Marianna", "photo": null },
"textLastMess": "Hello! Is this product available?",
"timeLastMess": "2026-08-13T10:15:00Z",
"authorLastMessage": 1,
"messageStatus": 6,
"isMedia": false,
"phone": null,
"organizationId": 1,
"createdAt": "2026-08-13T10:14:00Z",
"isStarred": false,
"isBlocked": false,
"tags": []
}
]
}
Os campos importantes para um aplicativo Instagram:
| Campo | Significado |
|---|---|
instaAccount | A conta empresarial do Instagram (a loja). id é o valor do filtro entityId; name é o nome da conta do Meta |
instagramUser | O cliente**. name é o identificador do Instagram, id é o valor do filtro instagram_user_id |
metaUserId | O ID do escopo do cliente no lado do Meta (string) |
messSource | 7 para Instagram |
phone | Normalmente null para Instagram — não use como chave |
ChatDTO também carrega olxUser, promUser, waba, rozetkaUser, facebookAccount,
facebookUser, viberAccount, tgBot, tgUser, viberBot, viberBotUser, widget,
media, isConnectedAI, isPromo, rate, rateComment, closedBy, draft, lang,
starMark, contactId, contactName, block, isInStopList, stopList,
isSmsFallbackEnabled e taggedMessages.
4.2 Mensagens de bate-papo
GET https://chatapi.smsbat.com/api/chat/chats/1867/messages?isChain=false
Authorization: Bearer <token>
200 OK retorna uma matriz de ChatMessageDTO:
[
{
"id": 9928,
"chatId": 1867,
"message": "Hi! Do you have size M in stock?",
"messageTranslation": null,
"phone": null,
"author": 1,
"source": 7,
"media": null,
"replyTo": null,
"status": 6,
"date": "2026-08-13T10:14:00Z",
"operator": null,
"client": { "id": 123, "name": "marianna_cat", "photo": "https://..." },
"messageType": 0,
"isInternal": false,
"isBroadcast": false,
"starMark": false,
"referralGuid": null,
"postId": null,
"isConnectedAI": false,
"organizationId": 1,
"countUnreadMessages": 0
}
]
postId é preenchido quando a mensagem está relacionada a uma postagem ou história do Instagram – passe-a
retorne como id / postId para a Meta API. media é um ChatMediaDTO:
{ name, format, type, uri, raw, length, isUploaded }.
4.3 Enviar uma mensagem (JSON)
POST https://chatapi.smsbat.com/api/chat/1867/message
Authorization: Bearer <token>
Content-Type: application/json
Corpo — SendChatMessageDTO:
{
"textMessage": "Hello! Yes, size M is available.",
"author": 0,
"isInternal": false,
"replyToMessageId": 9928,
"appGuid": "550e8400-e29b-41d4-a716-446655440000",
"media": {
"name": "item.jpg",
"format": "image/jpeg",
"dataBase64": "/9j/4AAQSkZJRg...",
"type": 1
}
}
| Campo | Tipo | Descrição |
|---|---|---|
textMessage | string? | Texto da mensagem. Pode estar vazio quando media estiver presente |
author | AuthorMessage? | 0 operador, 1 cliente |
isInternal | bool? | true marca nota interna que não é entregue ao cliente |
replyToMessageId | int? | ID da mensagem que está sendo respondida |
appGuid | uuid? | GUID de referência |
media | MediaDTO? | { name, format, dataBase64, thumbnail, duration, type } |
200 OK → { "id": 9930, "messageStatus": 0 }
Um GUID de referência também pode ser passado no caminho:
POST /api/chat/{chatId}/{referralGuid}/message (da mesma forma …/message/v1, …/message/v2).
4.4 Enviar um arquivo ou vídeo (multipart, v2)
POST https://chatapi.smsbat.com/api/chat/1867/message/v2
Authorization: Bearer <token>
Content-Type: multipart/form-data
Os nomes dos campos do formulário são PascalCase com notação de ponto
textMessage e media.file são ignorados silenciosamente. Use os nomes exatos abaixo.
| Campo do formulário | Tipo | Descrição |
|---|---|---|
TextMessage | string | Texto da mensagem |
Author | int | 0 operador, 1 cliente |
IsInternal | bool | Nota interna |
ReplyToMessageId | int | Mensagem sendo respondida |
AppGuid | uuid | GUID de referência |
Media.File | binary | O próprio arquivo |
Media.Name | string | Nome do arquivo |
Media.Format | string | Tipo MIME (video/mp4, image/png, application/pdf) |
Media.Type | MediaType | Consulte §8.5 |
Media.DataBase64 | string | Alternativa para Media.File |
Media.Thumbnail | string | Quadro de visualização de vídeo Base64 |
Media.Duration | double | Duração do vídeo em segundos |
curl -X POST "https://chatapi.smsbat.com/api/chat/1867/message/v2" \
-H "Authorization: Bearer <token>" \
-F "TextMessage=Here is the price list" \
-F "Author=0" \
-F "Media.Type=2" \
-F "Media.File=@./price.pdf"
200 OK → { "id": 9931, "messageStatus": 0 }
4.5 Alterar status do bate-papo
PUT https://chatapi.smsbat.com/api/chat/status
Authorization: Bearer <token>
Content-Type: application/json
{ "id": 1867, "status": 4 }
200 OK ecoa o objeto atualizado.
4.6 Atualizar status de mensagens
PUT https://chatapi.smsbat.com/api/chat/messages/status
Authorization: Bearer <token>
Content-Type: application/json
{ "status": 3, "messageIds": [9928, 9929] }
4.7 Excluir um bate-papo
DELETE https://chatapi.smsbat.com/api/chat/chats/1867
Authorization: Bearer <token>
5. Postagens, Momentos e Histórias
Caminho base: https://chatapi.smsbat.com/api/meta
Autorização: X-Authorization-Key: <organization token>
5.1 Listar postagens, Momentos e Histórias
GET https://chatapi.smsbat.com/api/meta/posts?platform=instagram&mediaType=story&page=1&perPage=20
X-Authorization-Key: <token>
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
page | int | não | Página, padrão 1 |
perPage | int | não | Itens por página, padrão 20 |
id | int | não | Filtrar por ID de postagem interna |
platform | string | não | instagram ou facebook |
mediaType | string | não | post, reel ou story. Todos os tipos quando omitidos |
# Every post
curl -H "X-Authorization-Key: <token>" \
"https://chatapi.smsbat.com/api/meta/posts?page=1&perPage=10"
# Instagram only
curl -H "X-Authorization-Key: <token>" \
"https://chatapi.smsbat.com/api/meta/posts?platform=instagram"
# A single post by ID
curl -H "X-Authorization-Key: <token>" \
"https://chatapi.smsbat.com/api/meta/posts?id=42"
# Instagram Stories only
curl -H "X-Authorization-Key: <token>" \
"https://chatapi.smsbat.com/api/meta/posts?platform=instagram&mediaType=story"
200 OK:
{
"total": 42,
"items": [
{
"id": 42,
"metaId": "18113450675314072",
"text": "Check out our new collection!",
"imageUrl": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-1711-4aa8-b21d-f6dbf8f347ef",
"platform": "instagram",
"mediaType": "story",
"createdAt": "2026-07-22T09:35:30Z",
"story": {
"id": 42,
"metaId": "18113450675314072",
"url": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-1711-4aa8-b21d-f6dbf8f347ef"
}
}
]
}
Discrepância — nome do campo do contador
O esquema Swagger MetaCommentPostListItemDtoPaginationDTO define total. O
documentos de especificações internas totalCount. Swagger é gerado a partir do código, então
total é a verdade mais provável. Analise total ?? totalCount até que isso seja resolvido.
| Campo | Descrição |
|---|---|
id | ID da postagem interna |
metaId | Postagem externa / Reel / ID da história no Meta |
text | Legenda da postagem |
imageUrl | URL de mídia proxy codificado pelo não sequencial MetaPost.Guid ou null |
platform | facebook ou instagram |
mediaType | post, reel ou story |
createdAt | Data de criação (data da plataforma ou data da base de dados) |
story | Presente apenas por mediaType: "story" |
story.id | ID interno da história; igual a post.id |
story.metaId | ID de história externa em Meta |
story.url | URL de proxy estável da mídia Story armazenada; null se a mídia não puder ser salva |
A pós-mídia é atendida por duas rotas: GET /api/meta/post/media/{id:int} para trás
compatibilidade e GET /api/meta/post/media/{guid:guid}. Novas respostas e retornos de chamada da API
sempre gere o formulário GUID.
5.2 Listar comentários
GET https://chatapi.smsbat.com/api/meta/comments?platform=instagram&postId=42&page=1&perPage=20
X-Authorization-Key: <token>
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
page | int | não | Página, padrão 1 |
perPage | int | não | Itens por página, padrão 20 |
postId | int | não | Filtrar por ID da postagem |
parentCommentId | int | não | Comentários secundários (respostas) de um determinado comentário |
platform | string | não | facebook ou instagram |
200 OK:
{
"total": 100,
"items": [
{
"id": 5,
"metaId": "179000000000005",
"text": "What is the price?",
"createdAt": "2026-04-15T10:30:00Z",
"platform": "instagram",
"replyStatus": null,
"author": {
"type": "meta_user",
"name": "John Doe",
"metaUserId": "1585775752382460"
},
"post": {
"id": 1,
"metaId": "18113450675314072",
"text": null,
"imageUrl": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-…",
"createdAt": "2026-07-22T09:35:30Z",
"mediaType": "story",
"story": {
"id": 1,
"metaId": "18113450675314072",
"url": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-…"
}
},
"mediaUrl": "https://chatapi.smsbat.com/api/meta/comment/media/5",
"replyTo": {
"id": 3,
"metaId": "179000000000003",
"text": "Parent comment..."
}
}
]
}
| Campo | Descrição |
|---|---|
id | ID do comentário interno |
metaId | ID externo em Meta. null por uma resposta nossa pendente até o seu envio |
text | Texto do comentário |
createdAt | Data de criação |
platform | facebook ou instagram |
replyStatus | null para um comentário de usuário recebido; "pending" / "sent" / "failure" pela nossa resposta |
author.type | "meta_user" usuário externo, "owner" proprietário da página |
author.name | Nome do autor |
author.metaUserId | ID do usuário com escopo definido no Meta; null para "owner" |
post | A postagem, Momento ou História à qual o comentário pertence |
post.mediaType | post, reel ou story |
post.story | Referência da história { id, metaId, url }, apenas histórias |
mediaUrl | Mídia anexada ao comentário ou null |
replyTo | Comentário pai { id, metaId, text }; null no nível superior |
Discrepância — tipo de `author.type`
A especificação interna documenta as strings "meta_user" / "owner". Tipos de arrogância
MetaCommentAuthorType como um inteiro com enum [0, 1]. Um JsonStringEnumConverter
explicaria a lacuna, mas isso não foi confirmado contra uma resposta real. Escreva um
analisador que aceita ambos.
5.3 Responder a um comentário
Enfileira uma resposta para entrega.
curl -X POST \
-H "X-Authorization-Key: <token>" \
-H "Content-Type: application/json" \
-d '{"text": "Thanks for the feedback!"}' \
"https://chatapi.smsbat.com/api/meta/comments/5/reply"
Corpo da solicitação: { "text": "Reply text" }
202 Accepted retorna o objeto de comentário — mesma forma que GET /api/meta/comments — com
replyStatus: "pending" e metaId: null. O resultado da entrega chega mais tarde como um
source: 13 retorno de chamada (§6.4).
Discrepância — código de resposta
Swagger declara 200 sem corpo; a especificação interna declara 202 Accepted
com o comentário como corpo. O controlador provavelmente não possui um ProducesResponseType
atributo, deixando o Swagger em seu padrão. Aceite qualquer 2xx e não dependa de um corpo.
6. Webhooks
SMSBAT envia solicitações POST com application/json para sua URL e espera HTTP 200 de volta.
Campos nulos são totalmente omitidos
Um campo cujo valor é null não é serializado no corpo do retorno de chamada. Por um
mensagem que não veio do Facebook ou Instagram simplesmente não existe a chave MetaUserId.
Trate “ausente” e null como a mesma coisa.
6.1 Registrar uma URL de retorno de chamada
curl -X POST 'https://restapi.smsbat.com/organizations/callback_urls' \
-H 'X-Authorization-Key: <token>' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://your-server.com/webhook",
"source": 12,
"headerName": "X-Webhook-Secret",
"headerValue": "your-secret",
"channelType": 7,
"channelEntityId": 12
}'
| Campo | Tipo | Descrição |
|---|---|---|
url | string | Seu ponto final |
source | SendingSourceCallback | Tipo de evento, consulte §8.2 |
headerName / headerValue | string | Cabeçalho de autenticação arbitrário que anexamos à solicitação (opcional) |
channelType | ChatSource | Canal. 7 para Instagram. Opcional |
channelEntityId | int | Uma conta comercial específica. Requer channelType |
Sem channelType a URL recebe eventos de todos os canais.
Tip
A cobertura completa dos comentários precisa de dois registros: source: 12 para novos comentários e
source: 13 para status de resposta. Para respostas diretas e de histórias, adicione source: 3
(e 11 se quiser todas as mensagens do chat).
Operações restantes:
GET https://restapi.smsbat.com/organizations/callback_urls?source=12
GET https://restapi.smsbat.com/organizations/callback_urls/{id}
PUT https://restapi.smsbat.com/organizations/callback_urls/{id}
DELETE https://restapi.smsbat.com/organizations/callback_urls/{id}
GET retorna:
[
{
"id": 101,
"url": "https://your-server.com/webhook",
"source": 12,
"headerName": "X-Webhook-Secret",
"headerValue": "your-secret",
"createdAt": "2026-08-13T09:00:00Z",
"channelType": 7,
"channelEntityId": 12
}
]
6.2 Nova mensagem e resposta da história do Instagram (source: 3, 11)
A resposta de um usuário a um Instagram Story chega como uma mensagem comum nesses retornos de chamada,
com um bloco Story extra de nível superior:
{
"ChatId": 123,
"MessageId": 456,
"MessageText": "😍",
"Username": "Jane Smith",
"UserId": 789,
"MetaUserId": "1585775752382460",
"ShopId": 12,
"ShopName": "instagram shop name",
"Author": 0,
"type_messenger": 7,
"Story": {
"Id": 42,
"MetaId": "18113450675314072",
"Url": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-1711-4aa8-b21d-f6dbf8f347ef"
}
}
| Campo | Descrição |
|---|---|
ChatId / MessageId | Identificadores de bate-papo e mensagens |
Author | usuário 0, operador 1 |
Username | Nome de exibição ou identificador do Instagram / Facebook |
UserId | ID de usuário numérico interno em SMSBAT |
MetaUserId | ID com escopo do interlocutor no Meta. Em uma mensagem do operador de saída, isso ainda identifica o metausuário do chat, não o operador |
ShopId | ID interno da conta comercial do Instagram/Facebook |
ShopName | Nome da conta comercial conforme recebido do Meta no momento da conexão |
MessageText | Texto da mensagem |
MessageMedia | URL de mídia quando a mensagem é mídia |
type_messenger | Fonte, 7 para Instagram |
operator_name | Nome do operador quando Author = 1 |
Story | Apresentar apenas em uma resposta de história recebida |
Story.Id | ID da história interna (MetaPost) — utilizável diretamente como id / postId na Meta API |
Story.MetaId | ID de história externa em Meta |
Story.Url | URL de proxy estável da mídia Story armazenada. Ausente quando a mídia não pôde ser salva — o bloco Story e a mensagem ainda são entregues |
`Author` está invertido em relação à API de bate-papo
Em ChatMessageDTO.author, 0 significa operador e 1 significa cliente. Neste retorno de chamada é
o contrário: 0 é o usuário, 1 é o operador. Não compartilhe o mapeamento.
6.3 Novo comentário (source: 12)
Dispara quando um usuário Meta comenta em uma postagem do Facebook ou uma postagem/Reel do Instagram.
Note
Instagram As respostas das histórias não são entregues por meio de source: 12. Elas chegam normalmente
mensagens de entrada em source: 3 e/ou 11 com um bloco Story — consulte §6.2.
{
"type": "new_comment",
"platform": "instagram",
"comment": {
"id": 10,
"metaId": "179000000000010",
"parentCommentId": 5,
"parentMetaId": "179000000000005",
"parentCommentText": "The user's previous comment",
"text": "Great product!",
"createdAt": "2026-04-16T12:00:00Z",
"author": {
"type": "meta_user",
"name": "Jane Smith",
"metaUserId": "1585775752382460"
}
},
"post": {
"id": 1,
"metaId": "123456789012345",
"text": "Post description...",
"imageUrl": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-…",
"createdAt": "2026-04-10T12:00:00Z",
"mediaType": "post"
}
}
6.4 Status da resposta do comentário (source: 13)
Dispara depois que tentamos entregar uma resposta, seja ela bem-sucedida ou falha.
{
"type": "comment_status",
"platform": "instagram",
"comment": {
"id": 15,
"metaId": "179000000000015",
"parentCommentId": 10,
"parentMetaId": "179000000000010",
"parentCommentText": "Great product!",
"text": "Thanks for the feedback!",
"createdAt": "2026-04-16T12:05:00Z",
"updatedAt": "2026-04-16T12:05:03Z",
"replyStatus": "sent",
"author": {
"type": "owner",
"name": "Support Agent"
}
},
"post": {
"id": 1,
"metaId": "179999999999999",
"text": "Reel description...",
"imageUrl": "https://dashboard.smsbat.com/api/meta/post/media/7d124c36-…",
"createdAt": "2026-07-22T09:35:30Z",
"mediaType": "reel"
}
}
6.5 Campos de retorno de chamada de comentário compartilhado
Ambos os retornos de chamada de comentários compartilham um formato de corpo e diferem apenas em type.
| Campo | Descrição |
|---|---|
type | "new_comment" ou "comment_status" |
platform | "facebook" ou "instagram" |
comment.id | ID do comentário interno |
comment.metaId | ID externo em Meta; null para uma resposta pendente antes de ser enviada |
comment.parentCommentId | ID do comentário pai. Ausente para um comentário de nível superior |
comment.parentMetaId | ID do comentário pai externo. Ausente no nível superior |
comment.parentCommentText | Texto de comentário dos pais. Ausente no nível superior |
comment.text | Texto do comentário |
comment.createdAt | Data de criação |
comment.updatedAt | Última atualização. Ausente se o comentário nunca foi editado |
comment.replyStatus | "pending" / "sent" / "failure". Ausente devido a um comentário recebido de um usuário |
comment.author.type | "meta_user" ou "owner" |
comment.author.name | Nome do autor |
comment.author.metaUserId | ID do autor com escopo definido no Meta. Ausente por "owner" |
comment.mediaUrl | Comente a mídia. Ausente quando não há |
post.id | ID da postagem interna |
post.metaId | Postagem externa / Reel / ID da história no Meta |
post.text | Postar texto |
post.imageUrl | Postar URL da imagem ou null |
post.createdAt | Data de pós-criação |
post.mediaType | Em retornos de chamada de comentários, apenas post ou reel |
6.6 Novo bate-papo (source: 7)
{ "ChatId": 12345, "Phone": "+380501234567", "chat.Source": 7 }
6.7 Mudanças no status de mensagens e bate-papo (source: 6 / 5)
{ "name": "changed_message_status", "id": 9928, "status": 6 }
{ "name": "changed_chat_status", "id": 1867, "status": 4 }
6.8 Mensagem editada ou excluída (source: 9)
{ "messageId": 9930, "text": "Updated message text" }
{ "messageId": 9931, "delete": true }
6.9 Indicador de digitação (source: 8)
{ "chat_id": 1867, "event": "start_typing", "operator_name": "Iryna" }
{ "chat_id": 1867, "event": "end_typing" }
7. Pesquisa de eventos
Para ambientes que não aceitam HTTP de entrada.
7.1 Buscar eventos
GET https://chatapi.smsbat.com/api/chat/callback-events?page=1&perPage=20
Authorization: Bearer <token>
| Parâmetro | Descrição |
|---|---|
organizationId | Opcional. Retirado do token quando omitido |
page / perPage | Paginação, padrões 1 / 20 |
{
"page": 1,
"perPage": 20,
"total": 947,
"items": [
{
"ChatId": 1867,
"MessageId": 9928,
"MessageText": "Hello there!",
"MessageMedia": null,
"Phone": null,
"Username": "marianna_cat",
"UserId": 123,
"ShopId": 12,
"ShopName": "instagram shop name",
"Author": 1,
"type_messenger": 7,
"message_date": "2026-08-13T12:27:39.724Z",
"timestamp": "2026-08-13T12:27:39.736Z",
"event_guid": "ff60129e-c6e4-4876-9d90-badb430c0606",
"organization_id": 1,
"callback_type": "3"
}
]
}
Cada evento carrega event_guid, timestamp, organization_id e callback_type — um
string correspondente aos valores source em §8.2. Os campos restantes correspondem ao correspondente
webhook em §6.
7.2 Reconhecer eventos processados
POST https://chatapi.smsbat.com/api/chat/callback-events/processed
Authorization: Bearer <token>
Content-Type: application/json
[ "ff60129e-c6e4-4876-9d90-badb430c0606" ]
200 OK → { "deleted": 1 }
Os eventos já removidos simplesmente não contam para deleted. Pedidos e novas tentativas são seus
responsabilidade do lado.
7.3 Ciclo recomendado
- Enquete
GET /api/chat/callback-eventsde acordo com uma programação. - Processe os eventos em seu serviço.
- Envie a lista
event_guidprocessada para/callback-events/processed. - Repita.
8. Referência de enumeração
8.1 ChatSource — canal (0–9)
| Código | Canal |
|---|---|
| 0 | Viber |
| 1 | ViberBot |
| 2 | TelegramBot |
| 3 | |
| 4 | Widget |
| 5 | Rozetka |
| 6 | |
| 7 | |
| 8 | Baile de formatura |
| 9 | Olx |
8.2 SendingSourceCallback — tipo de evento de retorno de chamada (0–13)
| Código | Evento |
|---|---|
| 3 | Chat — nova mensagem de bate-papo, incluindo respostas de histórias |
| 5 | Status do bate-papo alterado |
| 6 | Status da mensagem alterado |
| 7 | Novo bate-papo criado |
| 8 | Indicador de digitação |
| 9 | Mensagem atualizada ou excluída |
| 11 | AnyChatMessage — qualquer mensagem de bate-papo |
| 12 | MetaNewComment — novo comentário no Instagram/Facebook |
| 13 | MetaCommentStatus — status de entrega da nossa resposta ao comentário |
A enumeração abrange 0–13; os valores restantes não são necessários para integrações com Instagram.
8.3 ChatStatus (0–4)
0 Novo, 1 Aberto, 2 Aguardando, 3 Em pausa, 4 Fechado
8,4 MessageStatus (0–11)
| Código | Nome |
|---|---|
| 0 | NOVO |
| 1 | SUCESSO |
| 2 | REJEITADO |
| 3 | LEIA |
| 4 | DESCONHECIDO |
| 5 | PROCESSAMENTO |
| 6 | ENTREGUE |
| 7 | BLOQUEADO_BY_USER |
| 8 | USER_NOT_FOUND |
A enumeração abrange 0–11. Os valores 9, 10 e 11 existem na API, mas ainda não estão documentados —
trate-os como UNKNOWN.
8,5 MediaType (1–10)
1 Foto, 2 Arquivo, 3 Áudio, 4 Vídeo, 5 Adesivo, 6 Adesivo Animado,
7 AdesivoVídeo, 8 Animação, 9 Voz, 10 VídeoNota
8.6 AuthorMessage — autor na API de bate-papo (0–4)
0 Operador, 1 Cliente, 2 Bot, 3 ViberAccount
A enumeração abrange 0–4; o valor 4 não está documentado. Os retornos de chamada de “nova mensagem” usam o
mapeamento oposto — ver §6.2.
8,7 ChatMessageType (0–2)
0 Texto, 1 Foto, 2 Arquivo
8.8 Comentário replyStatus
null comentário de usuário recebido, "pending" nossa resposta está na fila, "sent" entregue,
"failure" falha na entrega.
Perguntas abertas
Três pontos onde a especificação interna e o Swagger gerado pelo código discordam. Um solicitação com token real liquida todos eles; até então, escreva para o cliente defensivamente.
| # | Pergunta | Especificação | Arrogância | Como verificar |
|---|---|---|---|---|
| 1 | Cabeçalho de autenticação para /api/meta/* | X-Authorization-Key | apenas Bearer declarado | curl -i -H "X-Authorization-Key: <token>" ".../api/meta/posts?perPage=1" — espere 200, não 401 |
| 2 | Campo de contador em respostas Meta | totalCount | total | Mesma solicitação – leia a chave JSON raiz |
| 3 | Tipo author.type e código de status reply | "meta_user" / "owner", 202 com corpo | int [0,1], 200 sem corpo | curl -i .../api/meta/comments?perPage=1 mais uma resposta de teste |
Orientação provisória:
- contador — leia
total ?? totalCount; author.type— aceita uma string e um número inteiro (0↔meta_user,1↔owner, mapeamento a ser confirmado);reply— trata qualquer2xxcomo sucesso, não requer corpo, obtém o status final do retorno de chamadasource: 13.
Notas de implementação
- A autenticação difere por grupo de endpoints —
/api/meta/*usaX-Authorization-Key, bate-papos e os operadores usamBearer,restapitambém aceita. - A paginação é escrita de duas maneiras —
per_pageem/api/chat/chats,perPageem/api/meta/*e/api/chat/callback-events. - Os campos
multipart/form-datasão PascalCase com notação de ponto (Media.File,Media.Type). - Campos nulos são omitidos dos retornos de chamada — uma chave ausente significa
null. phonegeralmente énullno Instagram. Identifique o cliente porinstagramUser.id/metaUserIde a loja porinstaAccount.id(o valor do filtroentityId).Story.Idde um retorno de chamada pode ser passado diretamente comoid/postIdpara a Meta API.- Verifique o
expiresAtdo JWT do operador antes de usá-lo em um deeplink ou widget.