Automatize o DzBot por script: veja seus bots, o que está rodando, ligue e desligue plugins. Tudo por requisição HTTP, sem abrir o painel.
Se você só quer jogar, pule esta página. Ela é para quem quer integrar.
É a mesma API que o site usa. As rotas aqui são as mesmas que o painel chama por dentro — com uma diferença: quem integra usa uma chave de acesso, e quem está no site usa a sessão dele. O resto é idêntico.
1O que você precisa: uma chave de API
Vá em Conta → Chaves de API e clique em Gerar chave.
Dê um nome que diga para que é (ex.: "bot do Discord", "script de backup"). A lista mostra o nome, nunca a chave — e é o nome que você usa para saber qual revogar se algo vazar.
No primeiro pedido, escolha o que a chave pode fazer:
| Permissão | Id | O que libera |
|---|---|---|
| Ler bots | bots:ler | ver a lista de bots, o detalhe, e quais plugins estão ligados |
| Ativar plugins | plugins:escrever | ligar e desligar plugins |
| Ligar e desligar bots | bots:escrever | não é liberado pela chave — a rota recusa com 403 |
| Ler economia | economia:ler | não é liberado pela chave — a rota recusa com 403 |
Comece com o mínimo que precisa. Uma chave de leitura não consegue ativar plugin — é para isso que as permissões existem.
2Como chamar
A base é a mesma do site:
https://dzbot.com.br/api/v1/minecraftEnvie a chave no cabeçalho X-DzBot-Key. É a única credencial — não precisa de login, não precisa de cookie, não precisa de nada além da chave.
curl https://dzbot.com.br/api/v1/minecraft \
-H "X-DzBot-Key: dz_AbCdEfGhIjKl_xxxxxxxxxxxxxxxx"Resposta:
{
"success": true,
"data": {
"bots": [
{ "id": "-P2YHTCRdnP0CC_tpZEC", "name": "DzBot", "status": "online" }
]
}
}Toda resposta tem a mesma forma: success, data e — quando dá erro — um error com um motivo estável (machine-readable, não muda).
3Endpoints
GET /api/v1/minecraft — seus bots
Permissão: bots:ler.
{ "bots": [ { "id": "...", "name": "...", "status": "online",
"instanceId": "...", "username": "...", "version": "1.21.4" } ] }GET /api/v1/minecraft/:id/status — detalhe de um bot
Permissão: bots:ler. Inclui o config (host, porta, versão) e o motivo da última queda, já traduzido:
{
"success": true,
"data": {
"botId": "-P2YHT...",
"status": "offline",
"online": false,
"lastError": "O servidor recusou a conexão\nLigue o servidor e confira a porta...",
"reason": "O servidor recusou a conexão\nLigue o servidor e confira a porta..."
}
}GET /api/v1/minecraft/:id/plugins — o que está ligado
Permissão: bots:ler.
{
"success": true,
"data": {
"botId": "-P2YHT...",
"plugins": [ { "plugin": "anti-afk", "enabled": true, "running": true } ],
"aoVivo": true
}
}⚠️ aoVivo importa. Ele diz se o bot tem worker rodando agora. Se for false, o que está na lista é o que foi gravado — pode ser diferente do que está rodando. Compare antes de agir.
PUT /api/v1/minecraft/:id/plugins — ativar ou desativar
Permissão: plugins:escrever.
curl -X PUT https://dzbot.com.br/api/v1/minecraft/-P2YHT.../plugins \
-H "X-DzBot-Key: dz_..." \
-H "Content-Type: application/json" \
-d '{"pluginName":"anti-afk","enabled":true}'| Campo | Tipo | Obrigatório |
|---|---|---|
pluginName | string | sim |
enabled | boolean | sim |
config | object | não |
⚠️ enabled tem que ser true ou false, e nada mais. Se mandar "true" (texto) ou omitir, a API responde 400 ENABLED_OBRIGATORIO. Isso é de propósito: sem o valor, o servidor não sabe se você quer ligar ou desligar — e o padrão "ausente = desligar" desligaria um plugin que estava funcionando.
A resposta diz quando vale:
{ "success": true,
"data": { "botId": "-P2YHT...", "pluginName": "anti-fall",
"enabled": true, "status": "saved_offline" } }applied_live— o bot recebeu agora.saved_offline— o bot está desligado; o plugin entra no próximo start.
As duas são sucesso. A diferença é quando, e é por isso que a API diz em vez de só devolver "ok": ler "ok" e continuar com o bot sem o plugin é a forma rápida de achar que deu certo quando não deu.
4Erros
Formato:
{ "success": false,
"error": "CHAVE_REVOGADA",
"detail": "Esta chave de API foi revogada. Gere outra no painel." }| HTTP | error | O que fazer |
|---|---|---|
| 401 | CHAVE_AUSENTE | faltou o cabeçalho X-DzBot-Key |
| 401 | CHAVE_MALFORMADA | a chave não tem o formato dz_id_segredo |
| 401 | CHAVE_NAO_ENCONTRADA | chave inválida |
| 401 | CHAVE_REVOGADA | você revogou essa chave |
| 403 | ESCOPO_INSUFICIENTE | a chave não tem a permissão para esta ação |
| 403 | ROTA_BLOQUEADA | esta rota não é liberada para chave (ex.: ligar bot) |
| 400 | ENABLED_OBRIGATORIO | enabled não veio como booleano |
| 400 | VALIDATION_ERROR | faltou o pluginName |
| 404 | PLUGIN_NOT_FOUND | o plugin não existe nesse bot |
| 502 | PLUGIN_NOT_APPLIED | o bot não confirmou a alteração |
⚠️ Erro de chave nunca diz se a chave existe. Só CHAVE_AUSENTE (não mandou) e CHAVE_REVOGADA (existe e foi revogada) são distinguíveis — e são os dois que mudam o que você faz. Os demais não revelam nada sobre chaves alheias.
⚠️ A chave não alcança tudo. O painel do site usa as mesmas rotas com mais permissão (é a sessão dele). A chave tem um escopo menor, e o que está fora dele é recusado com 403 — não é "permitido por omissão". Ligar, desligar e reiniciar bots, por exemplo, não são liberados pela chave.
error é estável
Use o error, não o detail. O detail é texto para humanos e pode mudar; o error é o identificador que seu script pode tratar.
5Receitas
Esperar o bot ficar online
const CAB = { "X-DzBot-Key": process.env.DZ_KEY };
const BASE = "https://dzbot.com.br/api/v1/minecraft";
async function status(id) {
const r = await fetch(`${BASE}/${id}/status`, { headers: CAB });
if (!r.ok) throw new Error("chave recusada: " + r.status);
return (await r.json()).data;
}
let s;
for (let i = 0; i < 30; i++) {
s = await status(BOT);
if (s.status === "online") break;
await new Promise(r => setTimeout(r, 5000));
}
console.log(s.status); // "online"Ligar um plugin se o bot estiver ligado
async function ligarPlugin(id, nome) {
const r = await fetch(`${BASE}/${id}/plugins`, {
method: "PUT",
headers: { ...CAB, "Content-Type": "application/json" },
body: JSON.stringify({ pluginName: nome, enabled: true }),
});
const { data, error, detail } = await r.json();
if (!r.ok) throw new Error(`${error}: ${detail}`);
// saved_offline NÃO é falha: o bot precisa ligar para o plugin entrar
console.log(data.status);
return data.status;
}6Segurança
- A chave é uma senha. Não cole em repositório, não mande por Discord, não ponha no logs. Quem tiver a chave age como você.
- Dê o menor escopo possível. Só "Ativar plugins" se é isso que o script faz.
- Um script por chave. Assim você sabe qual revogar se um vazar, e revogar um não derruba os outros.
- Revogar é imediato. Em Conta → Chaves de API, na lixeira. O script para de funcionar na hora e não tem volta.
- A API só age no que é seu. O dono vem da chave, não da requisição — não existe parâmetro que troque de quem são os bots.
- Sondar não revela o que existe. Pedir um bot de outra pessoa devolve 404 — o mesmo 404 de um bot que não existe. E um erro de chave não diz se a chave existe: só "não mandou" e "revogada" são distinguíveis, e são os dois casos em que a ação é diferente.
7Limites conhecidos
Honesto, porque API que esconde defeito custa mais que API que não tem:
- Não dá para ligar/desligar bots pela chave. O escopo existe, a rota não é liberada — e a recusa é
403 ROTA_BLOQUEADA, não um 401 que faz você caçar a chave errada. Para isso, use o painel. - Não há paginação. A lista de bots vem inteira. É adequado para dezenas de bots; com centenas, a chamada fica pesada.
- Só funciona no Firebase. O dono da chave é lido de lá, e em Postgres a chave não é encontrada.
- A família
/api/chave/*é a antiga. Ela continua funcionando para quem já usa, mas a canônica é a/api/v1/minecraft/*— a mesma do site. Não misture as duas na mesma integração.
Ajuda ou um caso que não está aqui? Fale com o suporte pelo Discord.