Integrazione API Meta e Instagram
Riferimento per la creazione di un’app Instagram sulla piattaforma SMSBAT ChatHub: autenticazione, Conversazioni di Instagram Direct, commenti su post e reel, risposte alle storie, webhook e sondaggi.
Fonti
Questa pagina unisce le specifiche interne dell’API Meta Comments con l’OpenAPI live
definizioni a https://chatapi.smsbat.com/swagger/v1/swagger.json e
https://restapi.smsbat.com/swagger/v1/swagger.json. Dove i due non sono d’accordo, il
la differenza viene evidenziata in linea ed elencata in Domande aperte.
1. URL di base
| Scopo | URL |
|---|---|
| API di chat + Meta API | https://chatapi.smsbat.com |
| Interfaccia utente spavalda/OpenAPI | https://chatapi.smsbat.com/index.html · …/swagger/v1/swagger.json |
| API REST (organizzazioni, URL di richiamata) | https://restapi.smsbat.com |
| Spavalderia dell’API REST | https://restapi.smsbat.com/swagger/v1/swagger.json |
| Pannello web operatore | https://chat.smsbat.com |
2. Autenticazione
Lo schema di autenticazione dipende dal gruppo di endpoint. Mescolarli è la causa più comune di 401.
| Gruppo | Intestazione |
|---|---|
chatapi.smsbat.com/api/meta/* (post, commenti) | 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 · Autenticazione di base |
Il token dell’organizzazione per X-Authorization-Key viene rilasciato nel pannello sotto Profilo.
I JWT dell’azienda e dell’operatore provengono da /api/company/get-token e /api/operator/get-token.
Discrepanza
Il documento chatapi OpenAPI dichiara un unico schema di sicurezza — Bearer — e lo applica
a livello globale. X-Authorization-Key non è affatto dichiarato lì, sebbene il Meta interno
La specifica API dei commenti lo nomina per /api/meta/*. Molto probabilmente è gestito da
middleware che non si riflette in Swagger. Conferma empiricamente prima di spedire.
2.1 Gettone aziendale
POST https://chatapi.smsbat.com/api/company/get-token
Content-Type: application/json
{ "login": "company_login", "password": "company_password" }
200 OK restituisce una stringa token semplice.
2.2 Organizzazioni
GET https://chatapi.smsbat.com/api/company/organization
Authorization: Bearer <company_token>
[ { "id": 24, "name": "My Instagram Store" } ]
2.3 Gli operatori di un’organizzazione
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" }
}
]
Stati dell’operatore: 0 Attivo, 1 Inattivo, 2 Eliminato.
2.4 Aggiungi/sincronizza operatori
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 Operatore 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 restituisce JWT come stringa.
2.6 Convalidare un token operatore
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
}
Se non valido: { "isValid": false, "error": "Invalid token" }.
2.7 Incorpora il pannello chat dell’operatore
<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. Collegamenti diretti al pannello della chat
Un sistema esterno (CRM, ERP, sito web) può aprire una conversazione specifica in
https://chat.smsbat.com/. L’operatore è autorizzato da un JWT passato come parametro di query.
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>
| Parametro | Descrizione |
|---|---|
chat_raw_id | ID chat |
phone | Numero di telefono in formato internazionale |
from | Identificatore del marchio/account aziendale (bm_id) |
source | Sorgente chat — 7 per Instagram, vedere §8.1 |
token | Operatore JWT valido e non scaduto con accesso alle chat |
Un JWT non valido indirizza il visitatore alla schermata di accesso del pannello operatore.
4. Conversazioni dirette di Instagram
4.1 Elenca le chat
GET https://chatapi.smsbat.com/api/chat/chats?source=7&page=1&per_page=20
Authorization: Bearer <token>
Note
La paginazione qui è per_page (snake_case). Sotto /api/meta/* e il sondaggio
l’endpoint è perPage (camelCase). Non si tratta di un errore di battitura: l’API utilizza entrambi.
Parametri di query, tutti facoltativi:
| Parametro | Digitare | Descrizione |
|---|---|---|
source | ChatSource | 7 limita i risultati a Instagram |
entityId | int | ID del conto aziendale. Applicato solo insieme a source |
instagram_user_id | int | ID utente Instagram in ChatHub |
facebook_user_id | int | ID utente Facebook in ChatHub |
page / per_page | int | Impaginazione, impostazioni predefinite 1 / 20 |
status | ChatStatus[] | Stato della chat, ripetibile |
search | string | Ricerca a testo libero (nome, telefono, …) |
organizationId | int | ID organizzazione |
operatorId | int[] | Filtra per operatori assegnati |
date | string[] | Due limiti: ?date=…&date=… |
isChain | bool | Restituisce le chat come catene, trasportando messaggi dalle chat precedenti |
isUnread, starMark, isOperator, isAIAgent | bool | Filtri aggiuntivi |
phone, email, contactId, clientId, tagIds, rate, sortedBy | — | Altri filtri |
200 OK restituisce 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": []
}
]
}
I campi che contano per un’app Instagram:
| Campo | Significato |
|---|---|
instaAccount | L’Account aziendale Instagram (il negozio). id è il valore del filtro entityId; name è il nome dell’account di Meta |
instagramUser | Il cliente. name è l’handle di Instagram, id è il valore del filtro instagram_user_id |
metaUserId | L’ID con ambito del cliente sul lato Meta (stringa) |
messSource | 7 per Instagram |
phone | Di solito null per Instagram: non usarlo come chiave |
ChatDTO trasporta anche 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 Messaggi di chat
GET https://chatapi.smsbat.com/api/chat/chats/1867/messages?isChain=false
Authorization: Bearer <token>
200 OK restituisce un array di 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 viene compilato quando il messaggio si riferisce a un post o a una storia di Instagram: passalo
direttamente come id / postId alla Meta API. media è un ChatMediaDTO:
{ name, format, type, uri, raw, length, isUploaded }.
4.3 Invia un messaggio (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 | Digitare | Descrizione |
|---|---|---|
textMessage | string? | Testo del messaggio. Può essere vuoto quando è presente media |
author | AuthorMessage? | 0 operatore, 1 cliente |
isInternal | bool? | true segnala una nota interna che non viene consegnata al cliente |
replyToMessageId | int? | ID del messaggio a cui si risponde |
appGuid | uuid? | GUID di riferimento |
media | MediaDTO? | { name, format, dataBase64, thumbnail, duration, type } |
200 OK → { "id": 9930, "messageStatus": 0 }
È inoltre possibile passare un GUID di riferimento nel percorso:
POST /api/chat/{chatId}/{referralGuid}/message (allo stesso modo …/message/v1, …/message/v2).
4.4 Invia un file o un video (multiparte, v2)
POST https://chatapi.smsbat.com/api/chat/1867/message/v2
Authorization: Bearer <token>
Content-Type: multipart/form-data
I nomi dei campi del modulo sono PascalCase con notazione punto
textMessage e media.file vengono silenziosamente ignorati. Utilizza i nomi esatti riportati di seguito.
| Campo modulo | Digitare | Descrizione |
|---|---|---|
TextMessage | string | Testo del messaggio |
Author | int | 0 operatore, 1 cliente |
IsInternal | bool | Nota interna |
ReplyToMessageId | int | Messaggio a cui è stata data risposta |
AppGuid | uuid | GUID di riferimento |
Media.File | binary | Il file stesso |
Media.Name | string | Nome del file |
Media.Format | string | Tipo MIME (video/mp4, image/png, application/pdf) |
Media.Type | MediaType | Vedi §8.5 |
Media.DataBase64 | string | Alternativa a Media.File |
Media.Thumbnail | string | Cornice di anteprima video Base64 |
Media.Duration | double | Durata del video in secondi |
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 Modificare lo stato della chat
PUT https://chatapi.smsbat.com/api/chat/status
Authorization: Bearer <token>
Content-Type: application/json
{ "id": 1867, "status": 4 }
200 OK fa eco all’oggetto aggiornato.
4.6 Aggiorna gli stati dei messaggi
PUT https://chatapi.smsbat.com/api/chat/messages/status
Authorization: Bearer <token>
Content-Type: application/json
{ "status": 3, "messageIds": [9928, 9929] }
4.7 Eliminare una chat
DELETE https://chatapi.smsbat.com/api/chat/chats/1867
Authorization: Bearer <token>
5. Post, reel e storie
Sentiero base: https://chatapi.smsbat.com/api/meta
Autentica: X-Authorization-Key: <organization token>
5.1 Elenca post, reel e storie
GET https://chatapi.smsbat.com/api/meta/posts?platform=instagram&mediaType=story&page=1&perPage=20
X-Authorization-Key: <token>
| Parametro | Digitare | Obbligatorio | Descrizione |
|---|---|---|---|
page | int | no | Pagina, predefinita 1 |
perPage | int | no | Elementi per pagina, predefinito 20 |
id | int | no | Filtra per ID articolo interno |
platform | string | no | instagram o facebook |
mediaType | string | no | post, reel o story. Tutti i tipi se omessi |
# 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"
}
}
]
}
Discrepanza - nome campo contatore
Lo schema Swagger MetaCommentPostListItemDtoPaginationDTO definisce total. Il
documenti di specifica interna totalCount. Swagger viene generato dal codice, quindi
total è la verità più probabile. Analizza total ?? totalCount finché non viene risolto.
| Campo | Descrizione |
|---|---|
id | ID post interno |
metaId | ID post/reel/storia esterno in Meta |
text | Didascalia del messaggio |
imageUrl | URL multimediale proxy digitato dal non sequenziale MetaPost.Guid o null |
platform | facebook o instagram |
mediaType | post, reel o story |
createdAt | Data di creazione (data della piattaforma o data del database) |
story | Presente solo per mediaType: "story" |
story.id | ID della storia interna; uguale a post.id |
story.metaId | ID storia esterna in Meta |
story.url | URL proxy stabile del supporto Story archiviato; null se non è stato possibile salvare il file multimediale |
I post media sono serviti da due percorsi: GET /api/meta/post/media/{id:int} per indietro
compatibilità e GET /api/meta/post/media/{guid:guid}. Nuove risposte API e callback
generare sempre il modulo GUID.
5.2 Elenca i commenti
GET https://chatapi.smsbat.com/api/meta/comments?platform=instagram&postId=42&page=1&perPage=20
X-Authorization-Key: <token>
| Parametro | Digitare | Obbligatorio | Descrizione |
|---|---|---|---|
page | int | no | Pagina, predefinita 1 |
perPage | int | no | Elementi per pagina, predefinito 20 |
postId | int | no | Filtra per ID articolo |
parentCommentId | int | no | Commenti secondari (risposte) di un dato commento |
platform | string | no | facebook 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..."
}
}
]
}
| Campo | Descrizione |
|---|---|
id | ID commento interno |
metaId | ID esterno in Meta. null per una nostra risposta in attesa dell’invio |
text | Testo del commento |
createdAt | Data di creazione |
platform | facebook o instagram |
replyStatus | null per il commento di un utente in entrata; "pending" / "sent" / "failure" per la nostra risposta |
author.type | "meta_user" utente esterno, "owner" proprietario della pagina |
author.name | Nome dell’autore |
author.metaUserId | ID utente con ambito in Meta; null per "owner" |
post | Il post, la Reel o la Storia a cui appartiene il commento |
post.mediaType | post, reel o story |
post.story | Riferimento alla storia { id, metaId, url }, Solo storie |
mediaUrl | File multimediali allegati al commento o null |
replyTo | Commento dei genitori { id, metaId, text }; null al livello più alto |
Discrepanza - tipo `author.type`
La specifica interna documenta le stringhe "meta_user" / "owner". Tipi spavaldi
MetaCommentAuthorType come intero con enum [0, 1]. A JsonStringEnumConverter
spiegherebbe il divario, ma ciò non è stato confermato da una risposta reale. Scrivi un
parser che accetta entrambi.
5.3 Rispondere a un commento
Accoda una risposta per la consegna.
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"
Richiedi corpo: { "text": "Reply text" }
202 Accepted restituisce l’oggetto commento - stessa forma di GET /api/meta/comments - con
replyStatus: "pending" e metaId: null. L’esito della consegna arriva più tardi come a
source: 13 richiamata (§6.4).
Discrepanza - codice di risposta
Swagger dichiara 200 senza corpo; la specifica interna dichiara 202 Accepted
con il commento come corpo. Molto probabilmente al controller manca un ProducesResponseType
attributo, lasciando Swagger sul valore predefinito. Accetta qualsiasi 2xx e non dipendere da un corpo.
6. Webhook
SMSBAT invia POST richieste con application/json al tuo URL e si aspetta HTTP 200 in risposta.
I campi nulli vengono completamente omessi
Un campo il cui valore è null non è affatto serializzato nel corpo del callback. Per un
messaggio che non proviene da Facebook o Instagram semplicemente non esiste il tasto MetaUserId.
Tratta “assente” e null come la stessa cosa.
6.1 Registrare un URL di richiamata
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 | Digitare | Descrizione |
|---|---|---|
url | string | Il tuo punto finale |
source | SendingSourceCallback | Tipo evento, vedere §8.2 |
headerName / headerValue | string | Intestazione di autenticazione arbitraria che alleghiamo alla richiesta (facoltativa) |
channelType | ChatSource | Canale. 7 per Instagram. Facoltativo |
channelEntityId | int | Un conto aziendale specifico. Richiede channelType |
Senza channelType l’URL riceve eventi da ogni canale.
Tip
La copertura completa dei commenti richiede due registrazioni: source: 12 per nuovi commenti e
source: 13 per gli stati delle risposte. Per le risposte dirette e alle storie aggiungi source: 3
(e 11 se vuoi tutti i messaggi di chat).
Operazioni rimanenti:
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 restituisce:
[
{
"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 Nuovo messaggio e risposta alla storia di Instagram (source: 3, 11)
La risposta di un utente a una Storia di Instagram arriva come un normale messaggio in queste richiamate,
con un blocco Story di primo livello aggiuntivo:
{
"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 | Descrizione |
|---|---|
ChatId / MessageId | Identificatori di chat e messaggi |
Author | 0 utente, 1 operatore |
Username | Nome visualizzato o handle di Instagram/Facebook |
UserId | ID utente numerico interno in SMSBAT |
MetaUserId | ID con ambito dell’interlocutore in Meta. Su un messaggio operatore in uscita questo identifica ancora l’utente Meta della chat, non l’operatore |
ShopId | ID interno dell’account aziendale Instagram/Facebook |
ShopName | Nome dell’account aziendale ricevuto da Meta al momento della connessione |
MessageText | Testo del messaggio |
MessageMedia | URL multimediale quando il messaggio è multimediale |
type_messenger | Fonte, 7 per Instagram |
operator_name | Nome dell’operatore quando Author = 1 |
Story | Presente solo nella risposta ad una Storia in entrata |
Story.Id | ID storia interna (MetaPost) — utilizzabile direttamente come id / postId nella Meta API |
Story.MetaId | ID storia esterna in Meta |
Story.Url | URL proxy stabile del supporto Story archiviato. Assente quando non è stato possibile salvare il supporto — il blocco Story e il messaggio vengono comunque recapitati |
`Author` è invertito rispetto all'API Chat
In ChatMessageDTO.author, 0 significa operatore e 1 significa cliente. In questo richiamo lo è
viceversa: 0 è l’utente, 1 è l’operatore. Non condividere la mappatura.
6.3 Nuovo commento (source: 12)
Si attiva quando un utente Meta commenta un post di Facebook o un post/reel di Instagram.
Note
Instagram Le risposte alle storie non vengono inviate tramite source: 12. Arrivano normalmente
messaggi in entrata su source: 3 e/o 11 con un blocco Story — vedere §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 Stato della risposta al commento (source: 13)
Si attiva dopo il tentativo di fornire una risposta, indipendentemente dal fatto che abbia esito positivo o negativo.
{
"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 Campi di richiamata dei commenti condivisi
Entrambi i richiami ai commenti condividono una forma del corpo e differiscono solo per type.
| Campo | Descrizione |
|---|---|
type | "new_comment" o "comment_status" |
platform | "facebook" o "instagram" |
comment.id | ID commento interno |
comment.metaId | ID esterno in Meta; null per una risposta in sospeso prima che venga inviata |
comment.parentCommentId | ID commento principale. Assente per un commento di primo livello |
comment.parentMetaId | ID commento principale esterno. Assente ai massimi livelli |
comment.parentCommentText | Testo del commento del genitore. Assente ai massimi livelli |
comment.text | Testo del commento |
comment.createdAt | Data di creazione |
comment.updatedAt | Ultimo aggiornamento. Assente se il commento non è mai stato modificato |
comment.replyStatus | "pending" / "sent" / "failure". Assente per il commento di un utente in entrata |
comment.author.type | "meta_user" o "owner" |
comment.author.name | Nome dell’autore |
comment.author.metaUserId | ID autore con ambito in Meta. Assente per "owner" |
comment.mediaUrl | Commento multimediale. Assente quando non ce n’è |
post.id | ID post interno |
post.metaId | ID post/reel/storia esterno in Meta |
post.text | Pubblica testo |
post.imageUrl | Pubblica l’URL dell’immagine o null |
post.createdAt | Data di creazione post |
post.mediaType | Nei callback dei commenti, solo post o reel |
6.6 Nuova chat (source: 7)
{ "ChatId": 12345, "Phone": "+380501234567", "chat.Source": 7 }
6.7 Modifiche allo stato dei messaggi e della chat (source: 6 / 5)
{ "name": "changed_message_status", "id": 9928, "status": 6 }
{ "name": "changed_chat_status", "id": 1867, "status": 4 }
6.8 Messaggio modificato o eliminato (source: 9)
{ "messageId": 9930, "text": "Updated message text" }
{ "messageId": 9931, "delete": true }
6.9 Indicatore di digitazione (source: 8)
{ "chat_id": 1867, "event": "start_typing", "operator_name": "Iryna" }
{ "chat_id": 1867, "event": "end_typing" }
7. Sondaggio sugli eventi
Per ambienti che non possono accettare HTTP in entrata.
7.1 Recupera eventi
GET https://chatapi.smsbat.com/api/chat/callback-events?page=1&perPage=20
Authorization: Bearer <token>
| Parametro | Descrizione |
|---|---|
organizationId | Opzionale. Preso dal token quando omesso |
page / perPage | Impaginazione, impostazioni predefinite 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"
}
]
}
Ogni evento porta event_guid, timestamp, organization_id e callback_type — un
stringa che corrisponde ai valori source in §8.2. I restanti campi corrispondono ai corrispondenti
webhook nel §6.
7.2 Riconoscere gli eventi elaborati
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 }
Gli eventi già rimossi semplicemente non contano per deleted. L’ordine e i tentativi sono tuoi
responsabilità della parte.
7.3 Ciclo consigliato
- Sondaggio
GET /api/chat/callback-eventssu un programma. - Elabora gli eventi nel tuo servizio.
- Invia l’elenco
event_guidelaborato a/callback-events/processed. - Ripeti.
8. Riferimento all’enumerazione
8.1 ChatSource — canale (0–9)
| Codice | Canale |
|---|---|
| 0 | Viber |
| 1 | ViberBot |
| 2 | TelegramBot |
| 3 | |
| 4 | Dispositivo |
| 5 | Rozetka |
| 6 | |
| 7 | |
| 8 | Ballo di fine anno |
| 9 | Olx |
8.2 SendingSourceCallback — tipo di evento di richiamata (0–13)
| Codice | Evento |
|---|---|
| 3 | Chat — nuovo messaggio di chat, incluse le risposte alle storie |
| 5 | Lo stato della chat è cambiato |
| 6 | Lo stato del messaggio è cambiato |
| 7 | Nuova chat creata |
| 8 | Indicatore di digitazione |
| 9 | Messaggio aggiornato o cancellato |
| 11 | AnyChatMessage — qualsiasi messaggio di chat |
| 12 | MetaNewComment — nuovo commento su Instagram/Facebook |
| 13 | MetaCommentStatus — stato di consegna della nostra risposta al commento |
L’enumerazione si estende su 0–13; i restanti valori non sono necessari per le integrazioni di Instagram.
8.3 ChatStatus (0–4)
0 Nuovo, 1 Aperto, 2 In attesa, 3 In pausa, 4 Chiuso
8.4 MessageStatus (0–11)
| Codice | Nome |
|---|---|
| 0 | NUOVO |
| 1 | SUCCESSO |
| 2 | RIFIUTATO |
| 3 | LEGGI |
| 4 | SCONOSCIUTO |
| 5 | LAVORAZIONE |
| 6 | CONSEGNATO |
| 7 | BLOCCATO_DA_UTENTE |
| 8 | UTENTE_NOT_TROVATO |
L’enumerazione si estende su 0–11. I valori 9, 10 e 11 esistono nell’API ma non sono ancora documentati —
trattateli come UNKNOWN.
8.5 MediaType (1–10)
1 Foto, 2 File, 3 Audio, 4 Video, 5 Adesivo, 6 AdesivoAnimato,
7 StickerVideo, 8 Animazione, 9 Voce, 10 VideoNote
8.6 AuthorMessage — autore nell’API Chat (0–4)
0 Operatore, 1 Cliente, 2 Bot, 3 ViberAccount
L’enumerazione si estende su 0–4; il valore 4 non è documentato. Le richiamate del “nuovo messaggio” utilizzano l’estensione
mappatura opposta — vedere §6.2.
8.7 ChatMessageType (0–2)
0 Testo, 1 Foto, 2 File
8.8 Commento replyStatus
null commento utente in entrata, "pending" la nostra risposta è in coda, "sent" consegnata,
"failure" consegna non riuscita.
Domande aperte
Tre punti in cui le specifiche interne e lo Swagger generato dal codice non sono d’accordo. Uno la richiesta con gettone reale li salda tutti; fino ad allora, scrivi al cliente sulla difensiva.
| # | Domanda | Specificazione | Spavalderia | Come controllare |
|---|---|---|---|---|
| 1 | Intestazione di autenticazione per /api/meta/* | X-Authorization-Key | solo Bearer dichiarati | curl -i -H "X-Authorization-Key: <token>" ".../api/meta/posts?perPage=1" — aspettati 200, non 401 |
| 2 | Campo contatore nelle risposte Meta | totalCount | total | Stessa richiesta: leggi la chiave JSON root |
| 3 | tipo author.type e codice di stato reply | "meta_user" / "owner", 202 con corpo | int [0,1], 200 senza corpo | curl -i .../api/meta/comments?perPage=1 più una risposta di prova |
Guida provvisoria:
- contatore: leggi
total ?? totalCount; author.type— accetta sia una stringa che un numero intero (0↔meta_user,1↔owner, mappatura da confermare);reply— considera qualsiasi2xxcome successo, non richiede alcun corpo, prende lo stato finale dal callbacksource: 13.
Note di implementazione
- L’autenticazione varia in base al gruppo di endpoint —
/api/meta/*utilizzaX-Authorization-Key, chat e gli operatori usanoBearer,restapiaccetta entrambi. - L’impaginazione è scritta in due modi —
per_pagesu/api/chat/chats,perPagesu/api/meta/*e/api/chat/callback-events. - I campi
multipart/form-datasono PascalCase con notazione punto (Media.File,Media.Type). - I campi nulli vengono omessi dalle richiamate — una chiave assente significa
null. phonedi solito ènullsu Instagram. Identifica il cliente tramiteinstagramUser.id/metaUserIde il negozio perinstaAccount.id(il valore del filtroentityId).Story.Idda una richiamata può essere passato direttamente comeid/postIdalla Meta API.- Controlla il JWT
expiresAtdell’operatore prima di utilizzarlo in un deeplink o nel widget.