Search by

homlity / sdk-instagram

homlity

SDK PHP de Homlity para la Instagram Graph API con Instagram Login: OAuth embebido, tokens de larga duracion renovables y publicacion de imagenes, carruseles y reels. Sin dependencias de runtime.

v1.0.0 2026-09-09 18:27 UTC

This package is not auto-updated.

Last update: 2026-09-11 10:19:28 UTC


README

Homlity · Portal de desarrolladores

SDK de Instagram para PHP

Cliente de la Instagram API with Instagram Login: conexión de cuentas por OAuth, tokens de larga duración que se renuevan solos y publicación de imágenes, carruseles y reels.

Sin dependencias de runtime: PHP 8.1, ext-curl y ext-json.

Por qué «con Instagram Login» y no «con Facebook Login»

Meta ofrece dos caminos para publicar en Instagram. Este SDK habla el primero:

Instagram Login Facebook Login
Qué hace el usuario Entra con su cuenta de Instagram Entra con Facebook y elige página
Requiere página de Facebook No
Requiere Business Manager No
Tipo de cuenta Business o Creator Business

Para una inmobiliaria que sólo quiere publicar sus inmuebles, el segundo camino significa crear una página de Facebook, vincularla a Instagram y pasar por Business Manager antes de poder empezar. El primero es entrar con su usuario y contraseña de Instagram de siempre.

Instalación

composer require homlity/sdk-instagram

Uso

1. Conectar una cuenta

use Instagram\Sdk\Auth\Scope;
use Instagram\Sdk\Auth\State;
use Instagram\Sdk\Config;
use Instagram\Sdk\InstagramClient;

$config = new Config(
    appId: getenv('INSTAGRAM_APP_ID'),
    appSecret: getenv('INSTAGRAM_APP_SECRET'),
    redirectUri: 'https://tu-dominio.com/instagram/callback',
);

$client = new InstagramClient($config);

// El `state` firmado lleva de qué cuenta es la conexión y vuelve intacto.
$state = State::create(['tenant_id' => 77], getenv('APP_KEY'));

header('Location: ' . $client->oauth()->authorizationUrl(Scope::publishing(), $state));

En el callback:

$payload = State::verify($_GET['state'], getenv('APP_KEY'));   // lanza si no cuadra
$token   = $client->oauth()->connect($_GET['code']);           // token de 60 días

$account = InstagramClient::withToken($config, $token)->account()->me();

if (! $account->isPublishable()) {
    // Cuenta personal: la API de publicación no funciona sobre ella.
}

guardar($payload['tenant_id'], $token->toArray(), $account->toArray());

2. Publicar

$client = InstagramClient::withToken($config, $token);

$media = $client->publisher()->publishCarousel(
    $account->id(),
    ['https://cdn.tu-dominio.com/1.jpg', 'https://cdn.tu-dominio.com/2.jpg'],
    "Apartamento en El Poblado\n3 hab · 2 baños · 92 m²\n#medellin #arriendo"
);

echo $media->permalink();

publishCarousel() crea un contenedor por imagen, espera a que Instagram termine de descargarlas y sólo entonces publica. Publicar sin esa espera falla de forma intermitente: funciona con imágenes pequeñas y falla con las grandes.

Con una sola URL publica una foto normal, porque Instagram no admite carruseles de un elemento.

3. Mantener vivo el token

use Instagram\Sdk\Auth\AccessToken;
use Instagram\Sdk\Auth\RefreshingTokenProvider;

$provider = new RefreshingTokenProvider(
    $client->oauth(),
    AccessToken::fromStorage($guardado),
    fn (AccessToken $nuevo) => guardar($tenantId, $nuevo->toArray()),  // ← imprescindible
);

$client = new InstagramClient($config, $provider);

El token vive 60 días y se puede estirar otros 60 tantas veces como se quiera, pero sólo mientras no haya caducado: si expira, la única salida es que el usuario vuelva a autorizar. Por eso el proveedor renueva con siete días de margen y por eso el callback $onRefresh no es opcional en la práctica: sin él el token renovado se pierde al terminar la petición.

Lo que hay que hacer una sola vez en Meta

Nada de esto lo puede automatizar el SDK. Está detallado en docs/configuracion-meta.md:

  1. Crear una app en developers.facebook.com y añadirle el producto Instagram.
  2. Registrar la URI de retorno (HTTPS obligatorio).
  3. Registrar los avisos de desautorización y de borrado de datos, que Meta exige y este SDK verifica con SignedRequest.
  4. Pedir en App Review los permisos instagram_business_basic e instagram_business_content_publish.

Hasta que Meta apruebe la revisión, la app sólo funciona con las cuentas añadidas como testers en el panel.

Requisitos de las imágenes

Instagram se descarga las imágenes desde sus servidores, así que las URLs tienen que ser públicas: una URL firmada que caduque, detrás de VPN o que exija Authorization no le sirve.

Formato JPEG
Tamaño hasta 8 MB
Proporción entre 4:5 y 1.91:1
Carrusel de 2 a 10 imágenes
Pie de foto 2200 caracteres, 30 hashtags
Cuota 100 publicaciones cada 24 h

$client->media()->publishingLimit() dice cuántas van consumidas.

Errores

Cada situación tiene su excepción, para poder decidir sin leer mensajes:

Excepción Cuándo Qué hacer
OAuthException El code caducó, el state no cuadra, el token no se puede refrescar Rehacer la conexión
AuthException Token inválido o revocado Reconectar la cuenta
PermissionException Falta un permiso, o la cuenta no es Business Revisar App Review o el tipo de cuenta
MediaException Imagen inaccesible, formato o proporción no admitidos Corregir la imagen
RateLimitException Cuota de la app o las 100 publicaciones diarias Reintentar más tarde
ValidationException Parámetro inválido Corregir la llamada
TransportException Red, DNS, TLS, timeout Reintentar

ApiException expone errorCode(), errorSubcode(), providerMessage(), userMessage() y traceId() —este último es lo único que el soporte de Meta pide para investigar una incidencia.

Ni el token ni el app secret aparecen nunca en mensajes de excepción, var_dump() ni logs.

Tests

composer install && composer test

Mantenido por Homlity · homlity.com/desarrolladores