Cómo Utilizar la API de Hootsuite

Ashley Innocent

Ashley Innocent

25 March 2026

Cómo Utilizar la API de Hootsuite

Apidog para empresas

Despliegue local

SSO & RBAC

Conforme con SOC 2

Explorar Apidog Enterprise

Resumen

La API de Hootsuite permite a los desarrolladores integrarse programáticamente con los flujos de trabajo de gestión de redes sociales. Utiliza autenticación OAuth 2.0, puntos finales RESTful para perfiles, publicaciones, análisis y gestión de equipos, con límites de tasa de 50-200 solicitudes por minuto según el plan. Esta guía cubre la configuración de autenticación, la programación de publicaciones, la recuperación de análisis, la gestión de equipos y las estrategias de integración en producción.

Nota: Hootsuite ha desaprobado su API pública a partir de 2024. Esta guía cubre enfoques alternativos, incluidas las integraciones de socios de Hootsuite, webhooks y APIs de gestión de redes sociales de terceros que proporcionan una funcionalidad similar.

Introducción

Hootsuite gestiona más de 30 millones de cuentas de redes sociales para más de 200.000 empresas en más de 175 países. Para los desarrolladores que crean herramientas de redes sociales, plataformas de marketing o paneles de análisis, la integración de la API de redes sociales es esencial para llegar a esta masiva audiencia empresarial.

Esta es la realidad: los gestores de redes sociales que manejan más de 20 cuentas pierden entre 25 y 35 horas semanales en la publicación manual, el seguimiento del engagement y la generación de informes. Una sólida integración de la API de redes sociales automatiza la distribución de contenido, el monitoreo del engagement, el análisis de sentimientos y la generación de informes de rendimiento.

botón

Estado de la API de Hootsuite y alternativas

Situación actual de la API

A partir de 2024, Hootsuite ha desaprobado su API pública. Opciones de integración:

Enfoque Descripción Ideal para
APIs de Plataformas Nativas Integración directa con Facebook, Twitter, LinkedIn, etc. Control total, soluciones personalizadas
Audiense Inteligencia de audiencia propiedad de Hootsuite Análisis de audiencia
HeyOrca API de programación de redes sociales Calendarios de contenido
API de Buffer Gestión de redes sociales Equipos pequeños
API de Sprout Social Gestión social empresarial Grandes organizaciones
API de Agorapulse CRM de redes sociales Gestión de la comunidad

Enfoque recomendado: APIs de plataformas nativas

Para la mayoría de los casos de uso, la integración directa con las plataformas sociales ofrece la mayor flexibilidad:

Plataforma Nombre de la API Características clave
Facebook/Instagram Graph API Publicaciones, insights, comentarios
Twitter/X API v2 Tweets, análisis, streams
LinkedIn Marketing API Publicaciones, páginas de empresa, anuncios
Pinterest API v5 Pines, tableros, análisis
TikTok Display API Videos, información del usuario
YouTube Data API Videos, listas de reproducción, análisis

Primeros pasos: Autenticación multiplataforma

Paso 1: Registrar aplicaciones de desarrollador

Cree cuentas de desarrollador 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
  }
};

Paso 2: Implementar el flujo OAuth 2.0

Manejador OAuth unificado para múltiples 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();
};

Paso 3: Almacenar 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'
};

Programación y publicación de publicaciones

Creando una publicación multiplataforma

Publique en múltiples plataformas simultáneamente:

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();
};

Programación de publicaciones

Implemente la programación de publicaciones:

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álisis e informes

Obtención de análisis multiplataforma

Agregue métricas de todas las 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);
}

Gestión de equipos

Control de acceso basado en roles

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);
};

Limitación de tasa

Límites de tasa de la plataforma

Plataforma Límite Ventana
Facebook Graph 200 llamadas Por hora por usuario
Twitter API v2 300 tweets Cada 15 min
LinkedIn 100-500 llamadas Por día
Instagram 200 llamadas Por hora

Implementación del manejo de límites de tasa

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 verificación de implementación en producción

Antes de salir en vivo:

Casos de uso en el mundo real

Panel de control de redes sociales

Una agencia de marketing construye un panel de control unificado:

Distribución automatizada de contenido

Un editor automatiza el intercambio de artículos:

Conclusión

Aunque la API pública de Hootsuite está desaprobada, las APIs de plataformas nativas proporcionan capacidades completas de gestión de redes sociales. Puntos clave:

botón

Sección de Preguntas Frecuentes

¿Hootsuite todavía tiene una API?

Hootsuite desaprobó su API pública en 2024. Utilice las APIs de plataformas nativas o plataformas de gestión alternativas como Buffer, Sprout Social o Agorapulse.

¿Cómo publico en múltiples plataformas a la vez?

Implemente OAuth para cada plataforma y cree una función de publicación unificada que llame a la API de cada plataforma en paralelo.

¿Cuáles son los límites de tasa para las APIs de redes sociales?

Los límites varían: Facebook (200/hora), Twitter (300/15min), LinkedIn (100-500/día), Instagram (200/hora).

¿Cómo programo publicaciones?

Almacene las publicaciones en una base de datos con scheduled_time, luego use una cola de trabajos (Bull, Agenda) para publicarlas a la hora programada.

¿Puedo obtener análisis de todas las plataformas?

Sí, cada plataforma proporciona APIs de análisis. Agregue datos para informes multiplataforma.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs

Cómo Utilizar la API de Hootsuite