Kostenlos testen
Handbuch

Instagram (Content-Analyse)

Instagram-Profi-Konten per Login verbinden, Beiträge und Insights lesen — für den eigenen Workspace oder als Partner-App über die API.

TaskMonkey liest Instagram-Profi-Konten (Business oder Creator) über die Instagram API with Instagram Login (graph.instagram.com). Nur lesend: Profil, Beiträge, Beitrags- und Konto-Insights. Es wird nichts gepostet, keine Kommentare oder Direktnachrichten gelesen.

Zwei Wege:

  • Eigener Workspace — Verbindungen (/manage/connections, Karte „Instagram, Facebook, WhatsApp“) → Instagram verbinden (/manage/instagram leitet dorthin um). Danach nutzen Assistenten die Tools, z. B. Content-Analyse.
  • Partner-App — eine externe App schickt ihre Nutzer auf einen vom Partner-Server signierten Link https://taskmonkey.de/connect/instagram?partner=<key>&ref=<nutzer-id>&exp=<unix>&sig=<hmac> (siehe Links signieren). Die Nutzer brauchen kein TaskMonkey-Konto. Die App holt die Daten danach per API-Key mit ref ab.

Berechtigungen

Scope Wofür
instagram_business_basic Profil (Benutzername, Kontotyp, Follower, Beitragszahl) und Beitragsliste
instagram_business_manage_insights Kennzahlen je Beitrag und Konto (Reichweite, Aufrufe, Interaktionen …)

Private Konten werden abgewiesen („Profi-Konto erforderlich“) — Umstellung in der Instagram-App unter Einstellungen → Kontotyp und Tools. Werden im Dialog nicht beide Berechtigungen erteilt, wird nichts gespeichert („Berechtigungen fehlen“, Rücksprung mit reason=missing_scopes).

Ablauf

  1. Start: /manage/instagram/connect (Workspace, POST) bzw. /connect/instagram?partner=…&ref=…&exp=…&sig=…[&redirect_url=…] (Partner, Signatur wird geprüft). Die Partner-Seite erklärt vorher: „Ihre Instagram-Daten werden über TaskMonkey für <Partner> ausgewertet“.
  2. Instagram-Dialog https://www.instagram.com/oauth/authorize mit signiertem state (HMAC, 15 min, an eine Cookie-Nonce im Browser gebunden, serverseitig nur einmal verwendbar).
  3. Callback https://app.taskmonkey.de/connect/instagram/callback: Code → kurzlebiger Token (api.instagram.com/oauth/access_token) → Long-Lived-Token, 60 Tage (graph.instagram.com/access_token, ig_exchange_token) → /me (Konto-ID, Benutzername, Kontotyp).
  4. Speichern in instagram_connections — Token verschlüsselt (OAuthTokenCrypto, Schlüssel OAUTH_TOKEN_KEY). Webhook instagram.connected.
  5. Rücksprung: Partner → redirect_url?ref=<ref>&status=connected|denied|error[&reason=…], Workspace → /manage/instagram (→ Verbindungen).

Token-Verlängerung: bin/cake instagram_refresh läuft täglich um 04:00 (cronjobs.sh) und verlängert alle Tokens, die in weniger als 30 Tagen ablaufen (ig_refresh_token, frühestens 24 h nach Ausgabe). Abgelaufene oder ungültige Tokens werden gelöscht, die Verbindung steht auf expired, Webhook instagram.revoked.

Tools

Alle in config/tenants/_shared/tools/instagram/, für jeden Workspace verfügbar, nur lesend, per API-Key aufrufbar (external_api).

Tool Liefert
instagramGetProfile Benutzername, Name, Kontotyp, Follower, Gefolgt, Beitragszahl
instagramListMedia Beiträge (neueste zuerst) mit Typ, Bildunterschrift, Datum, Likes, Kommentare, Link; limit (1–100), after → next_cursor
instagramGetMediaInsights Kennzahlen eines Beitrags: media_id, media_product_type (FEED/REELS/STORY), optional metrics
instagramGetAccountInsights Konto-Summen für max. 30 Tage (since/until, Standard 28 Tage), optional breakdown=media_product_type

Welche Verbindung? Ohne ref die eigene des Workspaces (bei mehreren: account=<benutzername>). Mit ref die Verbindung eines Partner-Nutzers — nur in dem Workspace, dem der Partner gehört.

Auth im ToolRunner: apis.instagram.auth.type = instagram_connection (App\Tooling\Auth\InstagramConnectionAuth). Der Token kommt aus der Verbindung, nie aus Config oder Args, geht nur an https://graph.instagram.com und wird aus Antworten entfernt (Metas Paging-Links enthalten ihn).

Hinweise von Meta: Kennzahlen können bis zu 48 h nachlaufen; einige gibt es erst ab 100 Followern; Stories nur 24 h; impressions, plays, video_views sind abgekündigt (stattdessen views).

Assistant „Content-Analyse“

_shared/assistants/instagram_content_analyse.php, standardmäßig versteckt, im meco-Workspace sichtbar. Liest die letzten 30 Beiträge plus Insights und liefert Kurzfazit, Top/Flop-Tabelle, Muster (Format, Uhrzeit, Einstieg/Hook, Hashtags, Länge/CTA) und 3–5 Vorschläge. Aktivieren in einem Workspace:

return ['assistants.instagram_content_analyse.hidden' => false];

Der Prompt ist Config (assistants.instagram_content_analyse.prompt) und lässt sich pro Workspace überschreiben.

Partner einrichten

Partner sind Plattform-Config (config/instagram.php, Instagram.partners), nicht Workspace-Config — ein Workspace kann sich nicht selbst zum Partner machen oder Rücksprung-Ziele eintragen.

'partners' => [
    'acme' => [
        'name' => 'Acme Creator Studio',          // steht auf der Erklärseite
        'tenant' => 'acme',                        // Workspace des Partners
        'redirect_urls' => ['https://app.acme.example/instagram/done'],  // exakt, https
        'secret_env' => 'INSTAGRAM_PARTNER_ACME_SECRET',  // Link-Secret, Wert in config/.env
        'enabled' => true,
    ],
],

Dann im Partner-Workspace:

  1. API-Key anlegen (/manage/api-keys) mit den vier Instagram-Tools.
  2. Webhook anlegen (/manage/webhooks) mit den Events instagram.connected und instagram.revoked.
  3. Link-Secret erzeugen (openssl rand -hex 32), in die Plattform-.env als INSTAGRAM_PARTNER_ACME_SECRET=… eintragen und dem Partner auf sicherem Weg geben. Ohne Secret weist TaskMonkey alle Links des Partners ab (503).
  4. Nutzer-Link: vom Partner-Server pro Nutzer signiert (ref: 1–128 Zeichen A-Z a-z 0-9 _ . : @ -), siehe unten.

Links signieren

Der Link darf nur auf dem Server des Partners entstehen (Secret nie in App oder Browser). Ohne gültige Signatur könnte jeder einen Link mit fremder ref bauen und die Instagram-Verbindung eines anderen Nutzers überschreiben.

exp = jetzt + max. 24 h (Unix-Sekunden, empfohlen: 10–30 min)
sig = hex( HMAC-SHA256( "v1\n" + partner + "\n" + ref + "\n" + exp , Link-Secret ) )

https://taskmonkey.de/connect/instagram?partner=acme&ref=user-42&exp=1767225600&sig=<64 hex>[&redirect_url=…]

PHP:

$exp = time() + 900;
$sig = hash_hmac('sha256', "v1\n{$partner}\n{$ref}\n{$exp}", getenv('TASKMONKEY_IG_LINK_SECRET'));
$url = 'https://taskmonkey.de/connect/instagram?' . http_build_query(compact('partner', 'ref', 'exp', 'sig'));

Node.js:

const exp = Math.floor(Date.now() / 1000) + 900;
const sig = crypto.createHmac('sha256', process.env.TASKMONKEY_IG_LINK_SECRET)
  .update(`v1\n${partner}\n${ref}\n${exp}`).digest('hex');

Abgewiesen (400, kein Instagram-Dialog): fehlende/falsche Signatur, andere ref als signiert, exp vorbei („Link abgelaufen“) oder mehr als 24 h in der Zukunft. redirect_url ist nicht Teil der Signatur, muss aber exakt in redirect_urls stehen. Secret-Rotation: neues Secret in .env, Partner stellt um — alte Links sind sofort ungültig.

Abruf:

curl -X POST https://app.taskmonkey.de/api/v1/tools/instagramListMedia \
  -H 'Authorization: Bearer tm_live_…' -H 'Content-Type: application/json' \
  -d '{"args":{"ref":"user-42","limit":25}}'

Isolation: Der Workspace kommt aus dem API-Key. ref wählt nur unter den Verbindungen, deren Partner laut Plattform-Config zu genau diesem Workspace gehört. Gleiche ref bei zwei Partnern = zwei getrennte Verbindungen.

Webhook-Daten (data): connection_id, partner, ref, ig_user_id, username; bei instagram.connected zusätzlich account_type, scopes, reconnected; bei instagram.revoked reason (deauthorized, data_deletion, disconnected, expired, token_invalid).

Meta-Pflicht-Callbacks

URL Methode Wirkung
/connect/instagram/deauthorize POST signed_request Nutzer hat die App in Instagram entfernt: Token löschen, Status revoked, Webhook
/connect/instagram/data-deletion POST signed_request Datenlöschung: Webhook, Verbindung löschen, Antwort {"url": …, "confirmation_code": …}
/connect/instagram/deletion-status/<code> GET Status der Löschung für den Nutzer
/connect/instagram/deauthorize, /connect/instagram/data-deletion GET/HEAD Infoseite (200): wie man die Löschung anstößt, Link zur Datenschutzerklärung. Keine Wirkung. Metas Crawler prüft die eingetragenen URLs per GET

signed_request wird per HMAC-SHA256 nur gegen INSTAGRAM_APP_SECRET geprüft (nicht gegen das Facebook-App-Secret META_APP_SECRET), dazu issued_at (Pflicht, max. 24 h alt). Ohne gültige Signatur: 403, keine Wirkung.

Einrichtung (Betreiber)

Plattform-.env (config/.env):

INSTAGRAM_APP_ID=…        # Meta-App → Instagram → API-Setup mit Instagram-Business-Login
INSTAGRAM_APP_SECRET=…

Meta-App-Review und einzutragende URLs: docs/plans/instagram-app-review.md.

Technik

Was Wo
Plattform-Config config/instagram.php
OAuth, Callbacks src/Controller/ConnectInstagramController.php, templates/ConnectInstagram/
Workspace-UI src/Controller/Manage/InstagramController.php
Lebenszyklus src/Service/Instagram/InstagramConnectionService.php (+ InstagramGraphClient, InstagramOAuthState, InstagramPartnerLink, SignedRequest)
Tool-Auth src/Tooling/Auth/InstagramConnectionAuth.php
Refresh bin/cake instagram_refresh
Tabellen instagram_connections, instagram_deletion_requests
Zuletzt aktualisiert: 2026-10-01