Resumo
A API do Hootsuite permite que os desenvolvedores se integrem programaticamente a fluxos de trabalho de gerenciamento de mídias sociais. Ela usa autenticação OAuth 2.0, endpoints RESTful para perfis, posts, análises e gerenciamento de equipe, com limites de taxa de 50-200 requisições por minuto, dependendo do plano. Este guia cobre a configuração de autenticação, agendamento de posts, recuperação de análises, gerenciamento de equipe e estratégias de integração em produção.
Nota: O Hootsuite descontinuou sua API pública a partir de 2024. Este guia aborda abordagens alternativas, incluindo integrações de parceiros do Hootsuite, webhooks e APIs de gerenciamento de mídias sociais de terceiros que fornecem funcionalidade semelhante.
Introdução
O Hootsuite gerencia mais de 30 milhões de contas de mídias sociais para mais de 200.000 empresas em mais de 175 países. Para desenvolvedores que constroem ferramentas de mídias sociais, plataformas de marketing ou painéis de análise, a integração da API de mídias sociais é essencial para atingir esse enorme público empresarial.
Aqui está a realidade: gerentes de mídias sociais que lidam com mais de 20 contas perdem de 25 a 35 horas semanais em postagem manual, rastreamento de engajamento e geração de relatórios. Uma sólida integração da API de mídias sociais automatiza a distribuição de conteúdo, o monitoramento de engajamento, a análise de sentimentos e a geração de relatórios de desempenho.
Status e Alternativas da API do Hootsuite
Situação Atual da API
A partir de 2024, o Hootsuite descontinuou sua API pública. Opções para integração:
| Abordagem | Descrição | Melhor Para |
|---|---|---|
| APIs Nativas da Plataforma | Integração direta com Facebook, Twitter, LinkedIn, etc. | Controle total, soluções personalizadas |
| Audiense | Inteligência de audiência de propriedade do Hootsuite | Análise de audiência |
| HeyOrca | API de agendamento de mídias sociais | Calendários de conteúdo |
| Buffer API | Gerenciamento de mídias sociais | Pequenas equipes |
| Sprout Social API | Gerenciamento social empresarial | Grandes organizações |
| Agorapulse API | CRM de mídias sociais | Gerenciamento de comunidade |
Abordagem Recomendada: APIs Nativas da Plataforma
Para a maioria dos casos de uso, a integração direta com as plataformas sociais oferece a maior flexibilidade:
| Plataforma | Nome da API | Principais Recursos |
|---|---|---|
| Facebook/Instagram | Graph API | Posts, insights, comentários |
| Twitter/X | API v2 | Tweets, análises, streams |
| Marketing API | Posts, páginas de empresa, anúncios | |
| API v5 | Pins, boards, análises | |
| TikTok | Display API | Vídeos, informações do usuário |
| YouTube | Data API | Vídeos, playlists, análises |
Começando: Autenticação Multiplataforma
Passo 1: Registrar Aplicativos de Desenvolvedor
Crie contas de desenvolvedor para cada plataforma:
// Store credentials securely
const SOCIAL_CREDENTIALS = {
facebook: {
appId: process.env.FB_APP_ID,
appSecret: process.env.FB_APP_SECRET,
redirectUri: process.env.FB_REDIRECT_URI
},
twitter: {
apiKey: process.env.TWITTER_API_KEY,
apiSecret: process.env.TWITTER_API_SECRET,
redirectUri: process.env.TWITTER_REDIRECT_URI
},
linkedin: {
clientId: process.env.LINKEDIN_CLIENT_ID,
clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
redirectUri: process.env.LINKEDIN_REDIRECT_URI
},
instagram: {
appId: process.env.FB_APP_ID, // Uses Facebook Login
appSecret: process.env.FB_APP_SECRET
}
};
Passo 2: Implementar Fluxo OAuth 2.0
Manipulador OAuth unificado para múltiplas plataformas:
const getAuthUrl = (platform, state) => {
const configs = {
facebook: {
url: 'https://www.facebook.com/v18.0/dialog/oauth',
params: {
client_id: SOCIAL_CREDENTIALS.facebook.appId,
redirect_uri: SOCIAL_CREDENTIALS.facebook.redirectUri,
scope: 'pages_manage_posts,pages_read_engagement,instagram_basic,instagram_content_publish',
state
}
},
twitter: {
url: 'https://twitter.com/i/oauth2/authorize',
params: {
client_id: SOCIAL_CREDENTIALS.twitter.apiKey,
redirect_uri: SOCIAL_CREDENTIALS.twitter.redirectUri,
scope: 'tweet.read tweet.write users.read offline.access',
state,
response_type: 'code'
}
},
linkedin: {
url: 'https://www.linkedin.com/oauth/v2/authorization',
params: {
client_id: SOCIAL_CREDENTIALS.linkedin.clientId,
redirect_uri: SOCIAL_CREDENTIALS.linkedin.redirectUri,
scope: 'w_member_social r_basicprofile',
state,
response_type: 'code'
}
}
};
const config = configs[platform];
const params = new URLSearchParams(config.params);
return `${config.url}?${params.toString()}`;
};
// Handle OAuth callback
const handleOAuthCallback = async (platform, code) => {
const tokenEndpoints = {
facebook: 'https://graph.facebook.com/v18.0/oauth/access_token',
twitter: 'https://api.twitter.com/2/oauth2/token',
linkedin: 'https://www.linkedin.com/oauth/v2/accessToken'
};
const response = await fetch(tokenEndpoints[platform], {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
client_id: SOCIAL_CREDENTIALS[platform].apiKey || SOCIAL_CREDENTIALS[platform].appId || SOCIAL_CREDENTIALS[platform].clientId,
client_secret: SOCIAL_CREDENTIALS[platform].appSecret || SOCIAL_CREDENTIALS[platform].apiSecret,
redirect_uri: SOCIAL_CREDENTIALS[platform].redirectUri,
code,
grant_type: 'authorization_code'
})
});
return response.json();
};
Passo 3: Armazenar Tokens de Forma Segura
// Database schema for social tokens
const SocialToken = {
userId: 'user_123',
platform: 'facebook',
accessToken: 'encrypted_token_here',
refreshToken: 'encrypted_refresh_token',
tokenExpiry: Date.now() + 5183999, // 60 days
scopes: ['pages_manage_posts', 'pages_read_engagement'],
pageId: 'page_456', // For Facebook/Instagram
pageName: 'My Business Page'
};
Agendamento e Publicação de Posts
Criando um Post Multiplataforma
Publique em várias plataformas simultaneamente:
const createSocialPost = async (postData) => {
const results = {};
// Facebook Page Post
if (postData.platforms.includes('facebook')) {
results.facebook = await postToFacebook({
pageId: postData.facebookPageId,
message: postData.message,
link: postData.link,
photo: postData.photo
});
}
// Twitter Post
if (postData.platforms.includes('twitter')) {
results.twitter = await postToTwitter({
text: postData.message,
media: postData.photo
});
}
// LinkedIn Post
if (postData.platforms.includes('linkedin')) {
results.linkedin = await postToLinkedIn({
authorUrn: postData.linkedinAuthorUrn,
text: postData.message,
contentUrl: postData.link
});
}
// Instagram Post
if (postData.platforms.includes('instagram')) {
results.instagram = await postToInstagram({
igAccountId: postData.igAccountId,
imageUrl: postData.photo,
caption: postData.message
});
}
return results;
};
// Facebook posting
const postToFacebook = async (postData) => {
const token = await getFacebookPageToken(postData.pageId);
const params = new URLSearchParams({
message: postData.message,
access_token: token
});
if (postData.link) {
params.append('link', postData.link);
}
if (postData.photo) {
params.append('photo', postData.photo);
}
const response = await fetch(
`https://graph.facebook.com/v18.0/${postData.pageId}/feed?${params.toString()}`,
{ method: 'POST' }
);
return response.json();
};
// Twitter posting
const postToTwitter = async (postData) => {
const token = await getTwitterToken();
let mediaIds = [];
if (postData.media) {
// Upload media first
const mediaUpload = await uploadTwitterMedia(postData.media, token);
mediaIds = [mediaUpload.media_id_string];
}
const response = await fetch('https://api.twitter.com/2/tweets', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: postData.text,
media: mediaIds.length > 0 ? { media_ids: mediaIds } : undefined
})
});
return response.json();
};
// LinkedIn posting
const postToLinkedIn = async (postData) => {
const token = await getLinkedInToken();
const post = {
author: postData.authorUrn,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text: postData.text
},
shareMediaCategory: postData.contentUrl ? 'ARTICLE' : 'NONE',
media: postData.contentUrl ? [{
status: 'READY',
media: postData.contentUrn,
description: { text: postData.text }
}] : []
}
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
}
};
const response = await fetch('https://api.linkedin.com/v2/ugcPosts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'X-Restli-Protocol-Version': '2.0.0'
},
body: JSON.stringify(post)
});
return response.json();
};
// Instagram posting
const postToInstagram = async (postData) => {
const token = await getInstagramToken();
// Step 1: Create media container
const containerResponse = await fetch(
`https://graph.facebook.com/v18.0/${postData.igAccountId}/media`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` },
body: JSON.stringify({
image_url: postData.imageUrl,
caption: postData.caption
})
}
);
const container = await containerResponse.json();
// Step 2: Publish
const publishResponse = await fetch(
`https://graph.facebook.com/v18.0/${postData.igAccountId}/media_publish`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` },
body: JSON.stringify({ creation_id: container.id })
}
);
return publishResponse.json();
};
Agendando Posts
Implementar agendamento de posts:
const schedulePost = async (postData, scheduledTime) => {
// Store in database for later execution
const scheduledPost = await db.scheduledPosts.create({
message: postData.message,
platforms: postData.platforms,
scheduledTime: scheduledTime,
status: 'pending',
media: postData.media,
link: postData.link
});
// Set up job queue
await jobQueue.add('publish-social-post', {
postId: scheduledPost.id
}, {
delay: scheduledTime - Date.now()
});
return scheduledPost;
};
// Job processor
jobQueue.process('publish-social-post', async (job) => {
const post = await db.scheduledPosts.findById(job.data.postId);
try {
const result = await createSocialPost(post);
await db.scheduledPosts.update(post.id, {
status: 'published',
publishedAt: new Date(),
results: result
});
return result;
} catch (error) {
await db.scheduledPosts.update(post.id, {
status: 'failed',
error: error.message
});
throw error;
}
});
Análises e Relatórios
Obtendo Análises Multiplataforma
Agregue métricas de todas as plataformas:
const getSocialAnalytics = async (accountId, dateRange) => {
const analytics = {
facebook: await getFacebookAnalytics(accountId.facebook, dateRange),
twitter: await getTwitterAnalytics(accountId.twitter, dateRange),
linkedin: await getLinkedInAnalytics(accountId.linkedin, dateRange),
instagram: await getInstagramAnalytics(accountId.instagram, dateRange)
};
// Aggregate metrics
const totals = {
impressions: sum(analytics, 'impressions'),
engagement: sum(analytics, 'engagement'),
clicks: sum(analytics, 'clicks'),
shares: sum(analytics, 'shares'),
comments: sum(analytics, 'comments'),
newFollowers: sum(analytics, 'newFollowers')
};
return { analytics, totals };
};
// Facebook Insights
const getFacebookAnalytics = async (pageId, dateRange) => {
const token = await getFacebookPageToken(pageId);
const metrics = [
'page_impressions_unique',
'page_engaged_users',
'page_post_engagements',
'page_clicks',
'page_fan_adds'
];
const params = new URLSearchParams({
metric: metrics.join(','),
since: dateRange.from,
until: dateRange.until,
access_token: token
});
const response = await fetch(
`https://graph.facebook.com/v18.0/${pageId}/insights?${params.toString()}`
);
return response.json();
};
// Twitter Analytics
const getTwitterAnalytics = async (userId, dateRange) => {
const token = await getTwitterToken();
const response = await fetch(
`https://api.twitter.com/2/users/${userId}/metrics/private`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
);
return response.json();
};
// LinkedIn Analytics
const getLinkedInAnalytics = async (organizationId, dateRange) => {
const token = await getLinkedInToken();
const response = await fetch(
`https://api.linkedin.com/v2/organizationalEntityFollowerStatistics?q=organizationalEntity&organizationalEntity=${organizationId}`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
);
return response.json();
};
// Instagram Insights
const getInstagramAnalytics = async (igAccountId, dateRange) => {
const token = await getInstagramToken();
const metrics = [
'impressions',
'reach',
'engagement',
'profile_views',
'follower_count'
];
const params = new URLSearchParams({
metric: metrics.join(','),
period: 'day',
since: dateRange.from,
until: dateRange.until
});
const response = await fetch(
`https://graph.facebook.com/v18.0/${igAccountId}/insights?${params.toString()}`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
);
return response.json();
};
function sum(analytics, metric) {
return Object.values(analytics).reduce((total, platform) => {
return total + (platform.data?.[metric] || 0);
}, 0);
}
Gerenciamento de Equipe
Controle de Acesso Baseado em Função
const TEAM_ROLES = {
ADMIN: 'admin',
MANAGER: 'manager',
CONTRIBUTOR: 'contributor',
VIEWER: 'viewer'
};
const ROLE_PERMISSIONS = {
[TEAM_ROLES.ADMIN]: ['create', 'read', 'update', 'delete', 'manage_team', 'billing'],
[TEAM_ROLES.MANAGER]: ['create', 'read', 'update', 'approve_posts'],
[TEAM_ROLES.CONTRIBUTOR]: ['create', 'read'],
[TEAM_ROLES.VIEWER]: ['read']
};
const checkPermission = (userRole, requiredPermission) => {
const permissions = ROLE_PERMISSIONS[userRole] || [];
return permissions.includes(requiredPermission);
};
Limitação de Taxas
Limites de Taxa da Plataforma
| Plataforma | Limite | Janela |
|---|---|---|
| Facebook Graph | 200 chamadas | Por hora por usuário |
| Twitter API v2 | 300 tweets | Por 15 min |
| 100-500 chamadas | Por dia | |
| 200 chamadas | Por hora |
Implementando o Tratamento de Limite de Taxa
class SocialMediaRateLimiter {
constructor() {
this.limits = {
facebook: { limit: 200, window: 3600000 },
twitter: { limit: 300, window: 900000 },
linkedin: { limit: 500, window: 86400000 },
instagram: { limit: 200, window: 3600000 }
};
this.counters = {};
}
async request(platform, endpoint, options) {
await this.waitForCapacity(platform);
const response = await fetch(endpoint, options);
this.incrementCounter(platform);
return response;
}
async waitForCapacity(platform) {
const limit = this.limits[platform];
const counter = this.counters[platform] || { count: 0, resetTime: Date.now() };
if (Date.now() > counter.resetTime + limit.window) {
counter.count = 0;
counter.resetTime = Date.now();
}
if (counter.count >= limit.limit) {
const waitTime = counter.resetTime + limit.window - Date.now();
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.counters[platform] = counter;
}
incrementCounter(platform) {
if (!this.counters[platform]) {
this.counters[platform] = { count: 0, resetTime: Date.now() };
}
this.counters[platform].count++;
}
}
Lista de Verificação para Implantação em Produção
Antes de entrar em produção:
- [ ] Implementar OAuth 2.0 para todas as plataformas
- [ ] Armazenar tokens de forma segura com criptografia
- [ ] Configurar atualização automática de tokens
- [ ] Implementar limitação de taxa por plataforma
- [ ] Adicionar tratamento de erros abrangente
- [ ] Configurar log para todas as chamadas de API
- [ ] Criar fluxos de trabalho de aprovação de posts
- [ ] Implementar moderação de conteúdo
- [ ] Configurar agregação de análises
- [ ] Criar mecanismos de postagem de backup
Casos de Uso do Mundo Real
Painel de Mídias Sociais
Uma agência de marketing constrói um painel unificado:
- Desafio: Gerenciar mais de 50 contas de clientes em várias plataformas
- Solução: Painel central com postagem multiplataforma
- Resultado: 60% de economia de tempo, presença de marca consistente
Distribuição Automatizada de Conteúdo
Um editor automatiza o compartilhamento de artigos:
- Desafio: Compartilhamento manual de novo conteúdo
- Solução: Publicação automática de novos artigos em todas as plataformas
- Resultado: Distribuição instantânea, 3x mais tráfego social
Conclusão
Embora a API pública do Hootsuite esteja descontinuada, as APIs nativas da plataforma fornecem recursos abrangentes de gerenciamento de mídias sociais. Principais aprendizados:
- Implementar OAuth 2.0 para cada plataforma separadamente
- Os limites de taxa variam significativamente por plataforma
- A postagem unificada exige implementações específicas da plataforma
- A agregação de análises fornece insights multiplataforma
- Apidog agiliza o teste de API e a colaboração em equipe
Seção de Perguntas Frequentes
O Hootsuite ainda tem uma API?
O Hootsuite descontinuou sua API pública em 2024. Use APIs nativas da plataforma ou plataformas de gerenciamento alternativas como Buffer, Sprout Social ou Agorapulse.
Como faço para postar em várias plataformas de uma vez?
Implemente OAuth para cada plataforma e crie uma função de postagem unificada que chame a API de cada plataforma em paralelo.
Quais são os limites de taxa para as APIs de mídias sociais?
Os limites variam: Facebook (200/hora), Twitter (300/15min), LinkedIn (100-500/dia), Instagram (200/hora).
Como faço para agendar posts?
Armazene os posts em um banco de dados com `scheduled_time` e, em seguida, use uma fila de jobs (Bull, Agenda) para publicar no horário agendado.
Posso obter análises de todas as plataformas?
Sim, cada plataforma fornece APIs de análise. Agregue os dados para relatórios multiplataforma.
