O trabalho cabe em uma frase: publicar no Instagram dentro de um calendário, a partir do seu próprio código, sem ninguém abrir o aplicativo.
Quase tudo o que se escreve sobre como automatizar publicações no Instagram responde a outra pergunta. Responde a “qual calendário eu deveria pagar”. Esta é a outra resposta, a de quem já decidiu construir, sobre a Graph API da Meta diretamente ou sobre uma API de publicação unificada. A construção tem três partes, e só uma é a que os produtos mostram na demo. Todos os dados da Meta abaixo foram lidos na documentação dela em 14 de setembro de 2026, e as páginas estão no fim.
Uma API no lugar do encanamento da Graph API. A InvisibleAPI é uma única API baseada em jobs para Instagram e X. Conecte a conta, crie um job de publicação e consulte-o até chegar a published.
Obter chave de APIO que automatizar publicações no Instagram significa de verdade
Tire as ferramentas e um publicador automático são três coisas.
| Parte | O que guarda | Quanto custa |
|---|---|---|
| A fila | O que publicar, onde e quando | Fácil. É uma tabela. |
| O despachante | O laço que transforma uma linha vencida em uma publicação | Fácil de começar, e a parte que decide se isso sobrevive um mês |
| A política de falhas | O que acontece quando a publicação não chega | O trabalho inteiro |
A automação de publicações no Instagram é vendida pela primeira parte porque a primeira parte é a que aparece bem numa demo. Um calendário com arrastar e soltar é uma fila com uma pessoa dentro. Tire a pessoa e a fila não muda nada, mas as outras duas partes passam a importar, porque não há mais ninguém olhando para notar que a publicação de terça nunca saiu.
Então a construção abaixo gasta quatro linhas com a fila e o resto com o que acontece depois do despacho.
A fila é um arquivo, não um banco de dados
Comece pela menor coisa que funciona. Um CSV, versionado no repositório ou guardado em armazenamento de objetos, com cinco colunas:
row_id |
account |
media_url |
caption |
publish_at |
|---|---|---|---|---|
2026-09-15-launch |
@yourbrand |
https://cdn.example.com/launch.jpg |
Novo lançamento disponível. | 2026-09-15T09:00:00Z |
2026-09-16-behind |
@yourbrand |
https://cdn.example.com/studio.jpg |
Bastidores da sessão. | 2026-09-16T09:00:00Z |
Duas coisas dessa tabela sustentam todo o resto.
A media é uma URL, não um arquivo. Não há etapa de upload aqui, porque a media é entregue como uma URL publicamente acessível. Um link para um bucket privado é o motivo mais comum de a primeira publicação automática falhar, e nenhuma nova tentativa transforma um objeto privado em público.
row_id não é decoração. Ele vira a chave de idempotência na chamada de criação, que é o que impede um cron caído de publicar duas vezes na execução seguinte. Escolha agora algo estável e legível e a seção de novas tentativas mais abaixo não vai custar nada.
Se você prefere partir de uma receita em vez de uma folha em branco, um calendário de publicação do Instagram com aprovação é a mesma forma com uma etapa de revisão na frente.
Uma linha, um job de publicação
A preparação são dois passos: conecte uma conta profissional do Instagram e crie uma API key de organização com os scopes publishing:read e publishing:publish. O guia de início rápido percorre os dois.
Depois, uma linha vira um job de publicação:
curl -X POST "https://api.invisibleapi.ai/api/v1/organizations/$ORGANIZATION/publishing/jobs" \
-H "Authorization: Bearer $INVISIBLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targets": ["acct_ig_01"],
"caption": "New drop, live now.",
"mediaItems": [{ "mediaType": "image", "sourceUrl": "https://cdn.example.com/launch.jpg" }],
"requestedPublishAt": "2026-09-15T09:00:00Z",
"clientRequestId": "2026-09-15-launch"
}'
A resposta é um job, não uma publicação:
{
"id": "job_01K2M4P7",
"status": "scheduled",
"clientRequestId": "2026-09-15-launch",
"requestedPublishAt": "2026-09-15T09:00:00Z"
}
Essa é a parte que a maioria dos tutoriais de automação erra. A publicação é assíncrona. Você cria um job, a sequência de publicação de várias etapas da plataforma roda por trás, e você consulta até o status chegar em published. Um tutorial que mostra uma chamada de criação devolvendo a URL de uma publicação ao vivo está descrevendo algo que não acontece, e um despachante escrito sobre essa suposição reporta sucesso para publicações que depois falharam.
Sobre os nomes dos campos. O formato do pedido está confirmado na referência da API: targets, mediaItems com o seu mediaType e sourceUrl, caption, requestedPublishAt e clientRequestId, e a chamada de criação a devolver 202. O que continua por confirmar é a resposta do trabalho: o nome do array deliveries e o campo failureCategory. Verifique-os na referência da API antes de publicar código que os leia.
A API do Instagram não agenda, então você agenda
Este é o dado sobre o qual os produtos de calendário são construídos, dito pela Meta: a API de publicação de conteúdo do Instagram “does not natively support scheduling”, não oferece agendamento de forma nativa. Essa única frase explica por que existe um mercado de agendadores de Instagram.
O agendamento é, portanto, algo que uma camada de publicação assume, e será o seu cron segurando linhas até a hora ou um campo requestedPublishAt carregando essa responsabilidade por você. Na construção acima é o segundo caso, o que significa que o despachante pode empurrar a semana inteira na segunda e parar de pensar nisso. Um job que ainda não foi despachado ainda pode ser cancelado.
De qualquer forma, conheça os estados que o seu laço lê. Um job passa por pending, scheduled, processing, preparing, submitted e polling, e depois chega a um destes: published, partial_failure, failed, action_required ou canceled. Cinco finais, não um, e a diferença entre três deles é todo o assunto da política de falhas.
Verifique os limites antes de despachar
Um despachante que descobre uma cota batendo nela já perdeu as publicações que estava segurando. Há dois tetos, e não são o mesmo teto.
O da Meta. A documentação de publicação de conteúdo indica 100 publicações por API dentro de um período móvel de 24 horas, e um carrossel conta como uma só. O número antigo de 25 publicações por dia ainda circula muito em textos de terceiros e não é o que a documentação diz hoje, então planeje contra 100 e confirme o número você mesmo antes de construir em cima dele.
O seu. Publicando pela InvisibleAPI, cada conta conectada pode publicar 100 posts por período de faturamento, e um endpoint de limites reporta o uso ao vivo para que o despachante leia o saldo restante antes de começar um lote.
O comportamento útil não é parar diante de uma fila cheia. É publicar o que cabe e reagendar o resto depois da renovação, o que transforma um lote de falhas em um lote que chega um dia depois. Uma proteção de limites de publicação é essa lógica como receita, e quanto custa publicar no Instagram cobre a pergunta mais ampla de contra o que o volume é contado.
O que dá errado, e o que o código faz a respeito
Cada falha que o seu despachante vê se resolve em uma de quatro decisões, e cada uma tem um dono diferente.
invalid_publish_data é o seu bug. O caption era longo demais, a proporção estava fora da faixa, o carrossel tinha itens demais. O mesmo payload vai falhar igual para sempre, então uma nova tentativa é cota jogada fora. Corrija a linha e crie um job novo.
retryable_provider_failure é a plataforma tendo um mau momento. Media ainda processando, um contêiner expirado, um erro de servidor. É repetido automaticamente, e o trabalho do seu laço é continuar esperando em vez de escalar.
provider_action_required é o problema de uma pessoa, normalmente uma concessão de credenciais expirada. Nenhum laço de novas tentativas consegue fazer login por alguém. Mostre e pare.
platform_software_failure é nosso. Vai para o suporte técnico, e o seu despachante não faz nada além de não repetir.
Por isso o switch abaixo se apoia na categoria e não em um código de erro do provedor. Códigos são adicionados e reclassificados; uma classificação de quatro valores não.
const TERMINAL = ["published", "partial_failure", "failed", "action_required", "canceled"];
const NOTIFY = {
invalid_publish_data: "developer",
retryable_provider_failure: null,
provider_action_required: "account_owner",
platform_software_failure: "support",
} as const;
export async function dispatch(row: QueueRow) {
const job = await createJob(row); // clientRequestId = row.row_id
const final = await pollUntil(job.id, (j) => TERMINAL.includes(j.status));
if (final.status === "published") return { row: row.row_id, ok: true };
return final.deliveries.map((d) => ({
target: d.target,
retry: d.failureCategory === "retryable_provider_failure",
notify: NOTIFY[d.failureCategory],
}));
}
Repare que o valor devolvido é por delivery, não por job. Um job pode mirar várias contas conectadas de uma vez, e o mesmo conteúdo pode funcionar em uma e falhar em outra. Um caption de 500 caracteres publica no Instagram e falha na regra de 280 caracteres do X dentro do mesmo job, que é exatamente o que partial_failure descreve. (Se o X está na sua lista, quanto custa publicar no X cobre a tabela dele.) Leia as deliveries e o relatório diz qual conta publicou e qual não. Leia só o status do job e sobra um ponto vermelho.
Essa distribuição é a versão de agência desta construção, coberta por publicar uma vez em várias contas conectadas, e a metade de varrer as falhas é a receita de recuperação de publicações que falharam.
O que uma nova tentativa nunca pode fazer
Este é o cenário que quebra em silêncio os publicadores sem supervisão. Seu despachante envia a chamada de criação. A conexão estoura o tempo limite. Você não tem resposta, e não há como distinguir uma requisição que falhou de uma que funcionou e perdeu a resposta no caminho.
Se repetir, pode publicar duas vezes. Se pular, pode perder a publicação em silêncio. Um cron que roda a cada cinco minutos vai encontrar esse caso, e vai encontrar às 3 da manhã.
Uma chave de idempotência elimina a escolha. O clientRequestId da chamada de criação é essa chave, e uma requisição repetida com o mesmo valor não publica duas vezes. Por isso a regra é estreita e absoluta: uma nova tentativa reutiliza a chave original. Ela nunca cria uma nova. Gerar um id novo dentro do ramo de repetição é a forma mais comum de um script de aparência correta produzir publicações duplicadas, porque desliga o mecanismo de segurança exatamente quando ele era necessário.
É também por isso que row_id veio do arquivo da fila e não do despachante. A chave pertence à linha, não à tentativa.
A automação pela qual contas do Instagram são restringidas
Procure automação de Instagram e boa parte do que volta é outra categoria de produto: ferramentas que mandam mensagens diretas automáticas para novos seguidores, curtem por hashtag, seguem e deixam de seguir, e bibliotecas que chegam ao Instagram fazendo login com usuário e senha em vez da API documentada. Vale ser preciso sobre por que esse caminho é um risco diferente, porque a distinção está publicada e não é questão de opinião.
Os Termos de Plataforma da Meta, seção 6.a.iii, dizem que um aplicativo “must not separately request or collect a Meta user’s login credentials for any Meta Products”, não deve solicitar nem coletar separadamente as credenciais de acesso de um usuário da Meta. Uma biblioteca que faz login como o usuário faz exatamente isso por desenho: é o mecanismo, não um caso extremo. A seção 2.a é mais ampla, e diz que, salvo licença expressa, “you will not use, access, integrate with, modify, translate, create derivative works of, reverse engineer, or otherwise exploit Platform or any aspect thereof”. Um endpoint não documentado alcançado por engenharia reversa do aplicativo móvel não está licenciado expressamente.
A automação de interações fica sob as Políticas para Desenvolvedores. A seção 2 proíbe participar de “any program that promotes or facilitates the purchase, sale, or exchange of ‘Likes’, ‘Shares’, ‘Followers’, ‘Comments’”, e a seção 5 descreve “creating bots either manually or automatically, at very high frequencies” como spam.
A aplicação das regras também não é teórica. A própria referência de erros do Instagram da Meta traz códigos para uma conta restringida e para atividade restringida por suspeita de spam na publicação. Eles existem porque há contas que chegam nesse estado.
Nada disso se aplica à construção deste artigo. A API de publicação de conteúdo é o caminho documentado, a conta autoriza pelo próprio fluxo OAuth do Instagram, nenhuma senha chega ao seu código, e o limite de uso é um número publicado que você pode consultar antes de despachar. Essa é a razão honesta para seguir o caminho oficial, e ela se sustenta melhor do que qualquer comparação de funcionalidades.
Publique o laço, não mais um calendário
Sua fila, seu calendário, seu código, e um job de publicação por linha que diz exatamente o que aconteceu com cada uma.
Conecte uma conta profissional do Instagram, crie uma API key com scopes e passe a primeira linha. Cada conta começa com um teste gratuito de 7 dias, e como funciona o preço por volume explica contra o que o uso é contado.
Publique no X e no Instagram a partir de uma única API.
Conecte as contas uma vez, crie um job de publicação e consulte-o até ele ser publicado. A validação prévia detecta uma publicação inválida antes de ela chegar à plataforma, e um clientRequestId torna as tentativas seguras.
Fontes
As três páginas foram consultadas em 14 de setembro de 2026.
- Guia de publicação de conteúdo do Instagram, para o limite de 100 publicações por período móvel de 24 horas, o carrossel contando como uma e a ausência de agendamento nativo
- Termos de Plataforma da Meta, para as seções 2.a e 6.a.iii
- Políticas para Desenvolvedores da Meta, para as seções 2 e 5