Pular para o conteúdo

Faz o deploy de um servidor

POST /cloud/servers

Escopo do token: servers:write · aceita Idempotency-Key · continua em segundo plano. Recurso: Servidores.

Exige cartão salvo, menos para conta de uso interno. Reserva uma máquina em estoque, abre o contrato mensal do servidor (com o cupom, se houver) e registra a operação, que segue em segundo plano (acompanhe GET /cloud/operations/{operation_id}). Primeira fatura sem nada a pagar (conta interna, cupom de 100%) não passa pelo cartão. Cupom que não vale responde 422 coupon.unavailable (“Cupom inválido ou indisponível.”, sem o motivo) e desfaz a compra; com cupom, o pedido conta no limite de tentativas de cupom (429 coupon.rate_limited). Aceita Idempotency-Key: repetir a mesma chave nunca cobra nem cria um segundo servidor. external_id (o pedido do revendedor) é único na conta entre os servidores não removidos: um segundo deploy com o mesmo valor responde 409 cloud.external_id_taken com o id do servidor que já o tem em existing_id, sem reservar máquina nem cobrar; a mesma Idempotency-Key continua devolvendo a resposta guardada do primeiro pedido.

Os exemplos leem o token da variável de ambiente HALVER_API_TOKEN (um token sc_live_… criado em Desenvolvedores › Tokens de API). Nunca escreva o token no código.

Janela do terminal
curl -X POST "https://dash.halver.com.br/api/v1/cloud/servers" \
-H "Authorization: Bearer $HALVER_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"description": "Servidor de produção",
"end_customer_ref": "",
"external_id": "",
"hostname": "web-01",
"os_image_id": "180cadfe-7099-445b-9dce-3a86af179a17",
"plan_id": "a30bf51c-7749-4ed5-8983-8201f864273b",
"site_id": "4afc7034-1b53-4b2a-bc4c-d831d6e39028",
"ssh_key_ids": [
"f14f67d8-9ae9-4217-991b-854a52150ae7"
],
"tags": [
"env=prod"
],
"user_data": "#cloud-config\npackages:\n - nginx\nruncmd:\n - systemctl enable --now nginx\n"
}'
  • Idempotency-Key string

    Chave de idempotência (draft-ietf-httpapi-idempotency-key-header-07): de 1 a 255 caracteres ASCII visíveis, como string de Structured Field ("…") ou texto puro; gere uma nova (um UUID) para cada operação. Vale por 24 horas, por conta e credencial (o token, ou o usuário no painel). A mesma chave com a mesma requisição (método, caminho, query e corpo) repete a resposta guardada (status e corpo) com Idempotent-Replayed: true, sem cobrar nem criar de novo; com outra requisição responde 422 idempotency.key_reused; enquanto a primeira roda, 409 idempotency.in_progress com Retry-After. Toda resposta fica guardada, inclusive 5xx (uma falha pode vir depois de uma cobrança); só 401, 403, 409 e 429, que dizem que nada rodou, liberam a chave. Uma chave presa por uma requisição que morreu é liberada depois de 10 minutos. Veja Idempotência.

application/json, obrigatório.

  • coupon_code string

    Cupom de desconto digitado no checkout; inválido recusa a compra com 422 (campo coupon_code).

  • description string

    Até 500 caracteres.

  • disk_layout string

    Legado (use storage, que tem precedência): single é o disco padrão (ext4 no Proxmox VE) e raid1 o espelho do primeiro par de discos iguais (ZFS RAID 1 no Proxmox VE), se o plano e o sistema permitem. Sem storage nem disk_layout: o Proxmox VE vai em ZFS RAID 1 no par de discos iguais com o disco de boot (ou ZFS num disco) e um sistema de imagem no menor disco que não seja HDD. Um de: single, raid1.

  • end_customer_ref string

    Id do cliente final no sistema do revendedor: agrupa servidores, não é único. Id opaco, sem dado pessoal (nem nome nem CPF), com a mesma regra do external_id. Vazio ou ausente: sem referência. Formato: ^([A-Za-z0-9._:-]{1,128})?$.

  • external_id string

    Id do pedido no sistema do revendedor: único na conta entre os servidores não removidos. Id opaco, sem dado pessoal (nem nome nem CPF): de 1 a 128 caracteres entre letras sem acento, números e . _ : -. Repetido na conta: 409 cloud.external_id_taken com existing_id. Um servidor em remoção ainda ocupa o valor até a remoção terminar (status deleted). Vazio ou ausente: servidor sem referência. Formato: ^([A-Za-z0-9._:-]{1,128})?$.

  • hostname string obrigatório
  • os_image_id string (uuid) obrigatório
  • password boolean

    Gera uma senha a cada instalação e a envia por e-mail a quem pediu.

  • plan_id string (uuid) obrigatório
  • site_id string (uuid) obrigatório
  • ssh_key_ids array de string (uuid)
  • storage object

    Os discos do plano (ids de disk_slots), o sistema de arquivos e o nível de RAID. Um pool usa discos iguais (mesmo tipo e tamanho); ext4 e XFS usam um disco; um sistema de imagem usa um disco, ou dois em RAID 1 quando oferece; cada nível do ZFS pede o seu mínimo de discos; a escolha inclui o boot_slot do plano, quando ele existe. Os discos fora da escolha ficam livres.

    • disks array de string obrigatório
    • filesystem string

      zfs (padrão no Proxmox VE), ext4 ou xfs; vazio nos sistemas de imagem.

    • raid string

      single, raid0, raid1, raid10, raidz-1, raidz-2 ou raidz-3; obrigatório no ZFS com mais de um disco.

  • tags array de string

    Até 20 itens. Formato de cada item: ^[a-z0-9]([a-z0-9_.:=/-]{0,62}[a-z0-9])?$.

  • user_data string

    Documento do cloud-init: a primeira linha é #cloud-config (YAML com um mapa de chaves) ou um #! de script, em UTF-8, até 64 KiB; pode vir em base64. Roda no primeiro boot de cada instalação, depois da configuração da plataforma: no #cloud-config, o que a plataforma define (login, senha, disable_root, ssh_pwauth) prevalece e as suas listas (runcmd, packages, write_files, users…) são acrescentadas às nossas; um script roda depois do script de primeiro boot do sistema. Hostname, chaves e rede vêm dos metadados. Guardado cifrado; a API devolve só user_data_sha256 e user_data_size. Só sistemas por imagem (422 cloud.user_data_unsupported no instalador do Proxmox VE e em “Sem sistema”). Muda só com a reinstalação. Até 90000 caracteres.

Exemplo de corpo
{
"description": "Servidor de produção",
"end_customer_ref": "",
"external_id": "",
"hostname": "web-01",
"os_image_id": "180cadfe-7099-445b-9dce-3a86af179a17",
"plan_id": "a30bf51c-7749-4ed5-8983-8201f864273b",
"site_id": "4afc7034-1b53-4b2a-bc4c-d831d6e39028",
"ssh_key_ids": [
"f14f67d8-9ae9-4217-991b-854a52150ae7"
],
"tags": [
"env=prod"
],
"user_data": "#cloud-config\npackages:\n - nginx\nruncmd:\n - systemctl enable --now nginx\n"
}

Servidor em deploy.

Cabeçalhos:

  • Idempotent-Replayed: true quando a resposta foi repetida de uma requisição anterior com a mesma Idempotency-Key. Convenção desta API, como a de outras; o rascunho da IETF não define cabeçalho de repetição.
  • Retry-After: Segundos sugeridos até consultar de novo (GET /cloud/operations/{id} ou o recurso): a operação segue em segundo plano e avança a cada 10 s.
Campos da resposta
  • cancel_at string (date) obrigatório pode ser nulo

    Último dia da assinatura cancelada (fim do período pago); depois dele a máquina volta ao estoque.

  • contract_id string (uuid) obrigatório pode ser nulo
  • created_at string (date-time) obrigatório
  • description string

    Descrição livre do cliente (até 500 caracteres).

  • disk_layout string obrigatório

    Legado (veja storage) - raid1 quando a última instalação é um RAID 1, senão single. Um de: single, raid1.

  • end_customer_ref string pode ser nulo

    Id do cliente final no sistema do revendedor: agrupa servidores, não é único. Id opaco, sem dado pessoal (nem nome nem CPF), com a mesma regra do external_id. Nulo quando não informado.

  • external_id string pode ser nulo

    Id do pedido no sistema do revendedor: único na conta entre os servidores não removidos. Id opaco, sem dado pessoal (nem nome nem CPF): de 1 a 128 caracteres entre letras sem acento, números e . _ : -. Nulo quando não informado.

  • first_invoice_id string (uuid) obrigatório pode ser nulo

    Fatura cobrada na compra.

  • hostname string obrigatório
  • id string (uuid) obrigatório
  • ipv4 string obrigatório
  • ipv4_gateway string obrigatório
  • ipv4_prefix integer obrigatório
  • monthly_cents integer (int64) obrigatório

    O que o servidor custa por mês: a recorrência do contrato dele (com reajustes), não o preço atual do plano, que vale só para servidores novos.

  • operation string obrigatório

    Um de: deploy, reinstall, wipe, delete, "" (vazio).

  • operation_id string (uuid) pode ser nulo

    A última operação do servidor (deploy, reinstall, wipe ou delete); acompanhe por GET /cloud/operations/{id}.

  • os object obrigatório
    • code string obrigatório
    • family string obrigatório
    • id string (uuid) obrigatório
    • install_method string obrigatório

      image grava uma imagem de disco; installer inicia o instalador oficial do sistema (Proxmox VE); none não instala nada (o cliente instala o próprio sistema pela IPMI). Um de: image, installer, none.

    • login_user string obrigatório

      Usuário de acesso ao sistema instalado.

    • name string obrigatório
    • password_required boolean obrigatório

      O sistema é usado com senha (painel web do Proxmox VE).

    • raid1 boolean obrigatório

      O sistema instala num espelho (RAID 1) de dois discos iguais.

    • storage object obrigatório

      O que o cliente escolhe nos discos deste sistema. O instalador do Proxmox VE grava ZFS (padrão, recomendado), ext4 ou XFS; ext4 e XFS vão num disco, o ZFS num disco ou nos níveis de RAID. Um sistema de imagem vai num disco (o sistema de arquivos é o da imagem) ou, quando o motor tem a versão dele para espelho, em RAID 1 de dois discos iguais.

      • default_filesystem string obrigatório

        Um de: zfs, ext4, xfs, "" (vazio).

      • filesystems array de string obrigatório

        Sistemas de arquivos que o instalador grava; vazio nos sistemas de imagem. Um de: zfs, ext4, xfs.

      • levels array de object obrigatório
        • even_disks boolean obrigatório

          O nível usa discos em pares (RAID 10).

        • filesystems array de string obrigatório

          Sistemas de arquivos que oferecem o nível; vazio nos sistemas de imagem. Um de: zfs, ext4, xfs.

        • level string obrigatório

          Um de: single, raid0, raid1, raid10, raidz-1, raidz-2, raidz-3.

        • max_disks integer obrigatório

          0 é sem limite.

        • min_disks integer obrigatório
    • version string obrigatório
  • password_login boolean obrigatório

    Cada instalação gera uma senha e a envia por e-mail.

  • plan object obrigatório
    • active boolean obrigatório
    • bandwidth_mbps integer obrigatório

      Limite de banda; 0 é a porta inteira.

    • boot_slot string

      Disco pelo qual o servidor inicia (id de disk_slots): o sistema precisa incluí-lo, sozinho ou num pool de discos iguais. As máquinas iniciam em BIOS legado só pelo primeiro disco. Ausente quando qualquer disco inicia o servidor.

    • code string obrigatório
    • cores integer obrigatório
    • cpu string obrigatório
    • cpu_threads integer obrigatório
    • created_at string (date-time) obrigatório
    • disk_slots array de object obrigatório

      Os discos do plano um a um, onde o sistema pode ser instalado.

      • id string obrigatório

        <tipo>-<GB>-<n>, por exemplo ssd-128-2: o segundo SSD de 128 GB do plano.

      • model string obrigatório
      • size_gb integer obrigatório
      • type string obrigatório

        Um de: nvme, ssd, hdd.

    • disks array de object obrigatório

      Discos mínimos que a máquina precisa ter.

      • count integer obrigatório
      • model string
      • size_gb integer obrigatório
      • type string obrigatório

        Um de: nvme, ssd, hdd.

    • id string (uuid) obrigatório
    • memory_gb integer obrigatório
    • monthly_cents integer (int64) obrigatório
    • name string obrigatório
    • port_speed_mbps integer obrigatório

      Velocidade da porta entregue.

    • product_id string (uuid) obrigatório pode ser nulo
    • raid1 boolean obrigatório

      O plano tem dois discos iguais, então o servidor pode espelhá-los (RAID 1).

    • traffic_tb integer obrigatório

      Tráfego mensal em TB; 0 é ilimitado.

  • power string obrigatório

    Um de: on, off, unknown.

  • site object obrigatório
    • active boolean obrigatório
    • city string obrigatório
    • code string obrigatório
    • country string obrigatório
    • created_at string (date-time) obrigatório
    • id string (uuid) obrigatório
    • name string obrigatório
    • region_id string (uuid) obrigatório

      Região do local; os IPs das máquinas vêm dos blocos dela.

  • ssh_keys integer obrigatório

    Quantidade de chaves instaladas no último deploy.

  • status string obrigatório

    Um de: pending_payment, deploying, active, failed, wiping, empty, deleting, deleted.

  • steps array de object obrigatório
    • finished_at string (date-time) obrigatório pode ser nulo
    • message string obrigatório
    • name string obrigatório

      Um de: prepare, erase, install, configure, reboot, ready, release.

    • started_at string (date-time) obrigatório pode ser nulo
    • status string obrigatório

      Um de: pending, running, done, failed.

  • storage object obrigatório

    Onde a última instalação pôs o sistema.

    • disks array de object obrigatório
      • id string obrigatório

        <tipo>-<GB>-<n>, por exemplo ssd-128-2: o segundo SSD de 128 GB do plano.

      • model string obrigatório
      • size_gb integer obrigatório
      • type string obrigatório

        Um de: nvme, ssd, hdd.

    • filesystem string obrigatório

      Vazio nos sistemas de imagem (o sistema de arquivos é o da imagem). Um de: zfs, ext4, xfs, "" (vazio).

    • raid string obrigatório

      Um de: single, raid0, raid1, raid10, raidz-1, raidz-2, raidz-3.

    • summary string obrigatório
  • suspended_at string (date-time) obrigatório pode ser nulo

    Desligado por falta de pagamento, com os dados mantidos; volta a ser ligado sozinho quando a fatura é paga. Enquanto isso, power, reinstalação, apagar, cancelar e VPN da IPMI respondem 409 cloud.server_suspended.

  • tags array de string

    Tags do cliente, em ordem alfabética e sem repetição.

  • terminated_at string (date-time) obrigatório pode ser nulo

    Encerrado na hora pela equipe. O cliente continua vendo a página do servidor (o aviso leva até ela) mesmo depois de removido, só com o texto fixo da categoria.

  • termination_category string obrigatório

    Por que a equipe encerrou o servidor (vazio quando não foi encerrado pela equipe). Um de: "" (vazio), abuse, fraud, customer_request, internal_test, delinquency, other.

  • user_data_sha256 string pode ser nulo

    SHA-256 (hex) do user data das instalações; o conteúdo nunca é devolvido. Nulo sem user data.

  • user_data_size integer

    Tamanho do user data em bytes (0 sem user data).

Exemplo de resposta
{
"cancel_at": null,
"contract_id": "751e7c9a-fae2-4027-9be3-5728dfce8982",
"created_at": "2026-10-20T18:00:00Z",
"description": "Servidor de produção",
"disk_layout": "raid1",
"end_customer_ref": null,
"external_id": null,
"first_invoice_id": "36d56e13-ffa3-4af3-acc1-14aa538fb0ab",
"hostname": "web-01",
"id": "307d7f63-0f00-4d4b-bc28-839d359e13a3",
"ipv4": "203.0.113.10",
"ipv4_gateway": "203.0.113.1",
"ipv4_prefix": 29,
"monthly_cents": 79900,
"operation": "deploy",
"operation_id": "38b54c25-1f8d-40fe-8cb1-649ddb710f23",
"os": {
"code": "ubuntu-24.04",
"family": "ubuntu",
"id": "180cadfe-7099-445b-9dce-3a86af179a17",
"install_method": "image",
"login_user": "ubuntu",
"name": "Ubuntu 24.04 LTS",
"password_required": false,
"raid1": true,
"storage": {
"default_filesystem": "",
"filesystems": [],
"levels": [
{
"even_disks": false,
"filesystems": [],
"level": "raid1",
"max_disks": 2,
"min_disks": 2
}
]
},
"version": "24.04"
},
"password_login": false,
"plan": {
"active": true,
"bandwidth_mbps": 0,
"boot_slot": "",
"code": "c1.small.ssd",
"cores": 4,
"cpu": "Intel(R) Xeon(R) CPU E3-1270 v6 @ 3.80GHz",
"cpu_threads": 8,
"created_at": "2026-10-20T18:00:00Z",
"disk_slots": [
{
"id": "ssd-128-2",
"model": "",
"size_gb": 128,
"type": "ssd"
}
],
"disks": [
{
"count": 2,
"model": "",
"size_gb": 128,
"type": "ssd"
}
],
"id": "a30bf51c-7749-4ed5-8983-8201f864273b",
"memory_gb": 32,
"monthly_cents": 79900,
"name": "c1.small.ssd · Supermicro X11",
"port_speed_mbps": 1000,
"product_id": "a3052a82-1c61-48d1-8feb-612bf80ff949",
"raid1": true,
"traffic_tb": 0
},
"power": "on",
"site": {
"active": true,
"city": "Varginha",
"code": "mg-1",
"country": "BR",
"created_at": "2026-10-20T18:00:00Z",
"id": "4afc7034-1b53-4b2a-bc4c-d831d6e39028",
"name": "Minas Gerais 01",
"region_id": "7991b4f0-3bd8-47f3-bd3c-30b5d9ac664e"
},
"ssh_keys": 1,
"status": "active",
"steps": [
{
"finished_at": null,
"message": "",
"name": "prepare",
"started_at": null,
"status": "done"
}
],
"storage": {
"disks": [
{
"id": "ssd-128-2",
"model": "",
"size_gb": 128,
"type": "ssd"
}
],
"filesystem": "",
"raid": "raid1",
"summary": "ZFS RAID 1 em 2× SSD 128 GB"
},
"suspended_at": null,
"tags": [
"env=prod"
],
"terminated_at": null,
"termination_category": "",
"user_data_sha256": "9f2c4e1b7a3d5f8e0c6b2a4d8e1f3a5c7b9d0e2f4a6c8e0b1d3f5a7c9e1b3d5f",
"user_data_size": 92
}

Todo erro vem como application/problem+json (RFC 9457), com um code estável, a mensagem em português em detail, o motivo de cada campo em errors (nos erros de validação) e o request_id, que você informa ao suporte. Veja a lista completa de códigos.

Status Quando Códigos
400 Requisição inválida (JSON malformado, campo desconhecido, parâmetro inválido ou falha de validação). validation_failed, request.invalid_json, idempotency.invalid_key
401 Não autenticado (token ausente, inválido ou expirado; credenciais inválidas). auth.unauthorized
403 Autenticado, mas sem permissão para a área ou a operação. api_token.insufficient_scope
409 Conflito (unicidade ou operação concorrente em andamento). idempotency.in_progress, cloud.external_id_taken
422 Entrada válida, mas viola uma regra de negócio. idempotency.key_reused, coupon.unavailable
429 Limite de requisições excedido. Retry-After diz em quantos segundos cabe a próxima requisição; os limites de taxa também mandam RateLimit-Policy e RateLimit (draft-ietf-httpapi-ratelimit-headers). rate_limited, coupon.rate_limited
503 Dependência (gateway de pagamento, consulta de CEP) temporariamente indisponível. —
Exemplo de erro
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "o token não tem o escopo servers:write; crie um token com esse escopo em Desenvolvedores › Tokens de API",
"code": "api_token.insufficient_scope",
"request_id": "6f1c0b2a9e4d7c3b5a8f0e1d"
}