🌍 Escolher a instância
Mastodon não é um site único — é uma rede federada. Cada servidor (instância) tem suas próprias regras, comunidade e moderação, mas todos conversam entre si via ActivityPub. Seu identificador será @usuario@instancia.tld, como um e-mail.
A escolha da instância importa: ela define seu domínio público, suas regras de moderação e a estabilidade do seu acesso. Para começar, fique numa instância pública grande e bem-administrada — depois pode migrar (o Mastodon suporta export/import de quem você segue).
# Instâncias públicas populares e estáveis
mastodon.social # oficial, mantida pela equipe Mastodon gGmbH
fosstodon.org # foco em software livre e tech
mas.to # generalista, registro aberto
hachyderm.io # tech/SRE/devops, moderação rígida
techhub.social # tech/dev, instância PT-BR amigável
# Inspecionar metadados de uma instância antes de entrar
curl https://mastodon.social/api/v2/instance | jq '.title, .description, .languages'
💡 Dica prática
Se você quer controle total e custo zero a longo prazo, considere self-host com docker-compose. Mas comece numa instância pública — operar Mastodon em produção exige Redis, Postgres, ElasticSearch e cuidado com moderação federada.
Conceitos-chave
Rede de servidores que falam ActivityPub entre si.
Servidor Mastodon com regras e comunidade próprias.
Formato @user@host identifica globalmente.
Você leva seguidores e listas ao mudar de instância.
⚙️ Criar app em /settings/applications
O Mastodon expõe uma API REST direta e — diferente do Twitter/X — você cria seu próprio app pela UI, sem fila de aprovação. Vá em Settings → Development → New application, dê um nome, marque os scopes que precisa e salve.
Para um bot/integração que só posta, o scope mínimo é write:statuses (e write:media se for anexar imagens). Evite marcar read ou admin se não precisar — princípio do menor privilégio.
# Alternativa via API (sem UI) — registra app programaticamente
curl -X POST https://mastodon.social/api/v1/apps \
-F 'client_name=meu-bot' \
-F 'redirect_uris=urn:ietf:wg:oauth:2.0:oob' \
-F 'scopes=write:statuses write:media' \
-F 'website=https://exemplo.com'
# Resposta JSON
# {
# "id": "1234567",
# "name": "meu-bot",
# "client_id": "AbCdEf...",
# "client_secret": "XyZ123..."
# }
🔒 Dica prática
Escopos do Mastodon são hierárquicos: write implica write:statuses, write:media, etc. Sempre prefira o mais granular possível — se vazar o token, o estrago é menor.
Conceitos-chave
Identidade do cliente que fala com a API.
Permissões: read, write, follow, push.
oob = out-of-band, sem callback web.
Marque só os scopes que o app realmente usa.
🔑 Token de app e Bearer auth
Após criar o app, o Mastodon gera um access token pessoal logo abaixo do client_id/client_secret. Esse token autentica como você dentro dos scopes marcados — basta copiar e usar como Authorization: Bearer ....
Para OAuth completo (terceiros logando no seu app) o fluxo é diferente, mas para um bot pessoal esse token estático resolve. Guarde-o em variável de ambiente — nunca em código versionado.
# Exportar token e instância como env vars
export MASTODON_HOST="https://mastodon.social"
export MASTODON_TOKEN="abc123def456...seu_token_aqui"
# Validar token — retorna seu perfil
curl -H "Authorization: Bearer $MASTODON_TOKEN" \
"$MASTODON_HOST/api/v1/accounts/verify_credentials"
# Resposta JSON
# {
# "id": "108123",
# "username": "neimaldaner",
# "acct": "neimaldaner",
# "display_name": "Nei",
# ...
# }
✓ O que FAZER
- ✓Guardar token em
.envfora do git. - ✓Testar com
verify_credentialsantes de publicar. - ✓Revogar e recriar o app se o token vazar.
- ✓Usar um token por integração — facilita auditoria.
✗ O que NÃO fazer
- ✗Colar o token num gist público para "debugar rápido".
- ✗Reaproveitar o mesmo token em N bots diferentes.
- ✗Mandar o token como
?access_token=na URL (vai pro log). - ✗Dar scope
admin:*para um bot que só posta.
Conceitos-chave
Credencial estática emitida pelo Mastodon.
Header Authorization: Bearer <token>.
Endpoint canônico para validar token.
Apagar o app na UI invalida o token na hora.
📝 POST /api/v1/statuses
O endpoint para publicar um toot (status) é POST /api/v1/statuses. O único campo obrigatório é status (texto, até 500 caracteres na maioria das instâncias). Os demais são opcionais: visibility, sensitive, spoiler_text, language, scheduled_at.
# Post simples
curl -X POST "$MASTODON_HOST/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "Olá Fediverso! 🐘 Postando via API.",
"visibility": "public",
"language": "pt"
}'
# Resposta — status criado
# {
# "id": "111234567890123456",
# "created_at": "2026-05-24T14:30:00.000Z",
# "url": "https://mastodon.social/@user/111234567890123456",
# "content": "<p>Olá Fediverso! 🐘 ...</p>",
# "visibility": "public",
# ...
# }
Para evitar duplicatas em retentativas, envie o header Idempotency-Key com um UUID. Se a mesma key chegar duas vezes em poucos minutos, o Mastodon retorna o status já criado em vez de duplicar.
# Post com idempotência (seguro para retry)
curl -X POST "$MASTODON_HOST/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"status":"Mesma chave = mesmo post","visibility":"unlisted"}'
⚡ Dica prática
Mastodon aceita scheduled_at em ISO-8601 para agendar nativamente (mínimo 5 minutos no futuro). Útil se você não tem orquestrador próprio — mas o Postiz já cuida disso e te dá controle melhor.
Conceitos-chave
Texto do toot — limite varia por instância.
ISO 639-1 (ex: pt) ajuda timeline locais.
UUID que previne duplicação em retry.
Agendamento nativo (mín. 5 min no futuro).
🖼️ Upload de mídia em /api/v2/media
Anexar imagem/vídeo é um processo de dois passos: primeiro faz upload no endpoint de mídia (retorna um id), depois inclui esse id no array media_ids[] ao criar o status. A v2 é assíncrona — aceita o arquivo e retorna 202 enquanto processa.
Upload do arquivo (multipart)
Sempre inclua description — é o alt-text de acessibilidade, obrigatório por convenção da comunidade.
curl -X POST "$MASTODON_HOST/api/v2/media" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-F "file=@foto.jpg" \
-F "description=Pôr do sol em Florianópolis com nuvens rosadas"
# Retorna o id (processamento assíncrono)
# { "id": "22348675309", "type": "image", "url": null, ... }
Anexar ao status
Use o id retornado em media_ids[]. Mastodon suporta até 4 imagens ou 1 vídeo por toot.
curl -X POST "$MASTODON_HOST/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "Foto de hoje 🌅",
"media_ids": ["22348675309"],
"visibility": "public"
}'
♿ Dica prática
A cultura do Mastodon valoriza muito alt-text. Postar mídia sem description gera reações negativas e reduz alcance — bots de "CaptionBot" cobram publicamente. Sempre descreva.
Conceitos-chave
Encoding para enviar binários via HTTP.
Processamento em background — pollar /media/:id.
Campo description = acessibilidade.
4 imagens OU 1 vídeo/GIF por status.
👁️ Visibility e content warnings
Mastodon tem quatro níveis de visibilidade por post — escolhidos individualmente, não como configuração da conta. Combine com sensitive: true + spoiler_text para Content Warnings (CW), uma convenção forte na cultura local.
📊 Os quatro níveis de visibility
- public: aparece em timelines federadas, locais e públicas. Indexável. Use para conteúdo que quer alcance máximo.
- unlisted: visível para quem te segue e para quem abre o link, mas não aparece nas timelines públicas. Bom para threads longas.
- private (followers-only): só seus seguidores veem. Não pode ser boostado por terceiros.
- direct: mensagem direta — só vê quem você mencionar com
@. Não é criptografada; use com cuidado.
# Toot com Content Warning + visibility unlisted
curl -X POST "$MASTODON_HOST/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "Spoiler do último episódio: o personagem X morre no final.",
"spoiler_text": "Spoiler S03E10",
"sensitive": true,
"visibility": "unlisted",
"language": "pt"
}'
# DM para um usuário específico
curl -X POST "$MASTODON_HOST/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "@fulano@outra.instancia oi, te mando o link em DM",
"visibility": "direct"
}'
✓ O que FAZER
- ✓Usar CW para política, spoilers, conteúdo pesado, NSFW.
- ✓
spoiler_textcurto e descritivo, não clickbait. - ✓Marcar
language— ajuda na descoberta. - ✓Respeitar o tom: Mastodon não é Twitter ragebait.
✗ O que NÃO fazer
- ✗Tratar
directcomo mensagem segura — não é E2E. - ✗Postar tudo como
publicsem CW. - ✗Bot postando em
publica cada 30 segundos. - ✗Usar
spoiler_textcomo título caça-clique.
Conceitos-chave
Por post, não por conta — escolha consciente.
Aviso colapsável que o leitor escolhe expandir.
Esconde mídia atrás de blur até clicar.
Cultura local: CW + alt-text não são opcionais.
🎯 Resumo do Módulo
@user@host./settings/applications com scopes write:statuses e write:media.verify_credentials, secret fora do git.POST /api/v1/statuses com idempotência e language tag./api/v2/media com alt-text obrigatório.Próximo Módulo:
3.3 — Bluesky e o protocolo AT