Centro de ayuda Integración de Meta e Instagram API

Integración de Meta e Instagram API

Referencia para crear una aplicación de Instagram en la Plataforma SMSBAT ChatHub: autenticación, Conversaciones de Instagram Direct, comentarios en publicaciones y Reels, respuestas a historias, webhooks y encuestas.

Fuentes

Esta página fusiona la especificación interna de la API de metacomentarios con la OpenAPI activa. definiciones en https://chatapi.smsbat.com/swagger/v1/swagger.json y https://restapi.smsbat.com/swagger/v1/swagger.json. Cuando los dos no están de acuerdo, el La diferencia se indica en línea y se enumera en Preguntas abiertas.


1. URL base

PropósitoURL
API de chat + Meta APIhttps://chatapi.smsbat.com
Interfaz de usuario Swagger / OpenAPIhttps://chatapi.smsbat.com/index.html · …/swagger/v1/swagger.json
API REST (organizaciones, URL de devolución de llamada)https://restapi.smsbat.com
Arrogancia de API RESThttps://restapi.smsbat.com/swagger/v1/swagger.json
Panel web del operadorhttps://chat.smsbat.com

2. Autenticación

El esquema de autenticación depende del grupo de puntos finales. Mezclarlos es la causa más común de 401.

GrupoEncabezado
chatapi.smsbat.com/api/meta/* (publicaciones, comentarios)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 · Autenticación básica

El token de organización para X-Authorization-Key se emite en el panel bajo Perfil. Los JWT de empresa y operador provienen de /api/company/get-token y /api/operator/get-token.

Discrepancia

El documento chatapi OpenAPI declara un esquema de seguridad único (Bearer) y lo aplica globalmente. X-Authorization-Key no está declarado allí en absoluto, aunque el Meta interno Comentarios La especificación API lo nombra como /api/meta/*. Lo más probable es que sea manejado por middleware que no se refleja en Swagger. Confirme empíricamente antes de realizar el envío.

2.1 Token de empresa

POST https://chatapi.smsbat.com/api/company/get-token
Content-Type: application/json

{ "login": "company_login", "password": "company_password" }

200 OK devuelve una cadena de token simple.

2.2 Organizaciones

GET https://chatapi.smsbat.com/api/company/organization
Authorization: Bearer <company_token>
[ { "id": 24, "name": "My Instagram Store" } ]

2.3 Operadores en una organización

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" }
  }
]

Estados del operador: 0 Activo, 1 Inactivo, 2 Eliminado.

2.4 Agregar/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 devuelve el JWT como una cadena.

2.6 Validar un 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
}

Cuando no es válido: { "isValid": false, "error": "Invalid token" }.

2.7 Incrustar el panel de chat del 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. Enlaces profundos al panel de chat

Un sistema externo (CRM, ERP, sitio web) puede abrir una conversación específica en https://chat.smsbat.com/. El operador está autorizado por un JWT pasado 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ámetroDescripción
chat_raw_idID de chat
phoneNúmero de teléfono en formato internacional
fromIdentificador de cuenta de marca/empresa (bm_id)
sourceFuente de chat: 7 para Instagram, consulte §8.1
tokenOperador JWT válido y vigente con acceso a chats

Un JWT no válido lleva al visitante a la pantalla de inicio de sesión del panel del operador.


4. Conversaciones directas de Instagram

4.1 Listar chats

GET https://chatapi.smsbat.com/api/chat/chats?source=7&page=1&per_page=20
Authorization: Bearer <token>

Note

La paginación aquí es per_page (snake_case). Bajo /api/meta/* y las encuestas El punto final es perPage (camelCase). Esto no es un error tipográfico: la API usa ambos.

Parámetros de consulta, todos opcionales:

ParámetroTipoDescripción
sourceChatSource7 restringe resultados a Instagram
entityIdintID de cuenta comercial. Sólo se aplica junto con source
instagram_user_idintID de usuario de Instagram en ChatHub
facebook_user_idintID de usuario de Facebook en ChatHub
page / per_pageintPaginación, valores predeterminados 1 / 20
statusChatStatus[]Estado del chat, repetible
searchstringBúsqueda de texto libre (nombre, teléfono,…)
organizationIdintID de organización
operatorIdint[]Filtrar por operadores asignados
datestring[]Dos límites: ?date=…&date=…
isChainboolDevolver chats como cadenas, llevando mensajes de chats anteriores
isUnread, starMark, isOperator, isAIAgentboolFiltros adicionales
phone, email, contactId, clientId, tagIds, rate, sortedBy—Otros filtros

200 OK devuelve 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": []
    }
  ]
}

Los campos que importan para una aplicación de Instagram:

CampoSignificado
instaAccountLa cuenta comercial de Instagram (la tienda). id es el valor del filtro entityId; name es el nombre de la cuenta de Meta
instagramUserEl cliente**. name es el identificador de Instagram, id es el valor del filtro instagram_user_id
metaUserIdID de ámbito del cliente en el lado de Meta (cadena)
messSource7 para Instagram
phoneGeneralmente null para Instagram: no lo use como clave

ChatDTO también lleva 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 y taggedMessages.

4.2 Mensajes de chat

GET https://chatapi.smsbat.com/api/chat/chats/1867/messages?isChain=false
Authorization: Bearer <token>

200 OK devuelve una 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 se completa cuando el mensaje se relaciona con una publicación o historia de Instagram: páselo directamente de regreso como id / postId a la Meta API. media es un ChatMediaDTO: { name, format, type, uri, raw, length, isUploaded }.

4.3 Enviar un mensaje (JSON)

POST https://chatapi.smsbat.com/api/chat/1867/message
Authorization: Bearer <token>
Content-Type: application/json

Cuerpo - 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
  }
}
CampoTipoDescripción
textMessagestring?Texto del mensaje. Puede estar vacío cuando media está presente
authorAuthorMessage?0 operador, 1 cliente
isInternalbool?true marca una nota interna que no se entrega al cliente
replyToMessageIdint?ID del mensaje al que se responde
appGuiduuid?GUID de referencia
mediaMediaDTO?{ name, format, dataBase64, thumbnail, duration, type }

200 OK → { "id": 9930, "messageStatus": 0 }

También se puede pasar un GUID de referencia en la ruta: POST /api/chat/{chatId}/{referralGuid}/message (igualmente …/message/v1, …/message/v2).

4.4 Enviar un archivo o vídeo (multiparte, v2)

POST https://chatapi.smsbat.com/api/chat/1867/message/v2
Authorization: Bearer <token>
Content-Type: multipart/form-data

Los nombres de los campos del formulario son PascalCase con notación de puntos

textMessage y media.file se ignoran silenciosamente. Utilice los nombres exactos a continuación.

Campo de formularioTipoDescripción
TextMessagestringTexto del mensaje
Authorint0 operador, 1 cliente
IsInternalboolNota interna
ReplyToMessageIdintMensaje respondido a
AppGuiduuidGUID de referencia
Media.FilebinaryEl archivo en sí
Media.NamestringNombre del archivo
Media.FormatstringTipo MIME (video/mp4, image/png, application/pdf)
Media.TypeMediaTypeVéase §8.5
Media.DataBase64stringAlternativa a Media.File
Media.ThumbnailstringCuadro de vista previa de vídeo Base64
Media.DurationdoubleDuración del vídeo en 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 Cambiar el estado del chat

PUT https://chatapi.smsbat.com/api/chat/status
Authorization: Bearer <token>
Content-Type: application/json

{ "id": 1867, "status": 4 }

200 OK hace eco del objeto actualizado.

4.6 Actualizar estados de mensajes

PUT https://chatapi.smsbat.com/api/chat/messages/status
Authorization: Bearer <token>
Content-Type: application/json

{ "status": 3, "messageIds": [9928, 9929] }

4.7 Eliminar un chat

DELETE https://chatapi.smsbat.com/api/chat/chats/1867
Authorization: Bearer <token>

5. Publicaciones, carretes e historias

Ruta base: https://chatapi.smsbat.com/api/meta Autenticación: X-Authorization-Key: <organization token>

5.1 Listar publicaciones, carretes e historias

GET https://chatapi.smsbat.com/api/meta/posts?platform=instagram&mediaType=story&page=1&perPage=20
X-Authorization-Key: <token>
ParámetroTipoRequeridoDescripción
pageintnoPágina, predeterminada 1
perPageintnoElementos por página, predeterminado 20
idintnoFiltrar por ID de publicación interna
platformstringnoinstagram o facebook
mediaTypestringnopost, reel o story. Todos los tipos cuando se omite
# 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"
      }
    }
  ]
}

Discrepancia - nombre del campo del contador

El esquema Swagger MetaCommentPostListItemDtoPaginationDTO define total. el Documentos de especificaciones internas totalCount. Swagger se genera a partir del código, por lo que total es la verdad más probable. Analice total ?? totalCount hasta que esto se resuelva.

CampoDescripción
idID de publicación interna
metaIdPublicación externa/Reel/ID de historia en Meta
textTítulo de la publicación
imageUrlURL de medios proxy codificada por MetaPost.Guid o null no secuencial
platformfacebook o instagram
mediaTypepost, reel o story
createdAtFecha de creación (fecha de la plataforma o fecha de la base de datos)
storyPresente solo por mediaType: "story"
story.idID de historia interna; igual a post.id
story.metaIdID de historia externa en Meta
story.urlURL proxy estable de los medios Story almacenados; null si no se pudieron guardar los medios

Los medios postales se sirven por dos rutas: GET /api/meta/post/media/{id:int} para atrás compatibilidad y GET /api/meta/post/media/{guid:guid}. Nuevas respuestas API y devoluciones de llamada genere siempre el formulario GUID.

5.2 Listar comentarios

GET https://chatapi.smsbat.com/api/meta/comments?platform=instagram&postId=42&page=1&perPage=20
X-Authorization-Key: <token>
ParámetroTipoRequeridoDescripción
pageintnoPágina, predeterminada 1
perPageintnoElementos por página, predeterminado 20
postIdintnoFiltrar por ID de publicación
parentCommentIdintnoComentarios secundarios (respuestas) de un comentario determinado
platformstringnofacebook o 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..."
      }
    }
  ]
}
CampoDescripción
idID de comentario interno
metaIdID externo en Meta. null por una respuesta nuestra pendiente hasta que sea enviada
textTexto del comentario
createdAtFecha de creación
platformfacebook o instagram
replyStatusnull para un comentario de usuario entrante; "pending" / "sent" / "failure" por nuestra respuesta
author.type"meta_user" usuario externo, "owner" propietario de la página
author.nameNombre del autor
author.metaUserIdID de usuario con ámbito en Meta; null para "owner"
postLa publicación, carrete o historia a la que pertenece el comentario
post.mediaTypepost, reel o story
post.storyReferencia de la historia { id, metaId, url }, solo historias
mediaUrlMedios adjuntos al comentario, o null
replyToComentario de los padres { id, metaId, text }; null al máximo nivel

Discrepancia - tipo de `author.type`

La especificación interna documenta las cadenas "meta_user" / "owner". Tipos de arrogancia MetaCommentAuthorType como entero con enumeración [0, 1]. Un JsonStringEnumConverter explicaría la brecha, pero esto no se ha confirmado con una respuesta real. Escribe un analizador que acepta ambos.

5.3 Responder a un comentario

Pone en cola una respuesta para su 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"

Cuerpo de la solicitud: { "text": "Reply text" }

202 Accepted devuelve el objeto comentario (la misma forma que GET /api/meta/comments) con replyStatus: "pending" y metaId: null. El resultado de la entrega llega más tarde como source: 13 devolución de llamada (§6.4).

Discrepancia - código de respuesta

Swagger declara 200 sin cuerpo; la especificación interna declara 202 Accepted con el comentario como cuerpo. Lo más probable es que al controlador le falte un ProducesResponseType atributo, dejando Swagger en su valor predeterminado. Acepta cualquier 2xx y no dependas de un cuerpo.


6. Webhooks

SMSBAT envía POST solicitudes con application/json a su URL y espera HTTP 200 de respuesta.

Los campos nulos se omiten por completo

Un campo cuyo valor es null no se serializa en absoluto en el cuerpo de la devolución de llamada. por un mensaje que no proviene de Facebook o Instagram simplemente no hay una clave MetaUserId. Trate “ausente” y null como la misma cosa.

6.1 Registrar una URL de devolución de llamada

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
  }'
CampoTipoDescripción
urlstringSu punto final
sourceSendingSourceCallbackTipo de evento, consulte §8.2
headerName / headerValuestringEncabezado de autenticación arbitrario que adjuntamos a la solicitud (opcional)
channelTypeChatSourceCanal. 7 para Instagram. Opcional
channelEntityIdintUna cuenta comercial específica. Requiere channelType

Sin channelType la URL recibe eventos de todos los canales.

Tip

La cobertura completa de comentarios necesita dos registros: source: 12 para nuevos comentarios y source: 13 para estados de respuesta. Para respuestas directas y de historias, agregue source: 3 (y 11 si quieres todos los mensajes de chat).

Operaciones 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 devuelve:

[
  {
    "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 Nuevo mensaje y respuesta a la historia de Instagram (source: 3, 11)

La respuesta de un usuario a una Historia de Instagram llega como un mensaje normal en estas devoluciones de llamada. con un bloque Story adicional de nivel 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"
  }
}
CampoDescripción
ChatId / MessageIdIdentificadores de chat y mensajes
Author0 usuario, 1 operador
UsernameNombre para mostrar o identificador de Instagram/Facebook
UserIdID de usuario numérico interno en SMSBAT
MetaUserIdID de ámbito del interlocutor de conversación en Meta. En un mensaje de operador saliente, esto aún identifica al metausuario del chat, no al operador
ShopIdID interno de la cuenta comercial de Instagram/Facebook
ShopNameNombre de la cuenta comercial recibido de Meta en el momento de la conexión
MessageTextTexto del mensaje
MessageMediaURL de medios cuando el mensaje es multimedia
type_messengerFuente, 7 para Instagram
operator_nameNombre del operador cuando Author = 1
StoryPresentar solo en una respuesta entrante de Historia
Story.IdID de historia interna (MetaPost): utilizable directamente como id / postId en Meta API
Story.MetaIdID de historia externa en Meta
Story.UrlURL de proxy estable de los medios de Story almacenados. Ausente cuando no se pudieron guardar los medios: el bloque Story y el mensaje aún se entregan

`Author` está invertido en relación con la API de chat

En ChatMessageDTO.author, 0 significa operador y 1 significa cliente. En esta devolución de llamada es al revés: 0 es el usuario, 1 es el operador. No compartas el mapeo.

6.3 Nuevo comentario (source: 12)

Se activa cuando un usuario Meta comenta en una publicación de Facebook o una publicación/Reel de Instagram.

Note

Instagram Las respuestas a las historias no se entregan a través del source: 12. Llegan con normalidad mensajes entrantes en source: 3 y/o 11 con un bloque 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 Estado de respuesta al comentario (source: 13)

Se activa después de que intentamos dar una respuesta, ya sea que tenga éxito o falle.

{
  "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 devolución de llamada de comentarios compartidos

Ambas devoluciones de llamada de comentarios comparten una forma de cuerpo y solo difieren en type.

CampoDescripción
type"new_comment" o "comment_status"
platform"facebook" o "instagram"
comment.idID de comentario interno
comment.metaIdID externa en Meta; null para una respuesta pendiente antes de enviarla
comment.parentCommentIdID de comentario de los padres. Ausente para un comentario de nivel superior
comment.parentMetaIdID de comentario externo de los padres. Ausente al máximo nivel
comment.parentCommentTextTexto de comentario de los padres. Ausente al máximo nivel
comment.textTexto del comentario
comment.createdAtFecha de creación
comment.updatedAtÚltima actualización. Ausente si el comentario nunca fue editado
comment.replyStatus"pending" / "sent" / "failure". Ausente para un comentario de usuario entrante
comment.author.type"meta_user" o "owner"
comment.author.nameNombre del autor
comment.author.metaUserIdID de autor con alcance en Meta. Ausente por "owner"
comment.mediaUrlMedios de comentarios. Ausente cuando no hay ninguno
post.idID de publicación interna
post.metaIdPublicación externa/Reel/ID de historia en Meta
post.textPublicar texto
post.imageUrlPublicar URL de la imagen, o null
post.createdAtFecha de creación de la publicación
post.mediaTypeEn devoluciones de llamada de comentarios, solo post o reel

6.6 Nuevo chat (source: 7)

{ "ChatId": 12345, "Phone": "+380501234567", "chat.Source": 7 }

6.7 Cambios de estado de mensajes y chats (source: 6 / 5)

{ "name": "changed_message_status", "id": 9928, "status": 6 }
{ "name": "changed_chat_status",    "id": 1867, "status": 4 }

6.8 Mensaje editado o eliminado (source: 9)

{ "messageId": 9930, "text": "Updated message text" }
{ "messageId": 9931, "delete": true }

6.9 Indicador de escritura (source: 8)

{ "chat_id": 1867, "event": "start_typing", "operator_name": "Iryna" }
{ "chat_id": 1867, "event": "end_typing" }

7. Encuesta de eventos

Para entornos que no pueden aceptar HTTP entrante.

7.1 Recuperar eventos

GET https://chatapi.smsbat.com/api/chat/callback-events?page=1&perPage=20
Authorization: Bearer <token>
ParámetroDescripción
organizationIdOpcional. Tomado del token cuando se omite
page / perPagePaginación, valores predeterminados 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 lleva event_guid, timestamp, organization_id y callback_type - un cadena que coincide con los valores source en §8.2. Los campos restantes coinciden con los correspondientes. webhook en §6.

7.2 Confirmar eventos procesados

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 }

Los eventos ya eliminados simplemente no cuentan para deleted. Realizar pedidos y reintentar son suyos. responsabilidad del lado.

7.3 Bucle recomendado

  1. Encuesta GET /api/chat/callback-events según un cronograma.
  2. Procesa los eventos en tu servicio.
  3. Envíe la lista event_guid procesada a /callback-events/processed.
  4. Repita.

8. Referencia de enumeración

8.1 ChatSource — canal (0–9)

CódigoCanal
0Viber
1ViberBot
2TelegramaBot
3WhatsApp
4Reproductor
5Rozetka
6Facebook
7Instagram
8Fiesta de graduación
9Olx

8.2 SendingSourceCallback — tipo de evento de devolución de llamada (0–13)

CódigoEvento
3Chat — nuevo mensaje de chat, incluidas las respuestas de la historia
5El estado del chat cambió
6Estado del mensaje cambiado
7Nuevo chat creado
8Indicador de escritura
9Mensaje actualizado o eliminado
11AnyChatMessage — cualquier mensaje de chat
12MetaNewComment — nuevo comentario de Instagram/Facebook
13MetaCommentStatus — estado de entrega de nuestra respuesta al comentario

La enumeración abarca 0–13; los valores restantes no son necesarios para las integraciones de Instagram.

8.3 ChatStatus (0–4)

0 Nuevo, 1 Abierto, 2 En espera, 3 En pausa, 4 Cerrado

8,4 MessageStatus (0–11)

CódigoNombre
0NUEVO
1ÉXITO
2RECHAZADO
3LEER
4DESCONOCIDO
5PROCESAMIENTO
6ENTREGADO
7BLOQUEADO_POR_USUARIO
8USUARIO_NO_ENCONTRADO

La enumeración abarca 0–11. Los valores 9, 10 y 11 existen en la API pero aún no están documentados: trátelos como UNKNOWN.

8,5 MediaType (1–10)

1 Foto, 2 Archivo, 3 Audio, 4 Vídeo, 5 Adhesivo, 6 Adhesivo animado, 7 StickerVideo, 8 Animación, 9 Voz, 10 VideoNote

8.6 AuthorMessage — autor en Chat API (0–4)

0 Operador, 1 Cliente, 2 Bot, 3 ViberAccount

La enumeración abarca 0–4; El valor 4 no está documentado. Las devoluciones de llamada de “mensaje nuevo” utilizan el mapeo opuesto — ver §6.2.

8,7 ChatMessageType (0–2)

0 Texto, 1 Foto, 2 Archivo

8.8 Comentario replyStatus

null comentario de usuario entrante, "pending" nuestra respuesta está en cola, "sent" entregada, "failure" la entrega falló.


Preguntas abiertas

Tres puntos en los que la especificación interna y el Swagger generado por el código no están de acuerdo. uno la solicitud con un token real los liquida todos; Hasta entonces, escriba al cliente a la defensiva.

#PreguntaEspecificaciónArroganciaCómo comprobarlo
1Encabezado de autenticación para /api/meta/*X-Authorization-Keysólo Bearer declaradocurl -i -H "X-Authorization-Key: <token>" ".../api/meta/posts?perPage=1" — espere 200, no 401
2Campo de contador en Meta respuestastotalCounttotalMisma solicitud: lea la clave JSON raíz
3author.type tipo y reply código de estado"meta_user" / "owner", 202 con cuerpoint [0,1], 200 sin cuerpocurl -i .../api/meta/comments?perPage=1 más una respuesta de prueba

Orientación provisional:

  • contador - lea total ?? totalCount;
  • author.type: acepta tanto una cadena como un número entero (0 ↔ meta_user, 1 ↔ owner, asignación por confirmar);
  • reply: trate cualquier 2xx como un éxito, no requiera ningún cuerpo, tome el estado final de la devolución de llamada source: 13.

Notas de implementación

  • La autenticación difiere según el grupo de puntos finales: /api/meta/* usa X-Authorization-Key, chats y los operadores usan Bearer, restapi acepta cualquiera de los dos.
  • La paginación se escribe de dos maneras: per_page en /api/chat/chats, perPage en /api/meta/* y /api/chat/callback-events.
  • multipart/form-data los campos son PascalCase con notación de puntos (Media.File, Media.Type).
  • Los campos nulos se omiten en las devoluciones de llamada: una clave ausente significa null.
  • phone suele ser null en Instagram. Identificar al cliente por instagramUser.id / metaUserId y comprar por instaAccount.id (el valor del filtro entityId).
  • Story.Id de una devolución de llamada se puede pasar directamente como id / postId a la Meta API.
  • Verifique el JWT del operador expiresAt antes de usarlo en un enlace profundo o en el widget.