Mapa da trilha
🦋 Bluesky
Sem aprovação, login em 5 min
🐘 Mastodon
Token direto, sem OAuth
🐦 X (Twitter)
Pay-per-use, $0,01 por post
OAuth 2.0 + token de 60 dias
📷 Instagram & Threads
App Review obrigatório
🎵 TikTok
Content Posting API rigorosa
Conteúdo detalhado
🦋 Bluesky (fácil, sem aprovação)
A rede mais permissiva: protocolo aberto AT Protocol, sem App Review, sem custo. Comece por aqui.
App Password é uma senha secundária gerada em bsky.app/settings/app-passwords. Permite que seu script faça login sem expor sua senha principal e pode ser revogada a qualquer momento.
É a única forma segura de automatizar publicações. Se a chave vazar, você revoga só ela. Sua senha principal continua intacta e o 2FA permanece ativo.
Handle (ex: nome.bsky.social), App Password (formato xxxx-xxxx-xxxx-xxxx), escopo limitado a publicar/ler.
A lib oficial @atproto/api abstrai chamadas HTTP do AT Protocol. Instalar com npm install @atproto/api. Documentação em docs.bsky.app.
Você ganha tipos TypeScript, retry automático, helpers de RichText e validação de schemas Lexicon. Evita reinventar parser de respostas.
BskyAgent é a classe principal, service URL padrão https://bsky.social, suporta também outros PDS (Personal Data Servers).
Método agent.login({ identifier, password }) retorna sessão com accessJwt e refreshJwt. A sessão é guardada na instância do agent para chamadas subsequentes.
Persistir agent.session evita login a cada publicação. Em jobs longos, use resumeSession em vez de login repetidamente.
JWT expira em ~2h, refreshJwt em ~60 dias, DID (identificador único e imutável do usuário).
await agent.post({ text: 'Hello mundo' }) cria um registro do tipo app.bsky.feed.post no repositório do usuário. Limite de 300 grafemas (não bytes).
É a operação base. Retorna uri e cid que servem para responder, curtir, deletar e linkar o post.
300 grafemas máx, createdAt em ISO 8601, langs para indicar idioma, reply para threads.
Fluxo de 2 passos: agent.uploadBlob(buffer, { encoding: 'image/jpeg' }) retorna referência do blob, depois você passa em embed: { $type: 'app.bsky.embed.images', images: [{ alt, image: blobRef }] }.
Imagens drivam 3-5x mais engajamento. Sem blob, seus posts ficam só texto e perdem alcance no feed algorítmico.
Máx 1MB por imagem, até 4 imagens por post, alt text obrigatório por acessibilidade.
Classe RichText detecta menções (@user), hashtags e URLs e gera facets com índices byte-precisos. Use rt.detectFacets(agent) antes de postar.
Sem facets, o texto sai como string inerte: links não clicáveis, hashtags não buscáveis, menções não notificam. Mata o alcance.
Facets indexados em bytes UTF-8, tipos: link/mention/tag, RichText também faz truncate respeitando grafemas.
🐘 Mastodon
Federado, instalável em qualquer servidor. Token em 2 minutos, REST API padrão, sem App Review.
Mastodon é federado: cada instância (servidor) é independente. Mais populares: mastodon.social, mas.to, fosstodon.org. Sua URL base muda conforme a instância.
O endpoint da API é https://SUA-INSTANCIA/api/v1/.... Errar a instância = 404 em tudo. Posts ficam visíveis em outras instâncias pela federação ActivityPub.
Fediverso, ActivityPub, instância vs conta, regras de moderação variam.
Acesse SUA-INSTANCIA/settings/applications logado. Clique em "New application", escolha nome, scopes (read write), e a instância gera client_id, client_secret e access token.
Diferente de Twitter/LinkedIn, não precisa de OAuth dance: a UI já te entrega o access token pronto. Setup em 2 minutos.
Scopes: read, write, follow, push, admin. Acesse "Your access token" no final do formulário.
O access token criado nas applications NÃO expira até você revogar. Use no header Authorization: Bearer SEU_TOKEN em todas as chamadas.
Token longo-prazo = automação simples. Sem refresh, sem renovação, sem OAuth callback. Diferencial enorme vs LinkedIn (60 dias) ou Twitter (2h).
Bearer auth, escopo herdado da app, revogável só pelo dono via UI.
Endpoint POST https://INSTANCIA/api/v1/statuses com body { status: "texto", visibility: "public" }. Retorna o objeto Status com id, url e timestamps.
É a operação principal. Suporta 500 caracteres (vs 300 do Bluesky), Markdown limitado, hashtags, menções remotas e idempotency key.
500 chars, Idempotency-Key header evita posts duplicados em retry, scheduled_at para agendar.
Use POST /api/v2/media (preferido, assíncrono) ou /api/v1/media com multipart contendo arquivo + description (alt text). Retorna media id que você passa em media_ids[] no statuses.
Mastodon aceita imagens, vídeo, áudio e GIF. O v2 processa em background — você recebe 202 e faz poll até processing terminar.
Até 4 anexos por status, alt text obrigatório por boas práticas, focus point para crop inteligente.
Campo visibility aceita: public (timeline pública), unlisted (não aparece em discovery), private (só seguidores) e direct (mensagem). Campo spoiler_text cria content warning.
A cultura Mastodon exige CW em política, NSFW e spoilers. Posts sem CW apropriado são silenciados/reportados. Use unlisted para reposts automatizados.
CW = spoiler_text, sensitive=true marca mídia, visibility define federação.
🐦 X (Twitter API v2)
Pay-per-use a partir de $0,01 por post. OAuth 2.0 + lib twitter-api-v2. Upload de mídia ainda usa v1.1.
Portal oficial em developer.x.com/portal/dashboard. Crie Project + App. Project agrupa apps por caso de uso; App contém as credenciais.
Sem Project, não há acesso à API v2. Use case description é avaliado: descreva claramente publicação automatizada de conteúdo próprio.
Project > App, Bearer Token (app-only), API Key/Secret (consumer), Access Token (user context).
Free tier: 500 posts/mês via API. Basic: $200/mês, 3.000 posts. Pro: $5.000/mês, 1M posts. Acima disso entra pay-per-use a partir de $0,01/post conforme volume.
É a rede mais cara do estudo. Calcule volume antes: 100 posts/dia = 3.000/mês = plano Basic obrigatório. Para teste pessoal o Free basta.
Rate limits separados por tier, leitura também consome quota, free tier permite só write/read básico.
Configure app com User authentication settings: tipo "Web App", scopes tweet.read tweet.write users.read offline.access, callback URL. Use OAuth 2.0 + PKCE para obter user access token.
Para postar em nome do usuário, OAuth 2.0 com PKCE é o caminho moderno. O scope offline.access dá refresh token (essencial pra automação).
PKCE = code_verifier + code_challenge, refresh token rotativo, access token expira em 2h.
Lib twitter-api-v2 (npm) é a referência da comunidade: cobre v2 e v1.1, OAuth 1.0a/2.0, streams, retry, tipagem TypeScript. Use new TwitterApi(token).v2.tweet({ text }).
Implementar OAuth 2.0 PKCE + media upload chunked do zero é trabalhoso. A lib resolve refresh automático, paginação e tipos.
Cliente .v2 e .v1, readWrite vs readOnly, helpers de paginação, plugin de cache opcional.
Upload de mídia em X ainda vive em upload.twitter.com/1.1/media/upload.json (v1.1). Fluxo INIT > APPEND (chunks) > FINALIZE > STATUS. Pegue o media_id_string e passe em media.media_ids ao criar o tweet v2.
É a única pegadinha grande: a API "v2" não faz upload. A lib twitter-api-v2 abstrai com v1.uploadMedia(buffer), mas saber do dual-API evita confusão.
Chunks de até 5MB, vídeo: media_category=tweet_video, alt text via metadata/create.
Para criar thread, publique o primeiro tweet, pegue o id retornado, e crie o próximo passando reply: { in_reply_to_tweet_id }. A lib oferece v2.tweetThread([...]) que automatiza isso.
Threads driblam o limite de 280 caracteres e funcionam como blog post curto. Conteúdo educativo viraliza muito mais em thread do que tweet único com link.
280 caracteres (4.000 no Premium), use conversation_id para buscar a thread inteira, retry com idempotency.
Developer App + produto "Share on LinkedIn" + OAuth 2.0. Token de 60 dias com refresh. Tom corporativo, alcance B2B alto.
Crie app em linkedin.com/developers/apps. Exige Company Page como "verified company": associe a app a uma página de empresa (pode ser pessoal/teste). Sem isso, alguns produtos ficam bloqueados.
A vinculação a Company Page é o ponto de fricção. Crie uma página minimal de "estudos" se não tiver empresa real. Sem página verified = sem produtos avançados.
Client ID, Client Secret, Authorized redirect URLs, Company Page admin role.
Na aba "Products" da sua app, solicite Share on LinkedIn e Sign In with LinkedIn using OpenID Connect. Ambos são self-serve — aprovados instantaneamente. Posts em página de empresa exigem Marketing Developer Platform (esse precisa review).
Share on LinkedIn = postar no perfil pessoal sem review. Cobre 90% dos casos de uso de creator. Marketing Developer Platform é só se você precisa postar em company pages de terceiros.
Self-serve products vs reviewed products, OIDC para login, escopo herdado dos products habilitados.
Scope w_member_social autoriza publicar posts em nome do usuário. r_liteprofile e r_emailaddress (ou openid profile email via OIDC) dão dados do perfil para identificar o autor.
Sem w_member_social, qualquer POST em /ugcPosts ou /rest/posts retorna 403. Outros scopes (w_organization_social) exigem Marketing Developer Platform.
Escopos separados por espaço na URL de autorização, w_member_social = write como membro.
Authorization Code flow: redireciona o usuário para linkedin.com/oauth/v2/authorization com client_id, redirect_uri, scope e state. Após consentimento, troca o code em linkedin.com/oauth/v2/accessToken por access_token.
Não suporta PKCE (ao contrário de X). Use state para evitar CSRF. Não há grant client_credentials para postar em nome de usuário — sempre user context.
state param (CSRF), redirect_uri precisa estar exatamente igual ao cadastrado, code expira em 30s.
Fluxo: POST /rest/images?action=initializeUpload retorna uploadUrl + image URN, depois PUT binário direto no uploadUrl. Use o URN em content.media.id ao criar post em /rest/posts. Header obrigatório: LinkedIn-Version: 202401.
Endpoint antigo /v2/assets está deprecado. A API "Versioned" (/rest) é o presente. Imagens dobram engajamento no feed.
URN no formato urn:li:image:XXX, header LinkedIn-Version, owner URN do autor.
Access token dura 60 dias, refresh token 365 dias (somente para apps com produto "Sign In with LinkedIn using OpenID Connect" + Marketing Developer Platform). Para Share on LinkedIn padrão, NÃO há refresh — usuário reautoriza a cada 60 dias.
Surpresa frequente: você assume que refresh sempre existe e descobre depois que precisa pedir Marketing Developer Platform. Planeje notificação antes do 55º dia.
grant_type=refresh_token, fallback: re-OAuth via email automático ao usuário.
📷 Instagram & Threads (Meta)
A mais burocrática: conta Business obrigatória, App Review da Meta, fluxo de 2 passos (container + publish). Threads usa mesmo ecossistema.
Instagram Graph API só funciona com contas Business ou Creator vinculadas a uma Facebook Page. Converta a conta em Configurações > Conta > Mudar para conta profissional e vincule à página do Facebook.
É o primeiro bloqueio. Conta pessoal = 0% de acesso à API. Vinculação à Facebook Page também é obrigatória — não basta ser Business.
Instagram Business Account (IGBA), Facebook Page ID, vinculação via Meta Business Suite.
Crie app no developers.facebook.com/apps, tipo "Business". Em Development Mode, só usuários de teste (admin/dev da app) podem usar. Para liberar ao público, submeta App Review com vídeo demonstrando uso de cada permissão.
Para uso pessoal (sua própria conta), Development Mode basta — não precisa review. Review só é necessária se outros usuários vão autorizar o app.
App Mode: Development vs Live, Roles: Admin/Developer/Tester, App Review com vídeo de até 90s.
Para Instagram: instagram_content_publish + instagram_basic + pages_show_list + pages_read_engagement. Para Facebook Pages: pages_manage_posts. Threads tem escopos próprios: threads_basic + threads_content_publish.
Esquecer um único escopo = endpoint retorna 200 mas sem dados. Cada permissão sensível precisa justificativa específica no App Review.
Advanced Access vs Standard Access, Business Verification obrigatória para algumas permissões.
Passo 1: POST /{ig-user-id}/media com image_url + caption — retorna container_id. Passo 2: POST /{ig-user-id}/media_publish com creation_id=container_id. Imagem precisa estar publicamente acessível via HTTPS (não aceita upload direto).
É o fluxo mais incomum entre todas as APIs. A exigência de URL pública força você a ter storage (S3/Cloudinary). Tente publicar imediatamente: containers expiram em 24h.
Status do container: IN_PROGRESS/FINISHED/ERROR, poll antes do publish para vídeos/Reels.
Threads usa o mesmo Meta Developer Portal. Endpoints em graph.threads.net/v1.0/{threads-user-id}/threads. Mesmo fluxo container + publish do Instagram. Auth próprio em threads.net/oauth/authorize.
Bônus enorme: se você já passou pelo App Review do Instagram, adicionar Threads é incremental. 500 caracteres por thread, suporta media e replies.
media_type: TEXT/IMAGE/VIDEO/CAROUSEL, reply_to_id para threads, link_attachment para preview de URLs.
O vídeo de App Review (60-90s) deve mostrar: login do usuário, tela de consentimento mostrando cada permissão sendo pedida, ação real usando cada permissão, resultado visível. Sem cortes editoriais. Plataforma de teste idêntica à produção.
Review típico leva 5-15 dias. Vídeo ruim = rejeitado e fila reinicia. Justifique cada permissão em 1 frase técnica (não marketing) descrevendo o use case exato.
Business Verification antes de submeter, política de Data Use, screencast com narração simples.
🎵 TikTok Content Posting API
App Review rigorosíssimo, upload em chunks, restrições de dimensão e duração. Quando vale o esforço.
Acesse developers.tiktok.com, crie organização e app. Habilite o produto Content Posting API e configure OAuth 2.0 com scopes video.upload e/ou video.publish.
Diferente da Meta, TikTok exige Organization (pessoa jurídica). Para teste, usuários de Sandbox são limitados a usuários de teste registrados na app.
Sandbox vs Production, scopes separados para upload (rascunho) e publish (publicado).
TikTok exige privacy policy hospedada, termos de uso, URL de produção funcionando, demo vídeo, e justificativa detalhada de cada scope. Review pode levar semanas e rejeições por detalhes mínimos são comuns.
É a API mais difícil de habilitar do estudo. Mesmo apps pequenas são escrutinadas. Tenha tudo polido antes de submeter.
Domain verification, Privacy Policy URL obrigatório, Demo video usando produção real.
Vídeo: POST /v2/post/publish/video/init/ seguido de upload chunked. Foto/carrossel: POST /v2/post/publish/content/init/ com post_mode: DIRECT_POST ou MEDIA_UPLOAD (rascunho aberto no app).
DIRECT_POST publica imediatamente (exige video.publish); MEDIA_UPLOAD só cria rascunho que o usuário finaliza no app (mais fácil de aprovar no review).
publish_id, status polling em /v2/post/publish/status/fetch/, post_info: title, privacy_level, disable_comment.
Após init, recebe upload_url. Faça PUTs em chunks (mínimo 5MB, máximo 64MB cada exceto o último) com header Content-Range: bytes start-end/total. Última PUT marca o upload como completo.
Vídeos grandes (>500MB) exigem chunking. Falhar em um chunk não invalida os anteriores — reenvie só o que falhou. URL de upload expira em ~1h.
chunk_size, total_chunk_count, Content-Type: video/mp4, resumable upload.
Vídeo: MP4/MOV/WEBM, até 4GB, duração de 3s a 10 min (varia por conta). Aspecto recomendado 9:16 (1080x1920). Resoluções suportadas: 360p a 1080p. Foto: JPG/WEBP, máx 20MB, máx 35 fotos no carrossel.
Subir vídeo 16:9 = letterbox feio = poucas views. Pre-processar com FFmpeg para 1080x1920 é praticamente obrigatório. Conta nova tem limite menor de duração.
9:16 ratio, H.264 + AAC, frame rate 23-60fps, bitrate recomendado 8-10Mbps.
TikTok recompensa quem usa o app nativo (edição, sons, efeitos). Postar via API geralmente performa pior algoritmicamente. A integração faz sentido para: cross-posting de vídeos pré-editados, agendamento e empresas com volume.
Saber QUANDO não automatizar é tão importante quanto saber automatizar. Para creators solo, usar o app + agendamento nativo do TikTok pode ser mais eficiente que a API.
Algoritmo prioriza posts nativos, MEDIA_UPLOAD (draft) como meio-termo, ROI vs esforço de App Review.