TL;DR
A API de Gráficos do Instagram permite que desenvolvedores gerenciem contas de Negócios e Criadores do Instagram programaticamente. Ela utiliza OAuth 2.0 via Facebook Login, endpoints GraphQL para publicação de conteúdo, insights, comentários e mensagens, com limite de taxa de 200 chamadas/hora por aplicativo. Este guia mostra desde a configuração de autenticação, publicação, insights, comentários e estratégias de integração em produção.
Experimente o Apidog hoje mesmo
Introdução
O Instagram ultrapassa 2 bilhões de usuários ativos mensais, com mais de 200 milhões de empresas usando contas comerciais. Se você desenvolve ferramentas de gestão de mídias sociais, plataformas de analytics ou integrações de e-commerce, integrar a API de Gráficos do Instagram é fundamental para automatizar operações e escalar o alcance.
Na prática: gerentes de mídias sociais que administram mais de 10 contas perdem de 20 a 30 horas por semana em tarefas manuais (postagens, respostas, relatórios). Uma integração robusta com a API do Instagram automatiza publicação, moderação, análise de sentimento e relatórios.
Este guia cobre a integração da API de Gráficos do Instagram: autenticação, publicação, insights, comentários, webhooks e checklist de produção. Ao final, você terá uma integração pronta para produção.
💡 Dica: Apidog simplifica o teste de integração de API. Teste endpoints do Instagram, valide OAuth, inspecione respostas e depure publicações no mesmo workspace. Importe specs, simule respostas e compartilhe testes com sua equipe.
O Que É a API de Gráficos do Instagram?
A API de Gráficos do Instagram oferece acesso programático a contas de Negócios e Criadores via API de Gráficos do Facebook. Permite:
- Publicação de conteúdo (fotos, vídeos, Reels, carrosséis)
- Insights e analytics
- Gerenciamento de comentários e menções
- Mensagens diretas (via API + Messenger)
- Rastreamento de hashtags/menções
- Gestão de Stories
- Tags de compras e produtos
Principais Recursos
| Recurso | Descrição |
|---|---|
| API baseada em Gráficos | Acesso via nós e conexões |
| OAuth 2.0 | Autenticação via Facebook Login |
| Webhooks | Notificações em tempo real |
| Limite de Taxa | 200 chamadas/hora por app |
| Publicação de Conteúdo | Fotos, vídeos, Reels, carrosséis |
| Insights | Engajamento, alcance, impressões |
| Moderação | Gerenciamento de comentários, menções, mensagens |
Requisitos da Conta
| Tipo de Conta | Acesso à API |
|---|---|
| Comercial | Acesso total |
| Criador de Conteúdo | Acesso total |
| Pessoal | Sem acesso (precisa converter) |
| Privada | Insights limitados |
Visão Geral da Arquitetura da API
A base da API:
https://graph.facebook.com/v18.0/
Versões da API Comparadas
| Versão | Status | Data Final | Uso recomendado |
|---|---|---|---|
| v18.0 | Atual | Mar 2026 | Novas integrações |
| v17.0 | Descontinuado | Jan 2026 | Integrações existentes |
| v16.0 | Aposentado | Expirado | Não usar |
Sempre use a versão estável mais recente.
Primeiros Passos: Configuração de Autenticação
Passo 1: Criar Conta de Desenvolvedor do Facebook
- Acesse o Portal de Desenvolvedores do Facebook
- Faça login
- Crie um App (tipo: Negócios)
- Adicione o produto Instagram Graph API
Passo 2: Vincular Conta Comercial do Instagram
- Vá em Configurações da Página do Facebook → Instagram
- Clique em Conectar Conta
- Faça login no Instagram e autorize
- Confirme a vinculação
Contas pessoais não usam a API; converta para Comercial ou Criador nas configurações do Instagram.
Passo 3: Obter Tokens de Acesso
Gere a URL de autorização OAuth:
const FB_APP_ID = process.env.FB_APP_ID;
const FB_APP_SECRET = process.env.FB_APP_SECRET;
const FB_REDIRECT_URI = process.env.FB_REDIRECT_URI;
const getAuthUrl = (state) => {
const params = new URLSearchParams({
client_id: FB_APP_ID,
redirect_uri: FB_REDIRECT_URI,
scope: 'instagram_basic,instagram_content_publish,instagram_manage_comments,instagram_manage_insights,pages_read_engagement',
state: state
});
return `https://www.facebook.com/v18.0/dialog/oauth?${params.toString()}`;
};
Permissões Necessárias
| Permissão | Descrição |
|---|---|
instagram_basic |
Perfil e mídias |
instagram_content_publish |
Publicar mídias |
instagram_manage_comments |
Ler/escrever comentários |
instagram_manage_insights |
Analytics |
pages_read_engagement |
Publicação |
pages_manage_posts |
Publicar na Página |
Passo 4: Trocar Token por Longa Duração
Troque token curto (1h) por longo (60 dias):
const exchangeForLongLivedToken = async (shortLivedToken) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/oauth/access_token?` +
`grant_type=fb_exchange_token&` +
`client_id=${FB_APP_ID}&` +
`client_secret=${FB_APP_SECRET}&` +
`fb_exchange_token=${shortLivedToken}`
);
const data = await response.json();
return data;
};
const longLivedToken = await exchangeForLongLivedToken(shortLivedToken);
console.log(`Token expira: ${new Date(longLivedToken.expires_at * 1000)}`);
Passo 5: Obter ID da Conta Comercial do Instagram
const getInstagramAccountId = async (pageId, accessToken) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/${pageId}?fields=instagram_business_account&access_token=${accessToken}`
);
const data = await response.json();
return data.instagram_business_account.id;
};
const igAccountId = await getInstagramAccountId('12345678', accessToken);
console.log(`ID da Conta do Instagram: ${igAccountId}`);
Passo 6: Fazer Chamadas Autenticadas da API
Use um cliente reutilizável:
const IG_BASE_URL = 'https://graph.facebook.com/v18.0';
const instagramRequest = async (endpoint, params = {}) => {
const url = new URL(`${IG_BASE_URL}${endpoint}`);
url.searchParams.append('access_token', process.env.INSTAGRAM_ACCESS_TOKEN);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.append(key, value);
});
const response = await fetch(url.toString());
if (!response.ok) {
const error = await response.json();
throw new Error(`Erro da API do Instagram: ${error.error.message}`);
}
return response.json();
};
// Exemplo de uso
const account = await instagramRequest(`/me`);
console.log(`Conta do Instagram: ${account.username}`);
Publicação de Conteúdo
Publicando uma Foto
const publishPhoto = async (igAccountId, photoData) => {
// 1. Criar contêiner de mídia
const containerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
image_url: photoData.imageUrl,
caption: photoData.caption,
location_id: photoData.locationId, // Opcional
is_carousel_item: 'false'
});
const creationId = containerResponse.id;
// 2. Publicar a mídia
const publishResponse = await instagramRequest(`/${igAccountId}/media_publish`, {
method: 'POST',
creation_id: creationId
});
return publishResponse;
};
// Exemplo de uso
const post = await publishPhoto({
igAccountId: '17841400000000000',
imageUrl: 'https://example.com/image.jpg',
caption: 'Animados para anunciar nosso novo produto! 🚀 #lançamento #inovação',
locationId: '123456789'
});
console.log(`ID da mídia publicada: ${post.id}`);
Publicando um Vídeo
const publishVideo = async (igAccountId, videoData) => {
// 1. Criar contêiner de mídia
const containerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
video_url: videoData.videoUrl,
cover_url: videoData.coverUrl, // Miniatura opcional
caption: videoData.caption,
media_type: 'REELS', // ou 'VIDEO' para o feed
share_to_feed: 'true'
});
const creationId = containerResponse.id;
// Aguarda o processamento do vídeo
await waitForVideoProcessing(creationId);
// 2. Publicar a mídia
const publishResponse = await instagramRequest(`/${igAccountId}/media_publish`, {
method: 'POST',
creation_id: creationId
});
return publishResponse;
};
const waitForVideoProcessing = async (creationId, maxAttempts = 30) => {
for (let i = 0; i < maxAttempts; i++) {
const status = await instagramRequest(`/${creationId}`);
if (status.status_code === 'FINISHED') {
return true;
} else if (status.status_code === 'EXPIRED') {
throw new Error('Processamento de vídeo expirou');
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
throw new Error('Tempo limite de processamento de vídeo');
};
Publicando um Carrossel
const publishCarousel = async (igAccountId, carouselData) => {
const children = [];
// 1. Criar cada item do carrossel
for (const item of carouselData.items) {
const containerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
[item.type === 'video' ? 'video_url' : 'image_url']: item.url,
caption: item.caption || '',
is_carousel_item: 'true'
});
children.push(containerResponse.id);
}
// 2. Criar contêiner de carrossel
const carouselContainerResponse = await instagramRequest(`/${igAccountId}/media`, {
method: 'POST',
media_type: 'CAROUSEL',
children: children.join(','),
caption: carouselData.caption
});
const creationId = carouselContainerResponse.id;
// 3. Publicar o carrossel
const publishResponse = await instagramRequest(`/${igAccountId}/media_publish`, {
method: 'POST',
creation_id: creationId
});
return publishResponse;
};
// Exemplo de uso
const carousel = await publishCarousel('17841400000000000', {
caption: 'Vitrine de produtos 2026',
items: [
{ type: 'image', url: 'https://example.com/img1.jpg', caption: 'Produto 1' },
{ type: 'image', url: 'https://example.com/img2.jpg', caption: 'Produto 2' },
{ type: 'video', url: 'https://example.com/vid1.mp4', caption: 'Demonstração' }
]
});
Tipos de Mídia
| Tipo | Parâmetros | Uso |
|---|---|---|
IMAGEM |
image_url, legenda | Post de foto |
VÍDEO |
video_url, cover_url, legenda | Post de vídeo |
REELS |
video_url, cover_url, legenda, share_to_feed | Reels |
CARROSSEL |
children (array), legenda | Múltiplas mídias |
Recuperando Mídia e Insights
Obtendo Mídia do Usuário
const getUserMedia = async (igAccountId, limit = 25) => {
const response = await instagramRequest(`/${igAccountId}/media`, {
fields: 'id,caption,media_type,media_url,permalink,timestamp,like_count,comments_count',
limit: limit.toString()
});
return response;
};
const media = await getUserMedia('17841400000000000');
media.data.forEach(item => {
console.log(`${item.media_type}: ${item.caption}`);
console.log(`Curtidas: ${item.like_count}, Comentários: ${item.comments_count}`);
console.log(`URL: ${item.permalink}`);
});
Obtendo Insights de Mídia
const getMediaInsights = async (mediaId) => {
const response = await instagramRequest(`/${mediaId}/insights`, {
fields: 'impressions,reach,engagement,saved,video_views,profile_visits,follows'
});
return response;
};
const insights = await getMediaInsights('17890000000000000');
insights.data.forEach(metric => {
console.log(`${metric.name}: ${metric.values[0].value}`);
});
Métricas de Insights Disponíveis
| Métrica | Descrição | Tipos de Mídia |
|---|---|---|
impressões |
Visualizações totais | Todos |
alcance |
Contas únicas alcançadas | Todos |
engajamento |
Curtidas + comentários + salvamentos | Todos |
salvos |
Quantas vezes salvo | Todos |
visualizações_de_vídeo |
Visualizações vídeo 3+ seg | Vídeo, Reels |
reproduções |
Reproduções totais | Vídeo, Reels |
visitas_ao_perfil |
Visitas ao perfil | Todos |
seguidores |
Seguidores ganhos | Todos |
comentários |
Total de comentários | Todos |
contagem_de_curtidas |
Total de curtidas | Todos |
Obtendo Insights da Conta
const getAccountInsights = async (igAccountId, metricNames, since = null, until = null) => {
const params = {
metric: metricNames.join(','),
period: 'day'
};
if (since) params.since = since;
if (until) params.until = until;
const response = await instagramRequest(`/${igAccountId}/insights`, params);
return response;
};
// Exemplo: últimos 30 dias
const accountInsights = await getAccountInsights(
'17841400000000000',
['impressions', 'reach', 'profile_views', 'email_contacts', 'website_clicks'],
'2026-02-23',
'2026-03-25'
);
accountInsights.data.forEach(metric => {
console.log(`${metric.name}:`);
metric.values.forEach(value => {
console.log(` ${value.end_time}: ${value.value}`);
});
});
Métricas Nível de Conta
| Métrica | Descrição |
|---|---|
impressões |
Visualizações de perfil + posts |
alcance |
Contas únicas alcançadas |
visualizações_de_perfil |
Visitas ao perfil |
cliques_no_site |
Cliques no link da bio |
contatos_por_email |
Toques no botão de e-mail |
cliques_em_chamada_telefônica |
Toques no botão de telefone |
cliques_em_mensagem_de_texto |
Toques em SMS |
cliques_em_obter_direções |
Cliques no endereço |
contagem_de_seguidores |
Total de seguidores |
cidade_da_audiência |
Cidades dos seguidores |
país_da_audiência |
Países dos seguidores |
gênero_idade_da_audiência |
Demografia |
Gerenciamento de Comentários
Obtendo Comentários
const getMediaComments = async (mediaId, limit = 50) => {
const response = await instagramRequest(`/${mediaId}/comments`, {
fields: 'id,text,timestamp,username,hidden',
limit: limit.toString()
});
return response;
};
const comments = await getMediaComments('17890000000000000');
comments.data.forEach(comment => {
console.log(`@${comment.username}: ${comment.text}`);
console.log(`Oculto: ${comment.hidden}`);
});
Respondendo a Comentários
const replyToComment = async (mediaId, commentId, replyText) => {
const response = await instagramRequest(`/${mediaId}/comments`, {
method: 'POST',
response_to: commentId,
message: replyText
});
return response;
};
const reply = await replyToComment(
'17890000000000000',
'17900000000000000',
'Obrigado pelo seu interesse! Verifique sua DM para mais detalhes.'
);
console.log(`Resposta publicada: ${reply.id}`);
Ocultando Comentários
const hideComment = async (commentId) => {
const response = await instagramRequest(`/${commentId}`, {
method: 'POST',
hide: 'true'
});
return response;
};
await hideComment('17900000000000000');
console.log('Comentário oculto');
Excluindo Comentários
const deleteComment = async (commentId) => {
await instagramRequest(`/${commentId}`, {
method: 'DELETE'
});
console.log('Comentário excluído');
};
Webhooks
Configurando Webhooks
const subscribeToWebhooks = async (appId, pageId, accessToken) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/${appId}/subscriptions`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
object: 'instagram',
callback_url: 'https://myapp.com/webhooks/instagram',
verify_token: process.env.WEBHOOK_VERIFY_TOKEN,
access_token: accessToken,
fields: ['comments', 'mentions', 'message_reactions']
})
}
);
return response.json();
};
Gerenciando Webhooks
const express = require('express');
const app = express();
// Verificar assinatura do webhook
app.get('/webhooks/instagram', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.WEBHOOK_VERIFY_TOKEN) {
console.log('Webhook verificado');
res.status(200).send(challenge);
} else {
res.status(403).send('Verificação falhou');
}
});
// Lidar com eventos de webhook
app.post('/webhooks/instagram', express.json(), async (req, res) => {
const body = req.body;
if (body.object !== 'instagram') {
return res.status(404).send('Não encontrado');
}
for (const entry of body.entry) {
const igId = entry.id;
const changes = entry.changes;
for (const change of changes) {
switch (change.field) {
case 'comments':
await handleNewComment(change.value);
break;
case 'mentions':
await handleMention(change.value);
break;
case 'message_reactions':
await handleReaction(change.value);
break;
}
}
}
res.status(200).send('OK');
});
async function handleNewComment(data) {
console.log(`Novo comentário na mídia ${data.media_id}`);
console.log(`De: ${data.from_id}`);
console.log(`Texto: ${data.text}`);
// Responder automaticamente ou moderar
if (isSpam(data.text)) {
await hideComment(data.id);
}
}
Campos de Webhook
| Campo | Gatilho |
|---|---|
comentários |
Novo comentário ou resposta |
menções |
Usuário menciona a conta |
reações_a_mensagens |
Reação a Story |
status_do_story |
Resposta/visualização de Story |
Limite de Taxa
Compreendendo os Limites de Taxa
- 200 chamadas/hora por app (compartilhado entre todos os usuários)
- Descoberta de Negócios: 200/hora por usuário
- Publicação de Conteúdo: limites por tipo de ação
Exceder limites: HTTP 400, subcódigo 613.
Melhores Práticas para Limite de Taxa
- Cache de respostas – evite buscas repetidas
- Agrupe requisições – use expansão de campos
- Use webhooks – atualizações em tempo real
- Implementação de backoff exponencial – para erros 429
const makeRateLimitedRequest = async (endpoint, params = {}, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await instagramRequest(endpoint, params);
return response;
} catch (error) {
if (error.message.includes('429') && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`Limite de taxa atingido. Tentando novamente em ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
};
Solução de Problemas Comuns
Problema: Token OAuth Expirado
Sintomas: Erro “token de acesso OAuth inválido”.
Soluções:
- Implemente renovação antes dos 60 dias
- Armazene a data de expiração e alerte o usuário
- Reautentique se expirar
Problema: Falha na Publicação de Mídia
Sintomas: Erro ao publicar.
Soluções:
- Verifique se a URL da imagem é pública
- Formato correto (JPEG, PNG, <8MB)
- Para vídeo: MP4, <1GB, <90s
- Aguarde processamento do vídeo
Problema: Insights Não Disponíveis
Sintomas: API retorna dados vazios.
Soluções:
- Certifique que a conta é Comercial ou Criador
- Aguarde 24-48h para preenchimento dos insights
- Verifique se há atividade suficiente
Lista de Verificação para Implantação em Produção
Antes do deploy, certifique-se de:
- [ ] Contas de teste são Comercial/Criador
- [ ] OAuth 2.0 com tokens longos implementado
- [ ] Tokens armazenados de forma segura (criptografia)
- [ ] Renovação automática de tokens
- [ ] Webhooks com HTTPS
- [ ] Gerenciamento de limite de taxa e fila
- [ ] Tratamento de erros robusto
- [ ] Logging de todas as chamadas
- [ ] Fluxos para moderação de conteúdo
- [ ] Testou com múltiplos tipos de contas
Casos de Uso no Mundo Real
Ferramenta de Agendamento de Mídias Sociais
- Desafio: Postagem manual em 50+ contas de clientes
- Solução: Agendamento e publicação automática via API
- Resultado: 80% economia de tempo, cronograma consistente
Funcionalidades:
- Calendário de conteúdo drag-and-drop
- Publicação automática de fotos, vídeos, carrosséis
- Sugestão de hashtags baseada no conteúdo
Automação de Atendimento ao Cliente
- Desafio: Resposta lenta a clientes
- Solução: Resposta automática via webhook
- Resultado: Tempo médio de resposta: 5min; 90% satisfação
Funcionalidades:
- Detecção de palavras-chave (preço, envio, disponibilidade)
- Resposta automática com links
- Escalonamento para humanos em casos complexos
Conclusão
A API de Gráficos do Instagram fornece acesso completo a recursos de contas de Negócios e Criadores. Pontos-chave para implementar:
- Autenticação OAuth 2.0 (tokens de 60 dias)
- Publicação de fotos, vídeos, Reels, carrosséis
- Insights de engajamento, alcance, demografia
- Webhooks para comentários/menções em tempo real
- Limite de taxa exige controle e cache
- Apidog otimiza teste de API e colaboração
Seção de Perguntas Frequentes (FAQ)
Como obtenho acesso à API do Instagram?
Crie uma conta de Desenvolvedor do Facebook, crie um app de Negócios, adicione Instagram Graph API e autentique via Facebook Login com as permissões certas.
Posso postar no Instagram automaticamente?
Sim. Use a API de publicação para fotos, vídeos, Reels e carrosséis em contas de Negócios e Criadores.
Quais tipos de contas do Instagram suportam a API?
Apenas contas de Negócios e Criadores. Contas pessoais não têm acesso total.
Como obtenho comentários do Instagram?
Use o endpoint de Comentários (/{media-id}/comments). Webhooks notificam em tempo real.
Quais são os limites de taxa do Instagram?
200 chamadas/hora por app. Alguns endpoints têm limites adicionais por usuário.
Posso publicar Stories via API?
Sim, Stories podem ser publicados via o fluxo de publicação como posts do feed.
Como acesso os Insights do Instagram?
Solicite permissão instagram_manage_insights no OAuth. Use o endpoint de Insights para métricas.
Posso responder a comentários automaticamente?
Sim, via API de Comentários. Automação é comum para atendimento ao cliente.
Dúvidas ou sugestões? Deixe seu comentário abaixo!
Top comments (0)