Como evitar post duplicado ao republicar
Como evitar que uma nova tentativa depois de um erro publique o mesmo conteúdo duas vezes.
A sua requisição de criar um post expira depois de 10 segundos sem resposta. Você não sabe se o PostGate recebeu e está processando, ou se a conexão caiu antes de chegar. A reação natural é tentar de novo — e é exatamente aí que uma integração sem cuidado publica o mesmo anúncio de lançamento duas vezes no Instagram e no LinkedIn de um cliente. Um timeout do lado do cliente nunca significa que a requisição falhou; significa só que você parou de esperar por uma resposta.
Por que a duplicação acontece
A maioria das APIs trata uma escrita retentada como um incômodo pequeno — uma linha extra no banco, limpa depois. Uma API de publicação é diferente: um POST /api/posts retentado depois de uma conexão que caiu pode significar que o mesmo anúncio de lançamento sai duas vezes nas redes sociais reais de um cliente. Isso não é um bug exótico — é o comportamento padrão de qualquer cliente HTTP que trata "não recebi resposta" como "não aconteceu nada" e refaz a mesma chamada do zero.
O mesmo problema aparece em qualquer lógica de retry automática: uma fila de jobs que reprocessa uma mensagem porque o worker não confirmou a tempo, um webhook de terceiro que reenvia o mesmo evento, ou um usuário que clica duas vezes num botão de "publicar" porque a interface não desabilitou o botão depois do primeiro clique.
A correção: uma chave de idempotência estável
Envie o cabeçalho Idempotency-Key em toda chamada de criação de post. Se o PostGate já aceitou uma requisição com aquela chave, ele retorna a resposta original em vez de criar um segundo post — mesmo que a sua chamada original tenha realmente sido processada e você só não tenha visto a resposta a tempo.
curl -X POST "https://api.postgate.studio/api/posts?profile_group_id=grp_acme123" \
-H "Authorization: Bearer $POSTGATE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: lancamento-post-001" \
-d '{
"post": { "body": "Dia de lançamento. 🚀" },
"profiles": ["pro_instagram123", "pro_linkedin456"],
"media": ["https://cdn.exemplo.com/lancamento.jpg"]
}'Gere chaves a partir da sua própria requisição, não a cada tentativa
Uma boa chave é estável para uma publicação lógica e diferente para cada publicação distinta — tipicamente derivada do seu próprio job interno, mensagem de fila ou ID de comando idempotente, como lancamento-post-{id_do_job_interno}. Gerar um UUID aleatório novo a cada retentativa anula o propósito inteiro: o PostGate veria cada tentativa como uma requisição totalmente nova e poderia publicar mais de uma vez — exatamente o problema que a chave existe para evitar.
Um erro comum é gerar a chave dentro da função que faz a chamada HTTP, em vez de no ponto de origem da intenção de publicar. Se a chave nasce junto com a tentativa de rede, ela muda a cada retentativa e vira só um UUID aleatório disfarçado de chave de idempotência.
Janela de retenção e reuso conflitante
O PostGate honra uma chave por 72 horas depois do primeiro uso. Retentar a mesma requisição idêntica dentro dessa janela retorna o post original sem alteração. Reusar a mesma chave com conteúdo diferente — um texto, perfis ou mídia diferentes — é rejeitado com um 409 conflict em vez de aplicar silenciosamente o novo conteúdo, de forma que uma colisão de chave nunca pode sobrescrever o que um cliente já viu publicado.
{
"error": {
"code": "conflict",
"message": "This idempotency key was already used with a different request.",
"retryable": false,
"request_id": "req_01JXYZ"
}
}Duplicação não é só sobre a chamada de criação
A chave de idempotência protege o momento da criação, mas a mesma disciplina precisa se estender ao resto do ciclo de vida. Ler o status por targets antes de decidir reenviar algo evita republicar um destino que na verdade já foi entregue com sucesso — um post pode estar partial, com alguns alvos published e outros failed, e a resposta correta é atuar só nos alvos que falharam, preservando os permalinks dos que já foram ao ar.
Combinada com uma Idempotency-Key estável na chamada de criação original e com um consumidor de webhook que deduplica pelo id do evento, essa disciplina torna o ciclo de vida inteiro seguro de raciocinar: você sabe exatamente o que foi aceito, exatamente o que aconteceu por destino, e nunca precisa adivinhar se uma retentativa vai publicar de novo um alvo que já teve sucesso.
