🏢 TikTok Developer Portal
Tudo começa em developers.tiktok.com. Crie uma conta TikTok comum primeiro (pessoal ou business), depois faça login no portal e crie um App. Não use a mesma conta que recebe posts: a conta dev é só pra gerenciar credenciais.
Cada App tem Client Key e Client Secret, e precisa declarar quais produtos usa — para postar, é o Content Posting API. Sem ele habilitado, todos os endpoints retornam scope_not_authorized.
# Checklist do portal
1. developers.tiktok.com → Login → Manage Apps
2. Create App
- Name, description, category, icon (512x512)
- URL do site (não pode ser localhost em produção)
3. Configuration
- Redirect URI: https://seu-dominio.com/oauth/tiktok/callback
- Add Products: Login Kit + Content Posting API
4. Anote Client Key + Client Secret (vai no .env)
# Scopes obrigatórios pra postar
user.info.basic
video.upload # gera o upload, fica em rascunho
video.publish # publica direto no feed (precisa de unaudited|audited)
💡 Dica prática
Use a Sandbox antes de submeter pra review. Em sandbox os endpoints funcionam só pra contas adicionadas como Target users dentro do App — perfeito pra testar fluxo OAuth + upload sem precisar de aprovação.
Conceitos-chave
Entidade que agrupa credenciais e produtos contratados.
Cada API (Login, Content Posting, Display) é ativada separadamente.
Ambiente de teste limitado a usuários-alvo do app.
Permissões pedidas no OAuth — granular por endpoint.
🛡️ App Review rigoroso
Pra sair de sandbox e atingir contas reais, você submete o App pra audit. TikTok é a plataforma mais rigorosa entre as grandes — recusas são comuns na primeira tentativa. Eles exigem vídeo demo do fluxo, política de privacidade publicada, justificativa escrita do uso de cada scope e, frequentemente, um teste interativo com revisor.
O produto Content Posting API tem dois modos: unaudited (posta como rascunho privado, abre o app pro usuário publicar) e audited (publica direto). Comece pelo unaudited — review mais leve.
📋 Checklist de submissão
- Vídeo demo (2-3 min): tela cheia mostrando login OAuth, escolha de vídeo, preview, post. Sem cortes suspeitos.
- Privacy Policy URL: precisa mencionar TikTok, dados coletados, retenção e direito de exclusão.
- Terms of Service URL: público, próprio domínio.
- Justificativa de scope: uma frase clara por scope ("video.publish para permitir agendamento automático que o usuário configura na nossa UI").
- App funcionando: URL de produção viva — bots do review acessam.
✓ Aumenta chance de aprovação
- ✓Vídeo demo nítido, com áudio explicando cada passo.
- ✓Privacy Policy específica pra integração TikTok.
- ✓Site funcional com signup público real.
- ✓Começar pelo modo
unaudited(rascunho).
✗ Recusa quase certa
- ✗Justificativas genéricas ("preciso do scope X").
- ✗Privacy Policy template copiado, sem TikTok.
- ✗App ainda em
localhostou staging quebrado. - ✗Submeter direto em
auditedsem histórico de uso.
Conceitos-chave
Revisão manual + automática antes de liberar produção.
Posta como rascunho — usuário finaliza no app TikTok.
Publica direto, sem confirmação no celular.
Prova visual de que o fluxo respeita os termos.
📤 Direct Post vs Photo Post
A Content Posting API tem dois endpoints distintos, com payloads diferentes. Escolher errado dá 400 invalid_param.
Video Post (/v2/post/publish/video/init/) recebe um único arquivo de vídeo. Photo Post (/v2/post/publish/content/init/ com media_type=PHOTO) recebe URLs públicas de imagens — vira o carrossel/photo mode.
# DIRECT POST (vídeo) — modo PULL_FROM_URL
POST https://open.tiktokapis.com/v2/post/publish/video/init/
Authorization: Bearer {access_token}
Content-Type: application/json
{
"post_info": {
"title": "Meu vídeo agendado pela API #demo",
"privacy_level": "SELF_ONLY", // ou PUBLIC_TO_EVERYONE
"disable_duet": false,
"disable_comment": false,
"disable_stitch": false,
"video_cover_timestamp_ms": 1000
},
"source_info": {
"source": "PULL_FROM_URL",
"video_url": "https://cdn.seu-app.com/video.mp4"
}
}
# PHOTO POST (carrossel) — até 35 fotos
POST https://open.tiktokapis.com/v2/post/publish/content/init/
Authorization: Bearer {access_token}
Content-Type: application/json
{
"media_type": "PHOTO",
"post_mode": "DIRECT_POST",
"post_info": {
"title": "Carrossel da semana",
"description": "Resumo visual #mkblogs",
"privacy_level": "PUBLIC_TO_EVERYONE",
"auto_add_music": true
},
"source_info": {
"source": "PULL_FROM_URL",
"photo_cover_index": 0,
"photo_images": [
"https://cdn.seu-app.com/1.jpg",
"https://cdn.seu-app.com/2.jpg",
"https://cdn.seu-app.com/3.jpg"
]
}
}
🔒 Dica prática
No modo unaudited, force privacy_level: "SELF_ONLY". Tentar PUBLIC_TO_EVERYONE sem audit retorna unaudited_client_can_only_post_to_private_accounts.
Conceitos-chave
TikTok baixa o arquivo da sua CDN (mais simples).
Você sobe o arquivo em chunks (mais controle).
Visibilidade do post — varia com audit status.
Qual foto do array vira capa do carrossel.
📦 Upload em chunks (FILE_UPLOAD)
Quando você não tem CDN pública (ou o vídeo é privado), use FILE_UPLOAD. O fluxo é três passos: init (TikTok devolve upload_url), PUT dos chunks no upload_url, e polling de status até PUBLISH_COMPLETE.
Initialize
Declare tamanho total, número de chunks e tamanho do chunk (5MB-64MB, último pode ser menor).
POST /v2/post/publish/video/init/
{
"source_info": {
"source": "FILE_UPLOAD",
"video_size": 47284736,
"chunk_size": 10000000,
"total_chunk_count": 5
}
}
# → { "upload_url": "...", "publish_id": "v_..." }
Upload dos chunks (PUT multipart)
Um PUT por chunk, com Content-Range e Content-Length corretos.
PUT {upload_url}
Content-Type: video/mp4
Content-Length: 10000000
Content-Range: bytes 0-9999999/47284736
<binary chunk>
# Repita para cada chunk, ajustando o range
Status polling
Após o último chunk, faça polling até o estado virar PUBLISH_COMPLETE ou FAILED.
POST /v2/post/publish/status/fetch/
{ "publish_id": "v_..." }
# status: PROCESSING_UPLOAD | PROCESSING_DOWNLOAD
# | PUBLISH_COMPLETE | FAILED
⚙️ Dica prática
Se o vídeo tem até 64MB, mande tudo num chunk só — simplifica drasticamente o código. Multi-chunk só se justifica acima desse tamanho. E sempre confira que o total_chunk_count × chunk_size bate (ou supera) o video_size.
Conceitos-chave
Pede upload_url e publish_id antes de mandar bytes.
Header HTTP que indica o intervalo de bytes do chunk.
ID rastreável do post até PUBLISH_COMPLETE.
Consultar status repetidamente (intervalo 5-10s).
📏 Limites e dimensões
TikTok rejeita silenciosamente vídeos que não batem com a especificação — o status fica FAILED com um motivo curto. Antes de subir, valide localmente com ffprobe.
📐 Especificação técnica
- Container: MP4, MOV, WebM (MP4 é o seguro).
- Codec: H.264 (vídeo) + AAC (áudio).
- Duração: mínimo 3s, máximo 10 minutos (contas verificadas, até 60 min).
- Tamanho do arquivo: até 4GB (mas mantenha < 500MB pra evitar timeouts).
- Aspect ratio recomendado:
9:16(vertical, 1080×1920). Outros funcionam mas perdem alcance. - Frame rate: 23-60 fps.
- Bitrate: ≥ 516 kbps; recomendado 6-10 Mbps.
- Fotos (carrossel): JPG/WebP, até 35 imagens, máx 20MB cada.
# Validar antes de submeter
ffprobe -v error -show_entries \
stream=codec_name,width,height,duration,r_frame_rate,bit_rate \
-of default=noprint_wrappers=1 video.mp4
# Converter pra spec ideal se precisar
ffmpeg -i input.mov \
-c:v libx264 -preset slow -crf 22 \
-c:a aac -b:a 192k \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" \
-movflags +faststart \
output.mp4
Conceitos-chave
9:16 vertical é o nativo do TikTok.
Move moov atom pro início — player não precisa baixar tudo.
Inspeciona container, codec e duração sem decodar.
6 posts por minuto por usuário; cobra reflow.
🤔 Quando vale a pena
Toda essa burocracia tem custo. Pergunta honesta: o seu volume justifica? Se você posta 2-3 vídeos por semana, o tempo investido em audit + manutenção da integração paga menos do que publicar manual no celular.
✓ Vale automatizar
- ✓Alto volume: 5+ posts/dia ou múltiplas contas geridas.
- ✓Pipeline de conteúdo já em vídeo 9:16 padronizado.
- ✓Equipe que aprova posts num dashboard central.
- ✓Audiência específica que justifica TikTok como canal principal.
- ✓Já tem domínio + privacy policy + site público.
✗ Deixe manual
- ✗Volume baixo (< 3/semana) — agendar no celular resolve.
- ✗Sem domínio público nem privacy policy pronta.
- ✗Conteúdo precisa de trends, sons populares, edição reativa.
- ✗TikTok é só "mais um canal" e não a praça principal.
- ✗Sem tempo pra 1-2 ciclos de revisão até aprovação.
🎯 Caminho do meio
O Postiz já tem integração TikTok pronta — basta colar Client Key + Client Secret do seu app. Faz sentido passar pelo audit (porque você precisa de credenciais reais mesmo usando Postiz), mas pula a parte de escrever o cliente HTTP. É o melhor custo-benefício pra maioria dos casos.
Conceitos-chave
Tempo de audit + dev vs. tempo de postar manual.
Ponto onde automação paga a complexidade.
Reuso de cliente já feito — só traga credenciais.
Manual ganha quando o conteúdo depende de tendências.
🎯 Resumo do Módulo
developers.tiktok.com, Content Posting API habilitada, Client Key/Secret salvos.init → PUT → status, com Content-Range correto e polling de publish_id.ffprobe e normalização com ffmpeg.🎉 Você terminou a Trilha 3 — Redes Sociais!
Agora você conhece os portais, OAuth e APIs de Instagram, X, Bluesky, LinkedIn, YouTube e TikTok. Próxima trilha: blogs — Ghost, WordPress headless, Hashnode, Dev.to e como publicar conteúdo longo de forma automatizada.