API REST v1

Automatize seus servidores

Integre o EzServer aos seus scripts, pipelines de deploy e sistemas internos. Respostas em JSON, autenticação por token.

URL base https://ezserver.app/api/v1

Prefere conversar com seus servidores pelo Claude? Veja a integração MCP.

Início rápido

1.Faça login

Use o e-mail e a senha da sua conta. A conta precisa ter o e-mail confirmado e a autenticação em dois fatores ativa (ative no painel no primeiro login). A resposta traz um challenge_token:

curl -X POST https://ezserver.app/api/v1/auth/login \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"email":"voce@empresa.com","password":"SUA_SENHA"}'

# Resposta (HTTP 200)
{ "success": false, "message": "2FA requerido", "requires_2fa": true,
  "challenge_token": "hK3v…(64 caracteres)…Qz", "expires_in": 300 }

2.Envie o código do app autenticador

curl -X POST https://ezserver.app/api/v1/auth/verify-2fa \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"challenge_token":"hK3v…Qz","code":"482913"}'

# Resposta (HTTP 200)
{ "success": true, "data": { "user": { ... }, "token": "45|o8Xk...Zq1" } }

O challenge_token vale por 5 minutos, pode ser usado uma única vez e é descartado após 5 códigos errados — nesse caso, faça login de novo. No lugar do código de 6 dígitos você pode enviar um código de backup.

Guarde o token em local seguro (variável de ambiente, cofre de segredos). Ele não expira — revogue com DELETE /auth/tokens/{id} quando não precisar mais.

3.Chame a API com o token

Envie sempre os cabeçalhos Authorization e Accept: application/json:

curl https://ezserver.app/api/v1/servers \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Accept: application/json"

Endpoints

Todos os caminhos são relativos à URL base. {id} é o ID numérico retornado em GET /servers. Exceto login, 2FA e health, todos exigem token. Esta é a lista dos principais — parâmetros, respostas e os demais endpoints (terminal em tempo real, domínios, backups, banco de dados, arquivos, webhooks e MCP) estão na documentação completa (.md).

Autenticação

  • POST /auth/login Valida e-mail e senha e devolve um challenge_token (válido por 5 minutos).
  • POST /auth/verify-2fa Envia challenge_token + código do app autenticador (ou código de backup) e recebe o token.
  • GET /auth/profile Dados do usuário do token.
  • GET /auth/tokens Lista seus tokens ativos.
  • DELETE /auth/tokens/{id} Revoga um token.
  • POST /auth/logout Revoga o token usado na requisição.
  • POST /auth/logout-all Revoga todos os seus tokens.

Servidores

  • GET /servers Lista seus servidores.
  • POST /servers Cadastra um servidor (autenticação por senha).
  • GET /servers/{id} Detalhes, configuração detectada e métricas de um servidor.
  • PUT /servers/{id} Atualiza nome, IP, porta, usuário, senha, tipo ou status.
  • DELETE /servers/{id} Remove o servidor do EzServer (não mexe na máquina).
  • POST /servers/{id}/test-connection Testa a conexão SSH.
  • POST /servers/{id}/execute-command Executa um comando via SSH e devolve saída e exit code.
  • GET /servers/{id}/applications Aplicações detectadas no servidor.
  • POST /servers/{id}/terminal Ticket de uso único para o terminal SSH em tempo real (WebSocket).

Monitoramento e conta

  • GET /metrics Últimas métricas (CPU, memória, disco, carga) de todos os servidores.
  • GET /dashboard Resumo da conta: contagem de servidores, domínios e plano.
  • GET /domains Lista seus domínios.
  • GET /health Status da API (não exige token).

Exemplos

Cadastrar um servidor

curl -X POST https://ezserver.app/api/v1/servers \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "producao-loja",
    "ip_address": "203.0.113.10",
    "ssh_port": 22,
    "ssh_user": "root",
    "ssh_password": "SENHA_DO_SERVIDOR",
    "type": "vps"
  }'

Obrigatórios: name, ip_address (somente IP), ssh_user e ssh_password (mín. 6 caracteres). Opcionais: ssh_port (padrão 22) e type (vps, dedicated, cloud, shared). O servidor nasce como inactive; chame test-connection para validar e ativar. Para usar chave SSH, cadastre pelo painel. O limite de servidores do plano também vale para a API.

Executar um comando

curl -X POST https://ezserver.app/api/v1/servers/42/execute-command \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"command":"df -h /"}'

# Resposta
{
  "success": true,
  "data": {
    "command": "df -h /",
    "output": "Filesystem  Size  Used Avail Use% Mounted on\n/dev/sda1  80G  27G  53G  34% /\n",
    "error": "",
    "exit_code": 0
  }
}

Terminal SSH em tempo real (WebSocket)

Para embutir o terminal no seu app: peça um ticket com o token da API e abra o WebSocket. A senha e a chave SSH nunca saem do EzServer.

curl -X POST https://ezserver.app/api/v1/servers/42/terminal \
  -H "Authorization: Bearer SEU_TOKEN" -H "Accept: application/json"

# { "data": { "ws_url": "wss://…/ssh-ws", "ticket": "…", "expires_in": 60 } }

// No app (JavaScript)
const ws = new WebSocket(data.ws_url);
ws.onopen = () => ws.send(JSON.stringify({ type: "auth", ticket: data.ticket, cols: 80, rows: 24 }));
ws.onmessage = (ev) => {
  const msg = JSON.parse(ev.data);              // connected | output | error | disconnected
  if (msg.type === "output")                     // saída: UTF-8 em base64
    term.write(new TextDecoder().decode(Uint8Array.from(atob(msg.data), (c) => c.charCodeAt(0))));
};
ws.send(JSON.stringify({ type: "input", data: "ls -la\r" }));
ws.send(JSON.stringify({ type: "resize", cols: 120, rows: 40 }));

O ticket vale 60 segundos e uma única conexão. Por padrão o terminal usa uma sessão persistente tmux: se a conexão cair, peça outro ticket e reconecte para continuar de onde parou. Protocolo completo, teclas especiais, reconexão e exemplos com xterm.js e Python na documentação completa.

Exemplo em Python

import os, requests

BASE = "https://ezserver.app/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['EZSERVER_TOKEN']}", "Accept": "application/json"}

for s in requests.get(f"{BASE}/metrics", headers=HEADERS, timeout=30).json()["data"]:
    if (s.get("disk_usage") or 0) > 85:
        print(f"⚠️  {s['name']}: disco em {s['disk_usage']}%")

Erros

Erros de validação retornam o campo errors:

{
  "success": false,
  "message": "Dados de validação inválidos",
  "errors": { "ip_address": ["O campo ip address deve ser um endereço IP válido."] }
}
200 / 201Sucesso / recurso criado
401Token ausente/inválido ou credenciais erradas
403E-mail não confirmado ou 2FA não ativado na conta
404Recurso não existe ou não pertence à sua conta
422Dados inválidos ou limite do plano atingido
429Muitas tentativas — aguarde e tente de novo
500Erro interno ou falha na conexão SSH (veja "message")

Limites e boas práticas

  • Login, 2FA e cadastro aceitam até 10 tentativas por minuto por IP. Faça login uma vez e reutilize o token.
  • O token tem os mesmos poderes que a sua conta, incluindo executar comandos. Nunca o coloque em código versionado ou no front-end.
  • execute-command espera o comando terminar. Para tarefas longas, rode em segundo plano (nohup … &) ou use o terminal com tmux.
  • Revogue tokens antigos em GET /auth/tokens + DELETE /auth/tokens/{id}.

Precisa de algo que a API ainda não faz?

Conte o seu caso de uso — ele ajuda a priorizar os próximos endpoints.

Fale com a gente