En bref
L'API Hootsuite permettait aux développeurs d'intégrer des flux de travail de gestion des médias sociaux par programmation. Elle utilisait 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 explique comment configurer l'authentification, planifier des publications, récupérer des analyses, gérer une équipe et intégrer ces workflows en production.
Note : Hootsuite a déprécié son API publique depuis 2024. Ce guide présente des solutions alternatives, notamment les intégrations partenaires Hootsuite, les webhooks et les API tierces qui offrent des fonctionnalités similaires.
Essayez Apidog dès aujourd'hui
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 créant des outils de gestion sociale, des plateformes marketing ou des dashboards analytiques, intégrer des API de médias sociaux reste essentiel pour toucher cette audience.
Concrètement, les gestionnaires de médias sociaux gérant plus de 20 comptes perdent 25 à 35 heures par semaine en publication manuelle, suivi de l'engagement et reporting. Une intégration API robuste automatise la distribution de contenu, la surveillance, l'analyse des sentiments et la génération de rapports.
Statut de l'API Hootsuite et alternatives
Situation actuelle de l'API
Depuis 2024, l'API publique Hootsuite est dépréciée. Voici les options d'intégration à privilégier :
| 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 besoins, intégrez directement les API des plateformes sociales pour bénéficier de la flexibilité maximale :
| 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, publicités | |
| API v5 | Épingles, tableaux, analyses | |
| TikTok | Display API | Vidéos, infos utilisateur |
| YouTube | Data API | Vidéos, playlists, analyses |
Démarrage : Authentification multiplateforme
Étape 1 : Enregistrer les applications de développeur
Créez des comptes développeur pour chaque plateforme et stockez les identifiants de façon sécurisée :
// Stocker les credentials de manière sécurisée
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, // Utilise Facebook Login
appSecret: process.env.FB_APP_SECRET
}
};
Étape 2 : Implémenter le flux OAuth 2.0
Utilisez un gestionnaire OAuth centralisé pour toutes les 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()}`;
};
// Callback OAuth
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é
Utilisez un schéma adapté pour stocker les tokens :
// Schéma base de données pour les jetons sociaux
const SocialToken = {
userId: 'user_123',
platform: 'facebook',
accessToken: 'encrypted_token_here',
refreshToken: 'encrypted_refresh_token',
tokenExpiry: Date.now() + 5183999, // 60 jours
scopes: ['pages_manage_posts', 'pages_read_engagement'],
pageId: 'page_456', // Pour Facebook/Instagram
pageName: 'My Business Page'
};
Planification et publication de posts
Créer un post multiplateforme
Publiez sur plusieurs plateformes en parallèle :
const createSocialPost = async (postData) => {
const results = {};
// Facebook
if (postData.platforms.includes('facebook')) {
results.facebook = await postToFacebook({
pageId: postData.facebookPageId,
message: postData.message,
link: postData.link,
photo: postData.photo
});
}
// Twitter
if (postData.platforms.includes('twitter')) {
results.twitter = await postToTwitter({
text: postData.message,
media: postData.photo
});
}
// LinkedIn
if (postData.platforms.includes('linkedin')) {
results.linkedin = await postToLinkedIn({
authorUrn: postData.linkedinAuthorUrn,
text: postData.message,
contentUrl: postData.link
});
}
// Instagram
if (postData.platforms.includes('instagram')) {
results.instagram = await postToInstagram({
igAccountId: postData.igAccountId,
imageUrl: postData.photo,
caption: postData.message
});
}
return results;
};
// Publication Facebook
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();
};
// Publication Twitter
const postToTwitter = async (postData) => {
const token = await getTwitterToken();
let mediaIds = [];
if (postData.media) {
// Upload média d'abord
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();
};
// Publication LinkedIn
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();
};
// Publication Instagram
const postToInstagram = async (postData) => {
const token = await getInstagramToken();
// Étape 1 : Création du container media
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();
// Étape 2 : Publication
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
Planifiez vos posts via une base de données et une file de tâches :
const schedulePost = async (postData, scheduledTime) => {
// Enregistrer dans la BDD pour exécution différée
const scheduledPost = await db.scheduledPosts.create({
message: postData.message,
platforms: postData.platforms,
scheduledTime: scheduledTime,
status: 'pending',
media: postData.media,
link: postData.link
});
// Ajout à la file de jobs
await jobQueue.add('publish-social-post', {
postId: scheduledPost.id
}, {
delay: scheduledTime - Date.now()
});
return scheduledPost;
};
// Traitement du job
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
Récupérez et agrégerez 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)
};
// Agrégation
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
Implémentez une gestion des permissions par rôle :
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 production, vérifiez les points suivants :
- [ ] Implémenter OAuth 2.0 pour toutes les plateformes
- [ ] Stocker les jetons de façon sécurisée (chiffrement)
- [ ] Configurer l'actualisation automatique des jetons
- [ ] Implémenter la limitation de débit par plateforme
- [ ] Ajouter une gestion des erreurs robuste
- [ ] Configurer la journalisation de tous les appels API
- [ ] Créer des workflows d'approbation de publication
- [ ] Implémenter la modération de contenu
- [ ] Configurer l'agrégation d'analyses
- [ ] Mettre en place des mécanismes de publication de secours
Cas d'utilisation réels
Tableau de bord des médias sociaux
- Défi : Gérer plus de 50 comptes clients sur plusieurs plateformes
- Solution : Dashboard centralisé avec publication multiplateforme
- Résultat : 60 % de gain de temps, branding cohérent
Distribution de contenu automatisée
- Défi : Partage manuel du nouveau contenu
- Solution : Publication automatique de chaque nouvel article sur toutes les plateformes
- Résultat : Distribution instantanée, trafic social multiplié par 3
Conclusion
Même si l'API publique Hootsuite est dépréciée, les API natives offrent de puissantes capacités de gestion sociale. Retenez :
- Implémentez OAuth 2.0 séparément pour chaque plateforme
- Les limites de débit varient fortement selon la plateforme
- La publication unifiée exige des implémentations spécifiques à chaque API
- L'agrégation d'analyses fournit une vue consolidée
- Apidog simplifie les tests d'API et la collaboration en équipe
Section FAQ
Hootsuite a-t-il toujours une API ?
Hootsuite a déprécié son API publique en 2024. Utilisez les API natives des plateformes ou des solutions 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 les 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/15 min), 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 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égez les données pour générer des rapports multiplateformes.
Top comments (0)