A conta do Instagram conectada à Synergy usa a mesma API, a mesma chave e o mesmo formato de erro do WhatsApp. O que muda é o id do caminho (o ig-user-id da conta, no lugar do phone_number_id), o corpo do envio (o do Instagram, não o da Cloud API) e os eventos de webhook (os nomes da Meta para o Instagram). Este guia cobre o envio de mensagens diretas, a resposta privada a um comentário, as regras da janela de 24 horas e os webhooks de saída.
Antes de começar, a organização precisa de uma conta do Instagram conectada (pela tela Conectar Instagram do app) e de um plano com os recursos api e instagram. A chave de API é a de sempre (Autenticação), com o escopo messages.
O id do caminho#
Em POST /{version}/{id}/messages, {id} é o ig-user-id da conta (só dígitos, de 1 a 32). A {version} segue o formato de sempre (v25.0) e não muda o comportamento.
A chave syn_… carrega só a organização, então a Synergy descobre o canal pelo id:
- Um número de WhatsApp da organização que ela já resolveu vai pelo caminho do WhatsApp, como sempre.
- Uma conta do Instagram que já respondeu antes vai direto para a conta.
- Um id novo é tentado como conta do Instagram uma vez. Se a conta não existe, ou é de outra organização, a resposta é igual à de um id que não existe (404, código 100): ninguém descobre de quem é uma conta.
O terceiro passo tem um limite por chave: 30 ids novos por minuto, por servidor. Passando disso, a Synergy pula a tentativa e segue o caminho do WhatsApp. Se o id for um número seu, o envio acontece normalmente. Se não for, a resposta é 429 com Retry-After: 1, nunca um 404: sem a tentativa, a Synergy não sabe dizer que o id não existe. Repita depois de 1 segundo.
Uma chave restrita a alguns números e contas (instanceIds) só alcança esses: numa conta fora da restrição ela responde 401 (código 190), como num número de WhatsApp fora dela. Uma conta de outra organização responde 404.
Enviar uma mensagem direta#
O corpo é estrito: um campo desconhecido é recusado com 400 (código 100). Escolha um destinatário e uma mensagem.
| Campo | O que é |
|---|---|
recipient.id | O IGSID da pessoa (só dígitos). A pessoa precisa já ter uma conversa com a conta |
recipient.comment_id | O id de um comentário, para uma resposta privada |
message.text | O texto, de até 1.000 bytes |
message.quick_replies | De 1 a 13 respostas rápidas (content_type: "text", title de até 20 caracteres, payload de até 100), junto com text |
message.attachment | Uma mídia (image, video, audio ou file) com payload.url, ou um template de botões (template_type: "button", text e de 1 a 3 botões web_url ou postback) |
sender_action | typing_on, typing_off ou mark_seen, no lugar de message |
Toda URL (attachment.payload.url, web_url dos botões) precisa ser https:, sem usuário e senha. O corpo inteiro tem até 64 KB.
A resposta, quando a Meta aceita, tem o formato dela:
Mais exemplos de corpo:
Idempotência#
Idempotency-Key funciona como no WhatsApp (Enviar mensagens): repetir a requisição com a mesma chave responde o mesmo message_id e a mensagem sai uma vez só. Enquanto o primeiro envio está em andamento, a repetição recebe 409 (código 1390002); reusar a chave para outra pessoa recebe 422 (código 1390003).
De quem é a conversa depois do envio#
Como no WhatsApp, a conversa passa para a automação (status automated, dona: a chave). Com uma chave notify, a resposta da pessoa vai para a fila dos atendentes; com bot, continua com a integração. Uma chave bot não envia para uma conversa que está com um atendente (409, código 1390001).
curl
curl -X POST 'https://api.synergyconnect.com.br/v25.0/17841400000000001/messages' \
-H "Authorization: Bearer $SYNERGY_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: pedido-42-saiu' \
-d '{"recipient":{"id":"17841400000000099"},"message":{"text":"Seu pedido saiu para entrega!"}}'JavaScript
const res = await fetch('https://api.synergyconnect.com.br/v25.0/17841400000000001/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SYNERGY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'pedido-42-saiu',
},
body: JSON.stringify({
recipient: { id: '17841400000000099' },
message: { text: 'Seu pedido saiu para entrega!' },
}),
});
const { recipient_id, message_id } = await res.json();Python
import os
import requests
res = requests.post(
"https://api.synergyconnect.com.br/v25.0/17841400000000001/messages",
headers={
"Authorization": f"Bearer {os.environ['SYNERGY_API_KEY']}",
"Idempotency-Key": "pedido-42-saiu",
},
json={
"recipient": {"id": "17841400000000099"},
"message": {"text": "Seu pedido saiu para entrega!"},
},
)
data = res.json() # {"recipient_id": "...", "message_id": "..."}{
"recipient_id": "17841400000000099",
"message_id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAw"
}{
"recipient": { "id": "17841400000000099" },
"message": {
"text": "Quer ver o catálogo?",
"quick_replies": [
{ "content_type": "text", "title": "Sim", "payload": "catalogo.sim" },
{ "content_type": "text", "title": "Agora não", "payload": "catalogo.nao" }
]
}
}{
"recipient": { "id": "17841400000000099" },
"message": {
"attachment": {
"type": "image",
"payload": { "url": "https://cdn.exemplo.com.br/promocao.jpg" }
}
}
}{
"recipient": { "id": "17841400000000099" },
"message": {
"attachment": {
"type": "template",
"payload": {
"template_type": "button",
"text": "Acompanhe o seu pedido:",
"buttons": [{ "type": "web_url", "title": "Rastrear", "url": "https://loja.exemplo.com.br/pedidos/42" }]
}
}
}
}{ "recipient": { "id": "17841400000000099" }, "sender_action": "typing_on" }Resposta privada a um comentário#
Com recipient.comment_id, a mensagem é a resposta privada da conta a um comentário (a pessoa recebe uma DM, mesmo sem ter escrito antes). A Meta permite uma resposta privada por comentário, em até 7 dias.
O envio não acontece na hora: o pedido entra na mesma fila das Jornadas, que respeita o ritmo que a Meta permite, e a resposta é 202:
O resultado final (enviada, recusada, vencida na fila) é o evento synergy_comment_actions do webhook (abaixo). Regras da fila:
- O
comment_idé só numérico. - A API usa no máximo 10 % da fila e da vazão: uma Jornada com muitos comentários não é atrasada por ela, e ela não é bloqueada por uma Jornada.
- Uma segunda tentativa no mesmo comentário recebe 400 (código 100,
This comment already has a private reply.). - Depois de 20 respostas seguidas a comentários que a Meta não aceita (
comment_ineligible: o comentário é antigo, foi apagado, já tem resposta), a chave fica 1 hora sem resposta privada: 429 comRetry-Afterem segundos. - Fila cheia: 429,
Retry-After: 60.
curl -X POST 'https://api.synergyconnect.com.br/v25.0/17841400000000001/messages' \
-H "Authorization: Bearer $SYNERGY_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"recipient":{"comment_id":"17900000000000001"},"message":{"text":"Oi! Te mandei os detalhes por aqui."}}'{ "queued": true, "comment_id": "17900000000000001" }A janela de 24 horas#
A conta só envia mensagem livre dentro de 24 horas da última mensagem da pessoa. Diferente do WhatsApp, a Synergy confere a janela antes de chamar a Meta: fora dela a resposta é imediata e nenhuma mensagem é enviada. A API nunca usa a etiqueta Human Agent (a janela estendida de 7 dias da Meta), que fica reservada aos atendentes na plataforma. Veja Janela de atendimento de 24 horas.
Erros#
Todos no formato da Graph API (Erros).
| Status | Código | Quando |
|---|---|---|
| 400 | 100 | Corpo inválido, campo desconhecido, URL que não é https, texto acima de 1.000 bytes, recipient com id e comment_id juntos ou nenhum dos dois |
| 400 | 100, subcódigo 2534014 | A pessoa não tem conversa com a conta (a API não inicia conversa) |
| 400 | 100 | Segunda resposta privada ao mesmo comentário |
| 400 | 10, subcódigo 2534022 | Fora da janela de 24 horas |
| 401 | 190 | Chave inválida ou revogada, ou que não alcança esta conta (instanceIds) |
| 403 | 200 | A chave não tem o escopo messages, ou é uma chave de assistente: conexões de assistente só enviam pelo WhatsApp |
| 403 | 1390004 | O plano não tem api ou instagram |
| 403 | 1390005 | Conta em modo leitura ou suspensa |
| 403 | 1390014 | A conta foi congelada pela plataforma |
| 404 | 100 | O id não é uma conta nem um número desta organização |
| 409 | 1390001, 1390002 | A conversa está com um atendente (chave bot), ou a Idempotency-Key ainda está em andamento |
| 422 | 1390003 | A Idempotency-Key já foi usada para outra pessoa |
| 429 | 130429 | Vazão da conta, borda da chave, fila de respostas privadas, ou o id novo sem tentativa disponível (veja acima). Sempre com Retry-After |
| 503 | 2 | Falha temporária: repita com espera |
{
"error": {
"message": "(#10) This message is sent outside of allowed window.",
"type": "OAuthException",
"code": 10,
"error_subcode": 2534022,
"fbtrace_id": "syn-3f9a1c0b"
}
}Webhooks do Instagram#
Os eventos da conta chegam nos mesmos webhooks do WhatsApp (Webhooks): o mesmo cadastro (POST /v1/webhooks), a mesma assinatura (Assinatura dos webhooks), o mesmo X-Synergy-Delivery-Id. O envelope imita o da Meta: object é "instagram" e entry[].id é o ig-user-id da conta.
fields | Quando dispara |
|---|---|
messages | Mensagem direta recebida. Vale também para o WhatsApp |
messaging_postbacks | A pessoa tocou num botão postback |
message_reactions | Reação a uma mensagem |
messaging_seen | A pessoa leu uma mensagem |
messaging_referral | A conversa veio de um link ig.me, anúncio ou código QR |
message_edit | A pessoa editou uma mensagem |
messaging_optins | A pessoa aceitou receber mensagens |
comments | Comentário em uma publicação da conta |
live_comments | Comentário durante uma transmissão ao vivo |
mentions | A conta foi mencionada |
synergy_comment_actions | O resultado de uma ação sobre um comentário (resposta privada, pública ou a uma menção) |
synergy_journeys | Eventos de uma Jornada (Jornadas) |
Exceto os dois synergy_*, o value é o da Meta, repassado como chegou. Um comentário:
Uma mensagem direta:
Regras da entrega:
- O plano na hora do evento. O evento só é encaminhado se o plano da organização tem o recurso
instagramquando ele chega. Sem o recurso, a Synergy continua guardando as mensagens e não envia nada ao seu endpoint (e não guarda para enviar depois). - Um envelope por chamada. Todos os comentários de uma mesma entrega da Meta saem juntos, em um envelope por endpoint, em vez de um POST por comentário.
- Teto por endpoint. Uma conta entrega no máximo 60 envelopes por minuto a cada endpoint. O que passa disso, enquanto o endpoint está saudável, é descartado e contado (o total aparece como "eventos descartados" na saúde do webhook). Se o endpoint está fora do ar, os eventos esperam na fila de retentativa e saem no ritmo do teto.
- URL revalidada, nada de segredo. A URL é conferida de novo em cada envio, sem seguir redirecionamentos. Nenhum envelope leva token da Meta, link de mídia nem o segredo do webhook.
- Assinatura. Toda tentativa leva
X-Hub-Signature-256eX-Synergy-Signature. - Filtro por conta.
instanceIdslimita o webhook a contas e números específicos, como no WhatsApp.
{
"object": "instagram",
"entry": [{
"id": "17841400000000001",
"time": 1767225600,
"changes": [{
"field": "comments",
"value": {
"id": "17900000000000001",
"text": "eu quero",
"from": { "id": "17841400000000099", "username": "maria.souza" },
"media": { "id": "17950000000000001", "media_product_type": "FEED" }
}
}]
}]
}{
"object": "instagram",
"entry": [{
"id": "17841400000000001",
"time": 1767225600,
"changes": [{
"field": "messages",
"value": {
"sender": { "id": "17841400000000099" },
"recipient": { "id": "17841400000000001" },
"timestamp": 1767225600000,
"message": { "mid": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAw", "text": "oi, quero comprar" }
}
}]
}]
}Limites#
Os limites do Instagram estão em Limites de taxa: a borda por chave e conta, a vazão da conta, a fila de respostas privadas e o teto de envelopes por endpoint.
Ficou com dúvida? Escreva para suporte@synergyconnect.com.br.