Centre d'aide Intégration des API Meta et Instagram

Intégration des API Meta et Instagram

Référence pour créer une application Instagram sur la Plateforme SMSBAT ChatHub : authentification, Conversations directes Instagram, commentaires sur les publications et les bobines, réponses aux histoires, webhooks et sondages.

Sources

Cette page fusionne la spécification interne de l’API Meta Comments avec l’OpenAPI en direct définitions à https://chatapi.smsbat.com/swagger/v1/swagger.json et https://restapi.smsbat.com/swagger/v1/swagger.json. Là où les deux ne sont pas d’accord, le la différence est signalée en ligne et répertoriée sous Questions ouvertes.


1. URL de base

ObjectifURL
API de chat + méta-APIhttps://chatapi.smsbat.com
Interface utilisateur Swagger / OpenAPIhttps://chatapi.smsbat.com/index.html · …/swagger/v1/swagger.json
API REST (organisations, URL de rappel)https://restapi.smsbat.com
API REST Swaggerhttps://restapi.smsbat.com/swagger/v1/swagger.json
Panneau Web de l’opérateurhttps://chat.smsbat.com

2. Authentification

Le schéma d’authentification dépend du groupe de points de terminaison. Les mélanger est la cause la plus fréquente du 401.

GroupeEn-tête
chatapi.smsbat.com/api/meta/* (messages, commentaires)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 · Authentification de base

Le jeton d’organisation pour X-Authorization-Key est émis dans le panneau sous Profil. Les JWT de l’entreprise et de l’opérateur proviennent de /api/company/get-token et /api/operator/get-token.

Différence

Le document chatapi OpenAPI déclare un schéma de sécurité unique — Bearer — et l’applique à l’échelle mondiale. X-Authorization-Key n’y est pas du tout déclaré, bien que le Meta interne La spécification de l’API Commentaires le nomme /api/meta/*. Il est très probablement géré par middleware qui n’est pas reflété dans Swagger. Confirmez empiriquement avant d’expédier.

2.1 Jeton d’entreprise

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

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

200 OK renvoie une chaîne de jeton nue.

2.2 Organisations

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

2.3 Opérateurs dans une organisation

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

Statuts de l’opérateur : 0 Actif, 1 Inactif, 2 Supprimé.

2.4 Ajouter/synchroniser des opérateurs

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 Opérateur 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 renvoie le JWT sous forme de chaîne.

2.6 Valider un jeton d’opérateur

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
}

Lorsqu’il n’est pas valide : { "isValid": false, "error": "Invalid token" }.

2.7 Intégrer le panneau de discussion de l’opérateur

<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. Liens profonds vers le panneau de discussion

Un système externe (CRM, ERP, site internet) peut ouvrir une conversation spécifique dans https://chat.smsbat.com/. L’opérateur est autorisé par un JWT passé en paramètre de requête.

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>
ParamètreDescriptif
chat_raw_idIdentifiant de discussion
phoneNuméro de téléphone au format international
fromIdentifiant de marque/compte professionnel (bm_id)
sourceSource du chat — 7 pour Instagram, voir §8.1
tokenOpérateur JWT valide et non expiré avec accès aux chats

Un JWT invalide amène le visiteur sur l’écran de connexion du panneau de commande.


4. Conversations directes sur Instagram

4.1 Liste des discussions

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

Note

La pagination ici est per_page (snake_case). Sous /api/meta/* et le scrutin le point final est perPage (camelCase). Ce n’est pas une faute de frappe : l’API utilise les deux.

Paramètres de requête, tous facultatifs :

ParamètreTapezDescriptif
sourceChatSource7 restreint les résultats à Instagram
entityIdintIdentifiant du compte professionnel. Appliqué uniquement avec source
instagram_user_idintID utilisateur Instagram dans ChatHub
facebook_user_idintID utilisateur Facebook dans ChatHub
page / per_pageintPagination, valeurs par défaut 1 / 20
statusChatStatus[]Statut du chat, reproductible
searchstringRecherche en texte libre (nom, téléphone, …)
organizationIdintIdentifiant de l’organisation
operatorIdint[]Filtrer par opérateurs assignés
datestring[]Deux bornes : ?date=…&date=…
isChainboolRenvoie les discussions sous forme de chaînes, transportant les messages des discussions précédentes
isUnread, starMark, isOperator, isAIAgentboolFiltres supplémentaires
phone, email, contactId, clientId, tagIds, rate, sortedBy—Autres filtres

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

Les champs importants pour une application Instagram :

ChampSignification
instaAccountLe Compte professionnel Instagram (la boutique). id est la valeur du filtre entityId ; name est le nom du compte de Meta
instagramUserLe client. name est le pseudo Instagram, id est la valeur du filtre instagram_user_id
metaUserIdL’identifiant du client du côté de Meta (chaîne)
messSource7 pour Instagram
phoneHabituellement null pour Instagram — ne l’utilisez pas comme clé

ChatDTO porte également 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 et taggedMessages.

4.2 Messages de discussion

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

200 OK renvoie un tableau 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 est renseigné lorsque le message concerne une publication ou une histoire Instagram – transmettez-le directement en tant que id / postId à la Meta API. media est un ChatMediaDTO : { name, format, type, uri, raw, length, isUploaded }.

4.3 Envoyer un message (JSON)

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

Corps — 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
  }
}
ChampTapezDescriptif
textMessagestring?Texte du message. Peut être vide lorsque media est présent
authorAuthorMessage?0 opérateur, 1 client
isInternalbool?true marque une note interne qui n’est pas remise au client
replyToMessageIdint?ID du message auquel on répond
appGuiduuid?GUID de référence
mediaMediaDTO?{ name, format, dataBase64, thumbnail, duration, type }

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

Un GUID de référence peut également être transmis dans le chemin : POST /api/chat/{chatId}/{referralGuid}/message (de même …/message/v1, …/message/v2).

4.4 Envoyer un fichier ou une vidéo (multipart, v2)

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

Les noms des champs du formulaire sont en PascalCase avec la notation par points

textMessage et media.file sont silencieusement ignorés. Utilisez les noms exacts ci-dessous.

Champ de formulaireTapezDescriptif
TextMessagestringTexte du message
Authorint0 opérateur, 1 client
IsInternalboolNote interne
ReplyToMessageIdintMessage auquel on répond
AppGuiduuidGUID de référence
Media.FilebinaryLe fichier lui-même
Media.NamestringNom du fichier
Media.FormatstringType MIME (video/mp4, image/png, application/pdf)
Media.TypeMediaTypeVoir §8.5
Media.DataBase64stringAlternative à Media.File
Media.ThumbnailstringImage d’aperçu vidéo Base64
Media.DurationdoubleDurée de la vidéo en secondes
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 Modifier le statut du chat

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

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

200 OK fait écho à l’objet mis à jour.

4.6 Mettre à jour les statuts des messages

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

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

4.7 Supprimer une discussion

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

5. Publications, bobines et histoires

Chemin de base : https://chatapi.smsbat.com/api/meta Authentification : X-Authorization-Key: <organization token>

5.1 Liste des publications, des bobines et des histoires

GET https://chatapi.smsbat.com/api/meta/posts?platform=instagram&mediaType=story&page=1&perPage=20
X-Authorization-Key: <token>
ParamètreTapezObligatoireDescriptif
pageintnonPage, par défaut 1
perPageintnonÉléments par page, par défaut 20
idintnonFiltrer par ID de publication interne
platformstringnoninstagram ou facebook
mediaTypestringnonpost, reel ou story. Tous les types lorsqu’ils sont omis
# 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"
      }
    }
  ]
}

Différence — nom du champ du compteur

Le schéma Swagger MetaCommentPostListItemDtoPaginationDTO définit total. Le documents de spécifications internes totalCount. Swagger est généré à partir du code, donc total est la vérité la plus probable. Analysez total ?? totalCount jusqu’à ce que cela soit réglé.

ChampDescriptif
idID de poste interne
metaIdPublication externe / Reel / Story ID dans Meta
textLégende du message
imageUrlURL du média proxy saisie par le MetaPost.Guid non séquentiel ou null
platformfacebook ou instagram
mediaTypepost, reel ou story
createdAtDate de création (date de la plateforme ou date de la base de données)
storyPrésent uniquement pour mediaType: "story"
story.idID d’histoire interne ; égal à post.id
story.metaIdID d’histoire externe dans Meta
story.urlURL proxy stable du média Story stocké ; null si le média n’a pas pu être enregistré

Les médias postaux sont desservis par deux routes : GET /api/meta/post/media/{id:int} pour le retour compatibilité et GET /api/meta/post/media/{guid:guid}. Nouvelles réponses et rappels d’API générez toujours le formulaire GUID.

5.2 Liste des commentaires

GET https://chatapi.smsbat.com/api/meta/comments?platform=instagram&postId=42&page=1&perPage=20
X-Authorization-Key: <token>
ParamètreTapezObligatoireDescriptif
pageintnonPage, par défaut 1
perPageintnonÉléments par page, par défaut 20
postIdintnonFiltrer par ID de publication
parentCommentIdintnonCommentaires des enfants (réponses) d’un commentaire donné
platformstringnonfacebook 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..."
      }
    }
  ]
}
ChampDescriptif
idID de commentaire interne
metaIdID externe dans Meta. null pour une de nos réponses en attente jusqu’à son envoi
textTexte du commentaire
createdAtDate de création
platformfacebook ou instagram
replyStatusnull pour un commentaire utilisateur entrant ; "pending" / "sent" / "failure" pour notre réponse
author.type"meta_user" utilisateur externe, "owner" propriétaire de la page
author.nameNom de l’auteur
author.metaUserIdID utilisateur étendu dans Meta ; null pour "owner"
postLa publication, la bobine ou l’histoire à laquelle appartient le commentaire
post.mediaTypepost, reel ou story
post.storyRéférence de l’histoire { id, metaId, url }, Histoires uniquement
mediaUrlMédia joint au commentaire, ou null
replyToCommentaire des parents { id, metaId, text } ; null au plus haut niveau

Écart — type de `author.type`

La spécification interne documente les chaînes "meta_user" / "owner". Types fanfarons MetaCommentAuthorType sous forme de entier avec l’énumération [0, 1]. Un JsonStringEnumConverter expliquerait l’écart, mais cela n’a pas été confirmé par une réponse réelle. Écrivez un analyseur qui accepte les deux.

5.3 Répondre à un commentaire

Met en file d’attente une réponse pour livraison.

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"

Corps de la requête : { "text": "Reply text" }

202 Accepted renvoie l’objet commentaire — même forme que GET /api/meta/comments — avec replyStatus: "pending" et metaId: null. Le résultat de la livraison arrive plus tard sous forme de Rappel source: 13 (§6.4).

 Écart – code de réponse 

Swagger déclare 200 sans corps ; la spécification interne déclare 202 Accepted avec le commentaire comme corps. Le contrôleur manque probablement d’un ProducesResponseType attribut, laissant Swagger sur sa valeur par défaut. Acceptez n’importe quel 2xx et ne dépendez pas d’un corps.


6. Webhooks

SMSBAT envoie POST requêtes avec application/json à votre URL et attend HTTP 200 en retour.

Les champs nuls sont entièrement omis

Un champ dont la valeur est null n’est pas du tout sérialisé dans le corps du rappel. Pour un message qui ne vient pas de Facebook ou d’Instagram, il n’y a tout simplement pas de touche MetaUserId. Traitez « absent » et null comme la même chose.

6.1 Enregistrez une URL de rappel

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
  }'
ChampTapezDescriptif
urlstringVotre point de terminaison
sourceSendingSourceCallbackType d’événement, voir §8.2
headerName / headerValuestringEn-tête d’authentification arbitraire que nous attachons à la demande (facultatif)
channelTypeChatSourceChaîne. 7 pour Instagram. Facultatif
channelEntityIdintUn compte professionnel spécifique. Nécessite channelType

Sans channelType, l’URL reçoit les événements de chaque canal.

Tip

La couverture complète des commentaires nécessite deux inscriptions : source: 12 pour les nouveaux commentaires et source: 13 pour les statuts de réponse. Pour les réponses Direct et Story, ajoutez source: 3 (et 11 si vous voulez chaque message de chat).

Opérations 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 renvoie :

[
  {
    "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 Nouveau message et réponse Instagram Story (source: 3, 11)

La réponse d’un utilisateur à une histoire Instagram arrive sous la forme d’un message ordinaire dans ces rappels, avec un bloc Story supplémentaire de niveau supérieur :

{
  "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"
  }
}
ChampDescriptif
ChatId / MessageIdIdentifiants de chat et de message
Author0 utilisateur, 1 opérateur
UsernameNom d’affichage ou identifiant Instagram / Facebook
UserIdID utilisateur numérique interne dans SMSBAT
MetaUserIdID étendu de l’interlocuteur dans Meta. Dans un message d’opérateur sortant, cela identifie toujours l’utilisateur méta du chat, pas l’opérateur
ShopIdID interne du compte professionnel Instagram / Facebook
ShopNameNom du compte professionnel tel que reçu de Meta au moment de la connexion
MessageTextTexte du message
MessageMediaURL du média lorsque le message est un média
type_messengerSource, 7 pour Instagram
operator_nameNom de l’opérateur lorsque Author = 1
StoryPrésenter uniquement sur une réponse Story entrante
Story.IdID d’histoire interne (MetaPost) — utilisable directement comme id / postId dans la Meta API
Story.MetaIdID d’histoire externe dans Meta
Story.UrlURL proxy stable du média Story stocké. Absent lorsque le média n’a pas pu être enregistré — le bloc Story et le message sont toujours délivrés

`Author` est inversé par rapport à l'API Chat

Dans ChatMessageDTO.author, 0 signifie opérateur et 1 signifie client. Dans ce rappel, c’est à l’inverse : 0 est l’utilisateur, 1 est l’opérateur. Ne partagez pas le mappage.

6.3 Nouveau commentaire (source: 12)

Se déclenche lorsqu’un utilisateur Meta commente une publication Facebook ou une publication / Reel Instagram.

Note

Instagram Les réponses aux histoires ne sont pas envoyées via source: 12. Elles arrivent comme d’habitude messages entrants sur source: 3 et/ou 11 avec un bloc Story — voir §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 État de la réponse aux commentaires (source: 13)

Se déclenche après que nous avons tenté de fournir une réponse, que celle-ci réussisse ou échoue.

{
  "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 Champs de rappel des commentaires partagés

Les deux rappels de commentaires partagent une forme de corps et ne diffèrent que par type.

ChampDescriptif
type"new_comment" ou "comment_status"
platform"facebook" ou "instagram"
comment.idID de commentaire interne
comment.metaIdID externe dans Meta ; null pour une réponse en attente avant son envoi
comment.parentCommentIdID du commentaire parent. Absent pour un commentaire de niveau supérieur
comment.parentMetaIdID de commentaire parent externe. Absent au plus haut niveau
comment.parentCommentTextTexte du commentaire des parents. Absent au plus haut niveau
comment.textTexte du commentaire
comment.createdAtDate de création
comment.updatedAtDernière mise à jour. Absent si le commentaire n’a jamais été édité
comment.replyStatus"pending" / "sent" / "failure". Absent pour un commentaire utilisateur entrant
comment.author.type"meta_user" ou "owner"
comment.author.nameNom de l’auteur
comment.author.metaUserIdID d’auteur étendu dans Meta. Absent pour le "owner"
comment.mediaUrlCommentez les médias. Absent quand il n’y en a pas
post.idID de poste interne
post.metaIdPublication externe / Reel / Story ID dans Meta
post.textTexte du message
post.imageUrlURL de la publication, ou null
post.createdAtDate de création du message
post.mediaTypeDans les rappels de commentaires, uniquement post ou reel

6.6 Nouveau chat (source: 7)

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

6.7 Modifications de l’état des messages et du chat (source: 6 / 5)

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

6.8 Message modifié ou supprimé (source: 9)

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

6.9 Indicateur de frappe (source: 8)

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

7. Sondage d’événements

Pour les environnements qui ne peuvent pas accepter le HTTP entrant.

7.1 Récupérer les événements

GET https://chatapi.smsbat.com/api/chat/callback-events?page=1&perPage=20
Authorization: Bearer <token>
ParamètreDescriptif
organizationIdFacultatif. Extrait du jeton en cas d’omission
page / perPagePagination, valeurs par défaut 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"
    }
  ]
}

Chaque événement porte event_guid, timestamp, organization_id et callback_type — un chaîne correspondant aux valeurs source du §8.2. Les champs restants correspondent aux champs correspondants webhook au §6.

7.2 Acquitter les événements traités

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 }

Les événements déjà supprimés ne comptent tout simplement pas dans le calcul du deleted. La commande et les tentatives sont à vous la responsabilité du côté.

7.3 Boucle recommandée

  1. Sondez GET /api/chat/callback-events selon un calendrier.
  2. Traitez les événements dans votre service.
  3. Envoyez la liste event_guid traitée au /callback-events/processed.
  4. Répétez.

8. Référence d’énumération

8.1 ChatSource — canal (0–9)

CodesChaîne
0Viber
1ViberBot
2TélégrammeBot
3WhatsApp
4Widget
5Rozetka
6Facebook
7Instagram
8Bal de promo
9Olx

8.2 SendingSourceCallback — type d’événement de rappel (0–13)

CodesÉvénement
3Chat — nouveau message de discussion, y compris les réponses de l’histoire
5Statut du chat modifié
6Statut du message modifié
7Nouveau chat créé
8Indicateur de frappe
9Message mis à jour ou supprimé
11AnyChatMessage — n’importe quel message de discussion
12MetaNewComment — nouveau commentaire Instagram / Facebook
13MetaCommentStatus — état de livraison de notre réponse au commentaire

L’énumération s’étend sur 0–13 ; les valeurs restantes ne sont pas nécessaires pour les intégrations Instagram.

8.3 ChatStatus (0–4)

0 Nouveau, 1 Ouvert, 2 En attente, 3 En Pause, 4 Fermé

8,4 MessageStatus (0-11)

CodesNom
0NOUVEAU
1SUCCÈS
2REJETÉ
3LIRE
4INCONNU
5TRAITEMENT
6LIVRÉ
7BLOCKED_BY_USER
8USER_NOT_FOUND

L’énumération s’étend sur 0–11. Les valeurs 9, 10 et 11 existent dans l’API mais ne sont pas encore documentées — traitez-les comme UNKNOWN.

8,5 MediaType (1–10)

1 Photo, 2 Fichier, 3 Audio, 4 Vidéo, 5 Autocollant, 6 AutocollantAnimé, 7 AutocollantVidéo, 8 Animation, 9 Voix, 10 VidéoNote

8.6 AuthorMessage — auteur dans l’API Chat (0–4)

0 Opérateur, 1 Client, 2 Bot, 3 ViberAccount

L’énumération s’étend sur 0–4 ; la valeur 4 n’est pas documentée. Les rappels “nouveau message” utilisent le mappage opposé — voir §6.2.

8,7 ChatMessageType (0–2)

0 Texte, 1 Photo, 2 Fichier

8.8 Commentaire replyStatus

null commentaire utilisateur entrant, "pending" notre réponse est en file d’attente, "sent" livrée, La livraison "failure" a échoué.


Questions ouvertes

Trois points sur lesquels la spécification interne et le Swagger généré par le code sont en désaccord. Un la demande avec un vrai jeton les règle tous ; en attendant, écrivez au client sur la défensive.

#QuestionSpécificationFanfaronnadeComment vérifier
1En-tête d’authentification pour /api/meta/*X-Authorization-Keyseulement Bearer déclaréscurl -i -H "X-Authorization-Key: <token>" ".../api/meta/posts?perPage=1" — attendez-vous à 200, pas à 401
2Champ de compteur dans les réponses métatotalCounttotalMême requête : lisez la clé racine JSON
3Type author.type et code d’état reply"meta_user" / "owner", 202 avec corpsint [0,1], 200 sans corpscurl -i .../api/meta/comments?perPage=1 plus une réponse test

Orientations provisoires :

  • compteur — lire total ?? totalCount ;
  • author.type — accepte à la fois une chaîne et un entier (0 ↔ meta_user, 1 ↔ owner, mappage à confirmer) ;
  • reply — traite tout 2xx comme un succès, ne nécessite aucun corps, prend le statut final du rappel source: 13.

Notes d’implémentation

  • L’authentification diffère selon le groupe de points de terminaison — /api/meta/* utilise X-Authorization-Key, les chats et les opérateurs utilisent Bearer, restapi accepte non plus.
  • La pagination s’écrit de deux manières — per_page sur /api/chat/chats, perPage sur /api/meta/* et /api/chat/callback-events.
  • Les champs multipart/form-data sont en PascalCase avec la notation par points (Media.File, Media.Type).
  • Les champs nuls sont omis des rappels — une clé absente signifie null.
  • phone est généralement null sur Instagram. Identifiez le client par instagramUser.id / metaUserId et la boutique par instaAccount.id (la valeur du filtre entityId).
  • Story.Id d’un rappel peut être transmis directement sous la forme id / postId à la Meta API.
  • Vérifiez le expiresAt de l’opérateur JWT avant de l’utiliser dans un lien profond ou le widget.