En bref
L'API Hootsuite permet aux développeurs d'intégrer des flux de travail de gestion des médias sociaux par programmation. Elle utilise l'authentification OAuth 2.0, des points de terminaison RESTful pour les profils, les publications, l'analyse et la gestion d'équipe, avec des limites de débit de 50 à 200 requêtes par minute selon le plan. Ce guide couvre la configuration de l'authentification, la planification des publications, la récupération des analyses, la gestion d'équipe et les stratégies d'intégration en production.
Note : Hootsuite a déprécié son API publique depuis 2024. Ce guide couvre des approches alternatives, y compris les intégrations partenaires de Hootsuite, les webhooks, et les API tierces de gestion des médias sociaux qui offrent des fonctionnalités similaires.
Introduction
Hootsuite gère plus de 30 millions de comptes de médias sociaux pour plus de 200 000 entreprises dans plus de 175 pays. Pour les développeurs qui créent des outils de médias sociaux, des plateformes marketing ou des tableaux de bord analytiques, l'intégration d'API de médias sociaux est essentielle pour atteindre cette vaste audience commerciale.
Voici la réalité : les gestionnaires de médias sociaux qui gèrent plus de 20 comptes perdent 25 à 35 heures par semaine en publication manuelle, suivi de l'engagement et génération de rapports. Une solide intégration d'API de médias sociaux automatise la distribution de contenu, la surveillance de l'engagement, l'analyse des sentiments et les rapports de performance.
Statut de l'API Hootsuite et alternatives
Situation actuelle de l'API
Depuis 2024, Hootsuite a déprécié son API publique. Options d'intégration :
| Approche | Description | Idéal pour |
|---|---|---|
| API de Plateformes Natives | Intégration directe avec Facebook, Twitter, LinkedIn, etc. | Contrôle total, solutions personnalisées |
| Audiense | Intelligence d'audience détenue par Hootsuite | Analyse d'audience |
| HeyOrca | API de planification de médias sociaux | Calendriers de contenu |
| API Buffer | Gestion des médias sociaux | Petites équipes |
| API Sprout Social | Gestion sociale d'entreprise | Grandes organisations |
| API Agorapulse | CRM de médias sociaux | Gestion de communauté |
Approche recommandée : API de plateformes natives
Pour la plupart des cas d'utilisation, l'intégration directe avec les plateformes sociales offre la plus grande flexibilité :
| Plateforme | Nom de l'API | Fonctionnalités clés |
|---|---|---|
| Facebook/Instagram | Graph API | Publications, statistiques, commentaires |
| Twitter/X | API v2 | Tweets, analyses, flux |
| Marketing API | Publications, pages d'entreprise, publicités | |
| API v5 | Épingles, tableaux, analyses | |
| TikTok | Display API | Vidéos, informations utilisateur |
| YouTube | Data API | Vidéos, listes de lecture, analyses |
Démarrage : Authentification multiplateforme
Étape 1 : Enregistrer les applications de développeur
Créez des comptes développeur pour chaque plateforme :
// 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
}
};
Étape 2 : Implémenter le flux OAuth 2.0
Gestionnaire OAuth unifié pour plusieurs plateformes :
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();
};
Étape 3 : Stocker les jetons en toute sécurité
// 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'
};
Planification et publication de posts
Créer un post multiplateforme
Publiez sur plusieurs plateformes simultanément :
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();
};
Planification des posts
Implémentez la planification des 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;
}
});
Analyse et rapports
Récupération d'analyses multiplateformes
Agréguer les métriques de toutes les plateformes :
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);
}
Gestion d'équipe
Contrôle d'accès basé sur les rôles
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);
};
Limitation de débit
Limites de débit des plateformes
| Plateforme | Limite | Fenêtre |
|---|---|---|
| Facebook Graph | 200 appels | Par heure et par utilisateur |
| Twitter API v2 | 300 tweets | Par 15 min |
| 100-500 appels | Par jour | |
| 200 appels | Par heure |
Implémentation de la gestion des limites de débit
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++;
}
}
Liste de contrôle de déploiement en production
Avant de passer en direct :
- [ ] Implémenter OAuth 2.0 pour toutes les plateformes
- [ ] Stocker les jetons en toute sécurité avec chiffrement
- [ ] Configurer l'actualisation automatique des jetons
- [ ] Implémenter la limitation de débit par plateforme
- [ ] Ajouter une gestion complète des erreurs
- [ ] Configurer la journalisation pour tous les appels d'API
- [ ] Créer des flux de travail d'approbation de publication
- [ ] Implémenter la modération de contenu
- [ ] Configurer l'agrégation d'analyses
- [ ] Créer des mécanismes de publication de secours
Cas d'utilisation réels
Tableau de bord des médias sociaux
Une agence marketing construit un tableau de bord unifié :
- Défi : Gérer plus de 50 comptes clients sur différentes plateformes
- Solution : Tableau de bord central avec publication multiplateforme
- Résultat : 60 % de gain de temps, présence de marque cohérente
Distribution de contenu automatisée
Un éditeur automatise le partage d'articles :
- Défi : Partage manuel de nouveau contenu
- Solution : Publication automatique de nouveaux articles sur toutes les plateformes
- Résultat : Distribution instantanée, trafic social multiplié par 3
Conclusion
Bien que l'API publique de Hootsuite soit dépréciée, les API de plateformes natives offrent des capacités complètes de gestion des médias sociaux. Points clés à retenir :
- Implémentez OAuth 2.0 pour chaque plateforme séparément
- Les limites de débit varient considérablement selon la plateforme
- La publication unifiée nécessite des implémentations spécifiques à chaque plateforme
- L'agrégation d'analyses fournit des informations multiplateformes
- Apidog simplifie les tests d'API et la collaboration d'équipe
Section FAQ
Hootsuite a-t-il toujours une API ?
Hootsuite a déprécié son API publique en 2024. Utilisez les API de plateformes natives ou des plateformes de gestion alternatives comme Buffer, Sprout Social ou Agorapulse.
Comment publier sur plusieurs plateformes à la fois ?
Implémentez OAuth pour chaque plateforme et créez une fonction de publication unifiée qui appelle l'API de chaque plateforme en parallèle.
Quelles sont les limites de débit pour les API de médias sociaux ?
Les limites varient : Facebook (200/heure), Twitter (300/15min), LinkedIn (100-500/jour), Instagram (200/heure).
Comment planifier des posts ?
Stockez les posts dans une base de données avec un `scheduled_time`, puis utilisez une file d'attente de tâches (Bull, Agenda) pour publier à l'heure prévue.
Puis-je obtenir des analyses de toutes les plateformes ?
Oui, chaque plateforme fournit des API d'analyse. Agréguez les données pour des rapports multiplateformes.
