Documentação
API Reference
Faça por chamada HTTP o que você faz pelo painel: autenticação por token com escopo, e uma rota para cada operação.
Endereço base
https://api.nexcloud.gg/v1/publicEndereço e formato
Onde a API responde, e o envelope que toda resposta usa.
Toda rota pública vive sob /v1/public e responde em JSON. O corpo de uma requisição com dados é application/json, exceto onde há arquivo — aí é multipart/form-data, e isso está dito na rota.
curl https://api.nexcloud.gg/v1/public/account \ -H "Authorization: Bearer nxc_seu_token_aqui"
O envelope
Sucesso e erro têm formatos fixos. O que muda é o que vem dentro de response.
{
"status": "success",
"response": { "…": "o conteúdo da rota" }
}{
"status": "error",
"code": "MEMORY_ABOVE_PLAN_QUOTA",
"params": { "requestedMb": 2048, "availableMb": 512 }
}O contrato é o `code`, nunca a frase
params com eles. Quem monta a frase é quem exibe — é assim que o painel fala dois idiomas sem a API saber qual. Se a sua integração mostra mensagem para uma pessoa, escreva a frase a partir do code, não do que vier em message.| Campo | Quem escreveu | O que fazer com ele |
|---|---|---|
| code | a plataforma | Escolher a frase e o caminho do seu código. |
| params | a plataforma | Preencher a frase — limites, nomes, prazos. |
| fields | a plataforma | Apontar o campo do formulário que foi recusado. |
| detail | um terceiro | Mostrar cru. É a resposta do seu banco de dados, do seu provedor de DNS ou do meio de pagamento — é ela que diz o que de fato foi recusado. |
Autenticação
Um token com escopos, criado no painel, enviado no cabeçalho Authorization.
- 1Abra Tokens de API no painel e crie um token, marcando só os escopos de que a sua automação precisa.
- 2Copie o valor. Ele começa com
nxc_e aparece uma única vez — a plataforma guarda só uma impressão dele, e nem o suporte consegue mostrá-lo depois. - 3Mande em toda chamada no cabeçalho
Authorization. OBeareré opcional e sem distinção de caixa.
Authorization: Bearer nxc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Um token pode ter prazo de validade — vale a pena para automação temporária, porque ele some sozinho se você esquecer dele — e pode ser revogado a qualquer momento pelo painel. O painel guarda a data do último uso de cada token, com resolução de minutos: é como se percebe um token vazado.
A sessão do painel não vale aqui
/v1/public responde API_TOKEN_REQUIRED — o código diz qual é o problema em vez de um 401 seco, porque quem está integrando precisa saber que a credencial é a errada, e não que o token dele quebrou.Escopos
O que cada escopo alcança. Não há herança: quem precisa de dois, marca os dois.
| Escopo | Alcança |
|---|---|
| apps:read | Ver aplicações, status, métricas, logs, eventos e deploys. |
| apps:write | Criar, editar, start/stop/restart, memória, redeploy e apagar. |
| databases:read | Ver bancos, métricas, logs, backups e vínculos. |
| databases:write | Criar, apagar, start/stop, backup, restore e vincular. |
| databases:credentials | Ler a senha em claro, as variáveis e rotacionar. |
| databases:sql | Listar tabelas, ler e escrever linhas, console SQL. |
| domains:read | Listar os domínios de uma aplicação. |
| domains:write | Adicionar, remover e reverificar domínio. |
| plan:read | Plano, limites, uso e faturas. |
| workspaces:read | Ver workspaces, membros e aplicações compartilhadas. |
| workspaces:write | Criar workspace, gerir membros e aplicações dele. |
| blob:read | Listar e detalhar arquivos do blob storage. |
| blob:write | Enviar e apagar arquivos do blob storage. |
| snapshots:read | Listar snapshots e baixar. |
| snapshots:write | Criar, restaurar e apagar snapshot. |
Os dois escopos sensíveis
databases:credentials e databases:sql nascem desmarcados na tela. Não são uma categoria diferente de permissão — a plataforma trata todos igual —, é uma afirmação sobre o dano: os dois dão acesso ao conteúdo do seu banco, e não só ao ciclo de vida dele. Um token de CI que só provisiona não precisa de nenhum dos dois.Faltando um escopo, a resposta é 403 MISSING_SCOPE com o escopo que falta em params.required — é o que permite ao seu curl dizer exatamente o que marcar na tela, em vez de você tentar rota por rota.
Limites de chamadas
São dois tetos, aplicados em sequência, e os dois respondem 429 TOO_MANY_REQUESTS quando estouram.
Por IP, antes da autenticação
300 / min
Existe para tentar um token inválido não sair de graça.
Por token, depois da autenticação
600 / min
Chaveado no token e não no IP: duas esteiras de CI atrás do mesmo NAT não dividem orçamento, e um token barulhento não derruba os irmãos.
Algumas rotas têm teto próprio, mais apertado, porque devolvem segredo ou custam caro do outro lado — elas estão marcadas individualmente na referência abaixo. Não há cabeçalho de quota na resposta: trate o 429 como sinal de recuar e tente de novo depois de alguns segundos.
Paginação
As listagens longas aceitam page e perpage na querystring, e devolvem os totais junto dos itens. limit continua sendo aceito como sinônimo de perpage e continua saindo na resposta.
{
"page": 1,
"limit": 24,
"perpage": 24,
"total": 137,
"pages": 6
}O teto absoluto é de 100 itens por página, em qualquer listagem: um perpage=99999 recebe 100 e não um erro. Busca por texto, onde existe, é o parâmetro q, e roda no servidor — filtrar só a página aberta daria um resultado errado para quem tem mais itens do que cabe numa página.
Status e erros
Todo código que a API pode devolver, o que cada um quer dizer e qual deles vale tentar de novo.
Quando deu certo
| HTTP | Quando acontece |
|---|---|
| 200 | Leitura, e toda ação que termina na hora. |
| 201 | Alguma coisa passou a existir: aplicação, banco, domínio, backup, vínculo ou arquivo. O corpo traz o recurso criado. |
| 202 | O pedido foi aceito e continua correndo depois da resposta — é o caso do restore de snapshot, que você acompanha pela rota de andamento em vez de assumir que terminou. A listagem de snapshots de uma aplicação também responde 202, por um detalhe histórico: ali é sucesso comum, com a lista no corpo. |
| 204 | Deu certo e não há corpo para devolver (remover um domínio). |
Quando o problema é do pedido
| HTTP | O que significa | O que fazer |
|---|---|---|
| 400 | Algum campo veio faltando, fora da faixa ou com valor que não existe — e também JSON malformado. | Corrigir e mandar de novo. O code diz qual campo. |
| 401 | A credencial não vale: ausente, inválida, vencida ou revogada. | Conferir o token. Repetir não resolve. |
| 402 | O seu plano não inclui esse recurso — hoje, o armazenamento de arquivos no plano gratuito. | Trocar de plano. Apagar arquivo não libera nada. |
| 403 | A credencial vale, mas não alcança: falta escopo, a conta está suspensa ou bloqueada, ou a cota do plano acabou. | Ver o code — cada caso pede uma ação diferente. |
| 404 | O recurso não existe ou não é seu. A API não distingue os dois casos. | Conferir o id. Não é um erro passageiro. |
| 409 | O recurso existe, mas está num estado que recusa essa operação: banco parado ou ocupado, restauração em curso, domínio já usado, aplicação sendo movida. | Esperar e tentar de novo, ou desfazer o conflito. |
| 413 | Grande demais: arquivo acima de 50 MB, consulta longa demais, ou espaço do plano esgotado. | Reduzir o envio, ou liberar espaço. |
| 415 | O tipo do arquivo não é aceito no armazenamento — executável, script ou algo que um servidor interpretaria. | Renomear não resolve: o conteúdo é conferido. |
| 429 | Teto de chamadas por minuto, por IP ou por token. | Recuar alguns segundos e tentar de novo. |
Quando o problema é nosso
| HTTP | O que significa | O que fazer |
|---|---|---|
| 500 | Algo falhou do nosso lado no meio da operação. | Tentar de novo; se persistir, falar com o suporte com o horário. |
| 501 | O recurso existe na plataforma, mas não está habilitado nesta instalação (por exemplo, domínio próprio). | Não adianta repetir — é configuração, não falha. |
| 502 | A máquina que hospeda o seu recurso não respondeu a tempo. | Quase sempre passageiro: repetir depois de alguns segundos. |
| 503 | A plataforma não conseguiu atender agora — capacidade ou um recurso indisponível no momento. | Repetir mais tarde; a página de status diz se é geral. |
Erros que qualquer rota pode devolver
| HTTP | Código | O que significa |
|---|---|---|
| 401 | API_TOKEN_INVALID | Token inexistente, malformado ou ausente. |
| 401 | API_TOKEN_REQUIRED | Veio a sessão do painel numa rota pública. |
| 401 | API_TOKEN_EXPIRED | O token passou da validade que você definiu. |
| 401 | API_TOKEN_REVOKED | O token foi revogado no painel. |
| 403 | MISSING_SCOPE | Falta um escopo. Qual, vem em params.required. |
| 403 | ACCOUNT_BLOCKED | A conta está bloqueada. Fale com o suporte. |
| 403 | ACCOUNT_SUSPENDED | Fatura vencida. Ler o plano e pagar continuam liberados. |
| 409 | MIGRATION_IN_PROGRESS | A aplicação está sendo movida durante uma manutenção. Leitura continua liberada. |
| 429 | TOO_MANY_REQUESTS | Teto de chamadas. Recue e tente de novo. |
| 500 | INTERNAL_ERROR | Falha não prevista. O detalhe fica no nosso log, não na resposta. |
Caminho que não existe responde diferente
{ "message": "404: Not Found", "code": 0 }), e não no envelope. Se a sua integração lê status e code sem conferir, é aqui que ela quebra: trate code: 0 como “essa rota não existe”.Conta suspensa
ACCOUNT_SUSPENDED. As de plano e pagamento continuam abertas, e apagar recurso também — quem quer reduzir custo para voltar a caber precisa conseguir apagar.Regra prática para repetir
429, 500, 502 e 503 valem repetir, com espera crescente entre as tentativas. Qualquer outro 4xx é sobre o pedido em si: repetir sem mudar nada devolve exatamente a mesma resposta.O que a API pública não faz
Quatro coisas ficaram de fora, e cada uma por um motivo diferente. Nenhuma delas é um “ainda não”:
- Movimentar dinheiro — assinar, trocar de plano, pagar fatura, cadastrar cartão. Ler o plano é útil para automação (
plan:read); autorizar uma cobrança a partir de um segredo guardado num CI é outra categoria de risco, e não há escopo aqui que a alcance. - Os fluxos que passam pelo navegador — conectar o GitHub, autorizar o seu provedor de DNS. Eles dependem de alguém aprovar numa página do outro serviço, e isso não cabe numa chamada automatizada. Faça pelo painel; depois disso, o resto é API.
- As rotas de administração da plataforma. Não há escopo que as alcance, nem para quem é administrador — elas existem só dentro do painel, com sessão.
- A edição de arquivos e o acompanhamento em tempo real. Os dois continuam sendo do painel por enquanto. Para automação, o equivalente é fazer um deploy novo e consultar
/deployse/logs.
Primeiros comandos
A primeira chamada de qualquer integração é a de identificação: ela não exige escopo nenhum e devolve quais escopos o token carrega — o que evita descobrir isso chamando rota por rota até uma parar de dar 403.
export NXC_TOKEN=nxc_seu_token_aqui export NXC_API=https://api.nexcloud.gg/v1/public # quem sou eu, e o que este token pode fazer curl -s "$NXC_API/account" -H "Authorization: Bearer $NXC_TOKEN" # o plano, os limites e o uso — numa chamada curl -s "$NXC_API/plan" -H "Authorization: Bearer $NXC_TOKEN" # as aplicações da conta, com o estado de cada uma curl -s "$NXC_API/apps" -H "Authorization: Bearer $NXC_TOKEN" # reiniciar uma delas curl -s -X POST "$NXC_API/apps/<app_id>/restart" \ -H "Authorization: Bearer $NXC_TOKEN"
2 rotas
Conta e plano
Quem é o dono do token, e o que o plano dele permite.
/v1/public/accountqualquer token válidoIdentifica a conta e devolve os escopos do token usado.
A única rota que não exige escopo — basta o token valer. Devolve o id do token, nunca o valor nem o prefixo: quem chama já tem o segredo na mão, e ecoá-lo só o colocaria em mais um log.
Resposta
{
"status": "success",
"response": {
"account": { "id": "local_8ebf…", "name": "Maria", "email": "[email protected]" },
"token": { "id": "tok_01H…", "scopes": ["apps:read", "apps:write"] }
}
}/v1/public/planplan:readPlano, limites e uso da conta, numa chamada só.
Limites e uso já somados, na mesma resposta — é a mesma conta que a plataforma usa para aceitar ou recusar um deploy, então o que ela diz que cabe é o que ela deixa criar. Continua respondendo com a conta suspensa.
Resposta
{
"status": "success",
"response": {
"plan": { "type": "standard", "label": "Standard", "billingStatus": "active", "expiresAt": "2026-10-01T00:00:00.000Z" },
"usage": {
"ram": { "limit": 4096, "used": 1536, "available": 2560 },
"applications": { "limit": 16, "used": 3 },
"databases": { "limit": 4, "used": 1 },
"blob": { "limit": 5120, "used": 210, "available": 4910, "files": 42 }
},
"breakdown": { "bots": [], "websites": [], "databases": [] }
}
}12 rotas
Workspaces
Compartilhar aplicações com outras contas, e quem alcança o quê.
/v1/public/workspacesworkspaces:readOs workspaces da conta e os que compartilharam com ela.
Um workspace não passa a ser dono de nada: a aplicação continua pertencendo a quem a criou, e é o plano dele que a paga. O que o workspace acrescenta é quem mais a alcança. Convite pendente não aparece aqui — quem ainda não aceitou não enxerga o workspace.
Resposta
{
"status": "success",
"response": {
"workspaces": [
{ "id": "3f1c…", "name": "Equipe de produto", "owner": true, "role": "owner", "members": 3, "apps": 2, "createdAt": "2026-09-01T12:00:00.000Z" }
]
}
}/v1/public/workspacesworkspaces:writeCria um workspace vazio.
Parâmetros
namecorpostringobrigatórioDe 2 a 48 caracteres.
Recusas
WORKSPACE_NAME_REQUIREDWORKSPACE_NAME_INVALIDWORKSPACE_LIMIT_REACHED/v1/public/workspaces/:idworkspaces:readO detalhe: as pessoas e as aplicações compartilhadas.
Parâmetros
idcaminhostringobrigatórioO workspace.
Resposta
{
"status": "success",
"response": {
"id": "3f1c…", "name": "Equipe de produto", "owner": true, "role": "owner",
"members": [
{ "id": "9a2b…", "email": "[email protected]", "name": "Maria", "role": "member", "pending": false, "acceptedAt": "2026-09-02T10:00:00.000Z" }
],
"apps": [
{ "id": "app_7c1…", "name": "checkout", "type": "website", "addedAt": "2026-09-01T12:30:00.000Z" }
]
}
}Recusas
WORKSPACE_NOT_FOUND/v1/public/workspaces/:idworkspaces:writeRenomeia o workspace.
Parâmetros
idcaminhostringobrigatórioO workspace.
namecorpostringobrigatórioO nome novo.
Recusas
WORKSPACE_NOT_FOUNDWORKSPACE_FORBIDDENWORKSPACE_NAME_INVALID/v1/public/workspaces/:idworkspaces:writeApaga o workspace. Só o dono.
As aplicações não são apagadas: elas continuam da conta que as criou, e apenas deixam de ser alcançáveis por quem estava no workspace.
Parâmetros
idcaminhostringobrigatórioO workspace.
Recusas
WORKSPACE_NOT_FOUND/v1/public/workspaces/:id/appsworkspaces:readAs aplicações que este workspace compartilha.
Parâmetros
idcaminhostringobrigatórioO workspace.
Recusas
WORKSPACE_NOT_FOUNDWORKSPACE_FORBIDDEN/v1/public/workspaces/:id/appsworkspaces:writeColoca uma aplicação no workspace.
Só aplicação da própria conta. Um administrador de workspace não repassa adiante uma aplicação que apenas lhe foi emprestada — isso tiraria do dono original o controle de quem alcança a aplicação dele, sem que ele ficasse sabendo.
Parâmetros
idcaminhostringobrigatórioO workspace.
app_idcorpostringobrigatórioA aplicação, que precisa ser sua.
Recusas
WORKSPACE_FORBIDDENAPP_NOT_FOUNDAPP_ALREADY_IN_WORKSPACEWORKSPACE_APP_LIMIT_REACHED/v1/public/workspaces/:id/apps/:app_idworkspaces:writeTira a aplicação do workspace.
Parâmetros
idcaminhostringobrigatórioO workspace.
app_idcaminhostringobrigatórioA aplicação.
Recusas
WORKSPACE_FORBIDDENAPP_NOT_IN_WORKSPACE/v1/public/workspaces/:id/membersworkspaces:readQuem está no workspace, e com que papel.
pending: true é convite emitido e não aceito — e não alcança aplicação nenhuma. O acesso passa a existir no aceite, não no convite.
Parâmetros
idcaminhostringobrigatórioO workspace.
Recusas
WORKSPACE_NOT_FOUNDWORKSPACE_FORBIDDEN/v1/public/workspaces/:id/membersworkspaces:writeConvida pelo e-mail cadastrado, e manda o link por e-mail.
O e-mail precisa já ter conta na plataforma: um endereço desconhecido responde USER_NOT_FOUND e nada é criado. A pessoa recebe um link de uso único, válido por 7 dias, e o acesso só existe depois que ela o abre — aceitar é ato do titular e por isso não tem rota na API pública.
Parâmetros
idcaminhostringobrigatórioO workspace.
emailcorpostringobrigatórioO e-mail cadastrado de quem você quer convidar.
rolecorpostringadmin,memberouviewer. O padrão éviewer.
Limite: 20 por minuto: cada chamada manda um e-mail.
Recusas
USER_NOT_FOUNDEMAIL_AMBIGUOUSCANNOT_INVITE_SELFMEMBER_ALREADY_INVITEDINVALID_WORKSPACE_ROLEWORKSPACE_MEMBER_LIMIT_REACHED/v1/public/workspaces/:id/members/:member_idworkspaces:writeTroca o papel de quem já está no workspace.
Parâmetros
idcaminhostringobrigatórioO workspace.
member_idcaminhostringobrigatórioO membro.
rolecorpostringobrigatórioadmin,memberouviewer.
Recusas
WORKSPACE_FORBIDDENMEMBER_NOT_FOUNDINVALID_WORKSPACE_ROLE/v1/public/workspaces/:id/members/:member_idworkspaces:writeRemove alguém do workspace.
O acesso cai na requisição seguinte: não há cache de associação, justamente para que revogar signifique revogar.
Parâmetros
idcaminhostringobrigatórioO workspace.
member_idcaminhostringobrigatórioO membro.
Recusas
WORKSPACE_FORBIDDENMEMBER_NOT_FOUND19 rotas
Aplicações
Criar, inspecionar e operar aplicações e websites.
/v1/public/appsapps:readLista as aplicações da conta com o estado atual de cada uma.
É a lista que responde “o que está no ar agora”, com o consumo do momento. Aplicação parada sai com running: false e sem números.
Resposta
{
"status": "success",
"response": [
{ "id": "app_01H…", "running": true, "ram": "128.44MB", "cpu": "0.6%" },
{ "id": "app_01J…", "running": false }
]
}/v1/public/appsapps:writeCria uma aplicação a partir de um pacote .zip.
multipart/form-data, com o arquivo e os campos de texto antes dele no corpo — é assim que o multipart os expõe. Os campos têm precedência sobre o arquivo de configuração do pacote, que é o que permite um zip sem configuração virar aplicação.
Parâmetros
filemultipartfile (application/zip)obrigatórioO pacote da aplicação.
namemultipartstringNome da aplicação no painel.
descmultipartstringDescrição livre.
rammultipartnumberMemória em MB. Mínimo 256 (aplicação) ou 512 (website).
domainmultipartstringRótulo do subdomínio, sem o domínio da plataforma. Mandar este campo é o que faz a carga ser um website — e exige plano com publicação na web.
A resposta vem assim que a aplicação é criada e o pacote é aceito. O build continua depois disso — acompanhe por /deploys, que diz em que passo ele está e como terminou.
Recusas
WEB_PUBLISH_NOT_ENABLEDINVALID_AGENT_RESPONSEAGENT_UNREACHABLE/v1/public/apps/githubapps:writeCria uma aplicação direto de um repositório do GitHub.
Exige a conta do GitHub conectada em Conexões. Com autoDeploy, cada push na branch escolhida dispara um deploy novo.
Parâmetros
repositorycorpostringobrigatóriodono/repositorio.branchcorpostringBranch de origem. Sem ela, a padrão do repositório.
namecorpostringobrigatórioNome da aplicação.
desccorpostringDescrição livre.
ramcorponumberobrigatórioMemória em MB.
domaincorpostringRótulo do subdomínio, para criar um website.
languagecorpostringForça o runtime em vez de detectar pela extensão do arquivo principal.
buildcorpostringComando de build, quando houver.
startcorpostringComando de start.
autoDeploycorpobooleanReimplantar a cada push na branch.
triggercorpostringO que dispara o deploy automático.
Recusas
AGENT_UNREACHABLEINVALID_AGENT_RESPONSE/v1/public/apps/:app_idapps:readDados cadastrais da aplicação.
status aqui é o estado da linha — provisioning enquanto o build acontece, failed quando ele não passou —, e não o do container. Para o container, use /status.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Resposta
{
"status": "success",
"response": {
"id": "app_01H…", "name": "api-loja", "desc": null,
"cluster": "node-3", "ram": 512, "language": "javascript",
"status": "running", "type": "website",
"domain": "loja.web.nexcloud.gg"
}
}Recusas
APP_NOT_FOUND/v1/public/apps/:app_idapps:writeAltera nome, descrição e autorestart.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
namecorpostringNovo nome.
desccorpostringNova descrição.
autorestartcorpobooleanReligar o container quando o processo morrer.
Domínio próprio não entra aqui: ele tem ciclo de vida próprio e rotas próprias — daí o USE_DOMAINS_ENDPOINT.
Recusas
APP_NOT_FOUNDINVALID_NAMEINVALID_AUTORESTARTNOTHING_TO_UPDATEUSE_DOMAINS_ENDPOINT/v1/public/apps/:app_idapps:writeApaga a aplicação.
O container morre e a cota é liberada; a linha fica marcada como apagada, com a data, quem pediu e o motivo. As snapshots vão junto.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
reasoncorpostringMotivo, opcional — fica no histórico da conta.
Recusas
APP_NOT_FOUNDCLUSTER_UNREACHABLE/v1/public/apps/:app_id/statusapps:readConsumo do container agora.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Resposta
{
"status": "success",
"response": {
"cpu": "0.60%", "ram": "128.44MB", "status": "running", "running": true,
"storage": "24.10MB",
"network": { "total": "1.20MB ↑ 8.40MB ↓", "now": "0B ↑ 2.10KB ↓" },
"uptime": 864000
}
}Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/metricsapps:readSérie de CPU, memória, rede e disco.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
rangequery1h | 6h | 24hJanela. Padrão
1h; valor desconhecido cai no padrão.
Resposta
{
"status": "success",
"response": {
"range": "1h",
"sampleIntervalMs": 60000,
"samples": [ { "t": 1788000000000, "cpu": 0.6, "ram": 128.4, "netTotal": 8400000, "netNow": 2100 } ]
}
}Container parado não rende amostra — registrar zero diria que ele rodou sem consumir nada, em vez de que não rodou.
Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/networkapps:readSe a aplicação está respondendo, e por qual caminho isso foi verificado.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/logsapps:readAs linhas recentes do console da aplicação.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/logs/daysapps:readOs dias que têm log guardado.
Chame antes de pedir o histórico: é a lista de datas válidas.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Resposta
{ "status": "success", "response": { "days": ["2026-09-01", "2026-08-31"] } }Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/logs/historyapps:readO log de um dia, com os eventos daquele dia intercalados.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
datequeryAAAA-MM-DDobrigatórioO dia pedido. Formato diferente é recusado.
Recusas
APP_NOT_FOUNDINVALID_DATE/v1/public/apps/:app_id/eventsapps:readO que aconteceu com a aplicação, do mais recente.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
perpagequerynumberQuantos eventos. Padrão e teto de 100.
Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/deploysapps:readAs tentativas de subir código, com passos e desfecho.
Guardado por 90 dias. Cada linha diz de onde veio (upload, github, redeploy), quem pediu, quanto demorou e em que passo parou — é a primeira coisa a olhar quando algo não subiu.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Resposta
{
"status": "success",
"response": {
"deploys": [{
"id": "dep_01H…", "kind": "app", "origin": "github", "actorKind": "user",
"status": "success", "code": null, "cluster": "node-3",
"ref": "main", "commit": "a1b2c3d", "bytes": 4210334, "files": 812,
"steps": [{ "name": "received", "at": "2026-09-02T12:00:01.000Z" }],
"startedAt": "2026-09-02T12:00:00.000Z",
"finishedAt": "2026-09-02T12:01:12.000Z",
"durationMs": 72000, "live": false
}]
}
}Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/startapps:writeSobe o container.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUNDMIGRATION_IN_PROGRESS/v1/public/apps/:app_id/stopapps:writePara o container. A cota continua reservada.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUNDMIGRATION_IN_PROGRESS/v1/public/apps/:app_id/restartapps:writeReinicia o container.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUNDMIGRATION_IN_PROGRESS/v1/public/apps/:app_id/memoryapps:writeTroca o limite de memória e recria o container.
O caminho da API usa /memory — o verbo já está no método. A rota equivalente do painel tem outro nome por razões históricas.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
memorycorponumberobrigatórioNova memória em MB.
As quatro recusas de memória têm códigos distintos de propósito: “abaixo do mínimo do tipo”, “acima do teto por container”, “acima do que sobra do plano” e “valor inválido” pedem ações diferentes de quem integrou.
Recusas
APP_NOT_FOUNDINVALID_MEMORY_VALUEMEMORY_BELOW_MINIMUMMEMORY_ABOVE_APP_LIMITMEMORY_ABOVE_PLAN_QUOTAMIGRATION_IN_PROGRESS/v1/public/apps/:app_id/redeployapps:writeRefaz o deploy do que já está vinculado, sem esperar um commit.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
4 rotas
Domínios
Domínio próprio de um website: adicionar, conferir e remover.
/v1/public/apps/:app_id/domainsdomains:readOs domínios da aplicação e o estado de cada um.
state é a chave que diz onde o domínio parou; reason é o código do motivo, e detail — quando existe — é o texto cru do provedor de DNS, para ser mostrado sem tradução. ownership traz o registro TXT quando ele ainda é necessário.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Resposta
{
"status": "success",
"response": [{
"id": "dom_01H…", "hostname": "loja.exemplo.com", "apex": false,
"state": "pending", "reason": "AWAITING_DNS", "detail": null, "actionable": true,
"ownership": { "type": "TXT", "name": "_cf-custom-hostname.loja", "value": "…" },
"createdAt": "2026-09-01T10:00:00.000Z", "verifiedAt": null
}]
}/v1/public/apps/:app_id/domainsdomains:writeAdiciona um domínio próprio ao website.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
hostnamecorpostringobrigatórioO domínio, sem esquema nem barra final.
Só vale para website — uma aplicação sem porta exposta não tem o que servir num domínio.
Recusas
HOSTNAME_TAKENDOMAIN_LIMIT_REACHEDCUSTOM_DOMAIN_NOT_CONFIGUREDCF_RECORD_EXISTS/v1/public/apps/:app_id/domains/:domain_id/verifydomains:writeReconsulta o estado do domínio agora.
Use depois de acertar o DNS, em vez de esperar a verificação periódica.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
domain_idcaminhostringobrigatórioId do domínio.
/v1/public/apps/:app_id/domains/:domain_iddomains:writeRemove o domínio da aplicação.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
domain_idcaminhostringobrigatórioId do domínio.
reasoncorpostringMotivo, opcional.
7 rotas
Snapshots
Cópias do disco da aplicação: criar, listar, baixar e restaurar.
/v1/public/snapshotssnapshots:readTodas as snapshots da conta, agrupadas por aplicação.
A paginação é por aplicação — um grupo é um cartão na tela —, e não por versão. Busca e ordenação rodam no servidor.
Parâmetros
pagequerynumberPágina de grupos.
perpagequerynumberGrupos por página, até 100.
qquerystringBusca pelo nome da aplicação.
sortquerystringOrdenação da lista de grupos.
/v1/public/apps/:app_id/snapshotssnapshots:readAs snapshots de uma aplicação.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/snapshotssnapshots:writeGera uma snapshot agora.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Limite: Duas por dia para cada 256 MB de RAM do plano, e um intervalo mínimo de 60 segundos entre duas criações da mesma aplicação.
Recusas
APP_NOT_FOUNDLIMIT_BACKUPSTOO_MANY_REQUESTSMIGRATION_IN_PROGRESS/v1/public/apps/:app_id/snapshots/restoresnapshots:readO andamento do restore em curso, se houver um.
Responde 200 com response: null quando não há restore nenhum — é um estado válido, e não um erro.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
Recusas
APP_NOT_FOUND/v1/public/apps/:app_id/snapshots/:snapshot_id/restoresnapshots:writeRestaura a aplicação a partir de uma snapshot.
Parâmetros
app_idcaminhostringobrigatórioId da aplicação.
snapshot_idcaminhostringobrigatórioId da snapshot.
Recusas
APP_NOT_FOUNDSNAPSHOT_NOT_FOUNDSNAPSHOT_APP_MISMATCHSNAPSHOT_INCOMPLETERESTORE_IN_PROGRESSRESTORE_TIMEOUTCLUSTER_UNREACHABLEPRESIGN_FAILED/v1/public/snapshots/:id/downloadsnapshots:readUma URL assinada para baixar a snapshot.
A URL é gerada na hora e vale por poucos minutos — tempo de baixar, não de guardar num script. Peça uma nova quando precisar de novo.
Parâmetros
idcaminhostringobrigatórioId da snapshot.
Recusas
SNAPSHOT_NOT_FOUNDSNAPSHOT_INCOMPLETEPRESIGN_FAILED/v1/public/snapshots/:idsnapshots:writeApaga uma snapshot.
Fica fora de /apps/:app_id/ porque a snapshot é um recurso da conta: apagar a aplicação já leva as dela junto, e esta rota trata do que sobrou.
Parâmetros
idcaminhostringobrigatórioId da snapshot.
Recusas
SNAPSHOT_NOT_FOUND15 rotas
Bancos de dados
Provisionar, operar e ler as credenciais de um banco gerenciado.
/v1/public/databases/enginesdatabases:readO catálogo de engines e versões disponíveis.
Chame antes de criar: é a lista que diz quais versões existem e qual é a recomendada de cada engine.
Resposta
{
"status": "success",
"response": [{
"key": "postgres", "label": "PostgreSQL",
"versions": ["17", "16", "15"], "recommended": "17",
"port": 5432, "urlScheme": "postgresql",
"envKey": "DATABASE_URL", "hasDatabaseName": true
}]
}/v1/public/databasesdatabases:readOs bancos da conta, com o estado ao vivo de cada um.
/v1/public/databasesdatabases:writeProvisiona um banco.
Responde 201 assim que o banco é criado e o endereço está reservado; o provisionamento termina em segundo plano. Acompanhe por /deploys do banco — só conecte quando ele estiver running.
Parâmetros
typecorpostringobrigatórioA chave do engine —
postgres,mysql,mariadb,mongo,redis,valkey.versioncorpostringVersão do catálogo. Sem ela, a recomendada.
namecorpostringobrigatórioNome do banco no painel.
ramcorponumberMemória em MB. Padrão 512, teto 32768.
Recusas
INVALID_ENGINEINVALID_VERSIONINVALID_DATABASE_NAMEBAD_MEMORYDATABASES_NOT_ALLOWEDDATABASE_LIMIT_REACHEDQUOTA_EXCEEDEDNO_NODE_AVAILABLEDATABASES_NOT_CONFIGUREDPROXY_PORT_EXHAUSTEDPROVISION_FAILEDTLS_FAILED/v1/public/databases/:db_iddatabases:readUm banco, com host, porta, volume e estado.
Sem a senha e sem o certificado: os dois têm rota própria, para um segredo não viajar em toda listagem.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Resposta
{
"status": "success",
"response": {
"id": "db_01H…", "name": "loja", "engine": "postgres", "version": "17",
"status": "running", "running": true, "health": "healthy",
"host": "db-01h….nexcloud.gg", "port": 25431,
"database": "loja", "user": "loja_app",
"cpu": 1, "ram": 1024, "storage": 2048, "cluster": "node-3",
"volume": "db_01h…", "volumePath": "/var/lib/postgresql/data",
"volumeRetentionDays": 7, "autoBackup": true, "tls": true,
"slowQueries": true, "lastBackupAt": "2026-09-01T03:00:00.000Z",
"createdAt": "2026-06-11T18:22:04.000Z"
}
}Recusas
DATABASE_NOT_FOUND/v1/public/databases/:db_iddatabases:writeApaga o banco. O volume vai para quarentena.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
reasoncorpostringMotivo, opcional.
Recusas
DATABASE_NOT_FOUNDCLUSTER_UNREACHABLEDATABASE_MIGRATING/v1/public/databases/:db_id/actiondatabases:writeStart, stop ou restart do engine.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
actioncorpostart | stop | restartobrigatórioA operação.
Recusas
DATABASE_NOT_FOUNDUNKNOWN_ACTIONDATABASE_BUSYDATABASE_MIGRATINGDATABASE_SUSPENDEDCLUSTER_UNREACHABLE/v1/public/databases/:db_id/logsdatabases:readO log do container do banco.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Recusas
DATABASE_NOT_FOUNDCLUSTER_UNREACHABLE/v1/public/databases/:db_id/metricsdatabases:readA série de consumo do banco.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
rangequery1h | 6h | 24hJanela. Padrão
1h.
Recusas
DATABASE_NOT_FOUND/v1/public/databases/:db_id/connectionsdatabases:readQuem está conectado agora, e o teto configurado.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Recusas
DATABASE_NOT_FOUNDDATABASE_STOPPED/v1/public/databases/:db_id/connectionsdatabases:writeTroca o teto de conexões do engine.
Recria o container: max_connections é opção de start, e um restart reusaria os mesmos argumentos. O volume é preservado.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
maxConnectionscorponumberobrigatórioDentro da faixa que a tela do banco mostra: o mínimo é 25 e o teto acompanha a memória contratada.
Limite: 5 por minuto.
Recusas
DATABASE_NOT_FOUNDINVALID_CONNECTION_LIMITCONNECTION_LIMIT_OUT_OF_RANGEDATABASE_BUSY/v1/public/databases/:db_id/ca.pemdatabases:readO certificado da CA da plataforma.
É o mesmo para todos os bancos — é a CA da plataforma, não a do banco —, e é ele que permite verificar o servidor de verdade em vez de aceitar qualquer certificado.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Recusas
DATABASE_NOT_FOUNDDATABASE_WITHOUT_TLS/v1/public/databases/:db_id/deploysdatabases:readO provisionamento do banco, passo a passo.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Recusas
DATABASE_NOT_FOUND/v1/public/databases/:db_id/credentialsdatabases:credentialsUsuário, senha em claro e a connection string.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Resposta
{
"status": "success",
"response": {
"host": "db-01h….nexcloud.gg", "port": 25431,
"user": "loja_app", "password": "…", "database": "loja",
"uri": "postgresql://loja_app:…@db-01h….nexcloud.gg:25431/loja?sslmode=verify-full"
}
}Limite: 30 por minuto — cada chamada é um segredo saindo.
Recusas
DATABASE_NOT_FOUNDCREDENTIALS_UNREADABLE/v1/public/databases/:db_id/envdatabases:credentialsAs variáveis de ambiente do banco, em dois grupos.
O que está dentro do container, e o que a plataforma monta para a sua aplicação ler.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Limite: 30 por minuto.
Recusas
DATABASE_NOT_FOUNDCREDENTIALS_UNREADABLE/v1/public/databases/:db_id/credentials/rotatedatabases:credentialsGera uma senha nova para o banco.
As aplicações vinculadas têm a variável reescrita e são reiniciadas. Quem conecta com a senha antiga de fora perde acesso na hora — é o ponto.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Limite: 5 por minuto.
Recusas
DATABASE_NOT_FOUNDCREDENTIALS_UNREADABLEDATABASE_BUSYCLUSTER_UNREACHABLE6 rotas
Dados do banco
Tabelas, linhas e console SQL. Exige `databases:sql`, que é sensível.
/v1/public/databases/:db_id/tablesdatabases:sqlAs tabelas do banco — ou as chaves, no Redis e no Valkey.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
cursorquerystringSó em Redis e Valkey: o cursor do
SCAN. Começa em0.
Recusas
DATABASE_NOT_FOUNDDATABASE_STOPPEDCREDENTIALS_UNREADABLE/v1/public/databases/:db_id/tables/:tabledatabases:sqlAs linhas de uma tabela, paginadas, com o esquema e a chave primária.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
tablecaminhostringobrigatórioNome da tabela, ou a chave no Redis.
pagequerynumberPágina.
perpagequerynumberLinhas por página, até 100.
qquerystringTermo de busca.
colquerystringColuna onde buscar. Sem ela, a busca é ampla.
onlyqueryrowsPula o esquema e a contagem. É o que um refresh automático deve usar: o
count(*)de uma tabela grande é varredura completa.
Recusas
DATABASE_NOT_FOUNDTABLE_NOT_FOUNDDATABASE_STOPPED/v1/public/databases/:db_id/tables/:table/rowsdatabases:sqlInsere uma linha.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
tablecaminhostringobrigatórioNome da tabela.
valuescorpoobjectobrigatórioColuna → valor. As colunas são conferidas contra o esquema real.
Limite: 60 por minuto.
Recusas
TABLE_NOT_FOUNDWRITE_REJECTEDREDIS_INSERT_UNSUPPORTED/v1/public/databases/:db_id/tables/:table/rowsdatabases:sqlAltera uma linha.
O WHERE é montado com a chave primária inteira, lida do banco no momento da escrita — é o que garante, pelo próprio engine, que no máximo uma linha é atingida.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
tablecaminhostringobrigatórioNome da tabela.
wherecorpoobjectobrigatórioA chave primária da linha, coluna → valor.
valuescorpoobjectobrigatórioAs colunas a alterar.
Limite: 60 por minuto.
Recusas
ROW_NOT_FOUNDKEY_NOT_EDITABLEWRITE_REJECTED/v1/public/databases/:db_id/tables/:table/rowsdatabases:sqlApaga uma linha.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
tablecaminhostringobrigatórioNome da tabela.
wherecorpoobjectobrigatórioA chave primária da linha.
Limite: 60 por minuto.
Recusas
ROW_NOT_FOUNDWRITE_REJECTED/v1/public/databases/:db_id/querydatabases:sqlRoda um comando no banco.
O comando não é validado nem reescrito — é o mesmo poder que a connection string já dá a quem tem o banco. O que limita é a posse, o teto de tempo do engine e o teto de saída.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
sqlcorpostringobrigatórioO comando. No Mongo e no Redis, a sintaxe é a do próprio engine.
Limite: 120 por minuto.
Recusas
EMPTY_QUERYQUERY_TOO_LONGDATABASE_STOPPEDINVALID_ENGINE9 rotas
Backups e vínculos
Cópias do banco e a variável de ambiente que liga um banco a uma aplicação.
/v1/public/databases/:db_id/backupsdatabases:readOs backups do banco, do mais recente.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Resposta
{
"status": "success",
"response": [{
"id": "bkp_01H…", "size": 4823110, "engine": "postgres",
"state": "ready", "error": null, "origin": "auto",
"createdAt": "2026-09-01T03:00:00.000Z",
"expiresAt": "2026-09-08T03:00:00.000Z"
}]
}Recusas
DATABASE_NOT_FOUND/v1/public/databases/:db_id/backupsdatabases:writeGera um backup agora.
Síncrona de propósito: um dump termina em segundos na maioria dos bancos, e devolver o resultado direto poupa um segundo estado para acompanhar.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Limite: 6 por minuto.
Recusas
DATABASE_NOT_FOUNDDATABASE_STOPPEDCLUSTER_UNREACHABLECREDENTIALS_UNREADABLE/v1/public/databases/:db_id/backupsdatabases:writeLiga ou desliga o backup automático.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
autoBackupcorpobooleanobrigatórioO novo estado.
Recusas
DATABASE_NOT_FOUNDINVALID_PAYLOAD/v1/public/databases/:db_id/backups/:backup_id/downloaddatabases:readUma URL assinada para baixar o dump.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
backup_idcaminhostringobrigatórioId do backup.
Recusas
BACKUP_NOT_FOUNDPRESIGN_FAILED/v1/public/databases/:db_id/backups/:backup_iddatabases:writeApaga um backup.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
backup_idcaminhostringobrigatórioId do backup.
Recusas
BACKUP_NOT_FOUND/v1/public/databases/:db_id/restoredatabases:writeRestaura o banco a partir de um backup.
Sobrescreve e tem indisponibilidade. Os comandos de restauração derrubam e recriam os objetos — aplicar um dump por cima de dados existentes daria conflito de chave em qualquer engine.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
backupIdcorpostringobrigatórioO backup a restaurar.
origincorpostringDe onde partiu o pedido, para o histórico.
Limite: 3 por minuto.
Recusas
BACKUP_NOT_FOUNDDATABASE_NOT_FOUNDDATABASE_STOPPEDCLUSTER_UNREACHABLE/v1/public/databases/:db_id/linksdatabases:readAs aplicações vinculadas a este banco.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
Recusas
DATABASE_NOT_FOUND/v1/public/databases/:db_id/linksdatabases:writeVincula uma aplicação, escrevendo a variável no .env dela.
A aplicação é reiniciada só se o arquivo mudou — vincular duas vezes o mesmo banco não derruba nada.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
appIdcorpostringobrigatórioA aplicação a vincular.
envKeycorpostringNome da variável. Sem ele, o padrão do engine (
DATABASE_URLno Postgres).
Resposta
{
"status": "success",
"response": { "appId": "app_01H…", "appName": "api-loja", "envKey": "DATABASE_URL", "restarted": true }
}Recusas
APP_NOT_FOUNDDATABASE_NOT_FOUNDLINK_EXISTSINVALID_ENV_KEYCREDENTIALS_UNREADABLE/v1/public/databases/:db_id/links/:app_iddatabases:writeDesvincula a aplicação e remove a variável.
Parâmetros
db_idcaminhostringobrigatórioId do banco.
app_idcaminhostringobrigatórioA aplicação vinculada.
Recusas
LINK_NOT_FOUNDDATABASE_NOT_FOUND5 rotas
Blob storage
Arquivos públicos servidos por CDN, com URL imutável.
/v1/public/blobblob:readOs arquivos da conta, paginados, com o uso da cota.
O uso volta em toda resposta: buscá-lo numa segunda chamada faria a barra de cota piscar desencontrada da lista.
Parâmetros
pagequerynumberPágina.
perpagequerynumberArquivos por página. Padrão 24, teto 100.
qquerystringBusca pelo nome do arquivo.
sortquerysizeOrdena por tamanho. Sem ele, do mais recente.
Resposta
{
"status": "success",
"response": {
"page": 1, "limit": 24, "perpage": 24, "total": 42, "pages": 2,
"usage": { "limit": 5368709120, "used": 220200960, "available": 5148508160, "files": 42 },
"objects": [{
"id": "b1f0…", "filename": "logo.png", "contentType": "image/png",
"size": 20481, "createdAt": "2026-08-20T12:00:00.000Z",
"url": "https://cdn.nexcloud.gg/blob/b1f0….png"
}]
}
}/v1/public/blob/:id/detailsblob:readConfere o arquivo no armazenamento, e não o registro dele.
É a chamada que diz se o arquivo realmente está lá, qual é o tamanho real e qual é o tipo de verdade — o .png que é um JPEG por dentro aparece aqui. Por ser mais cara que a listagem, tem teto próprio.
Parâmetros
idcaminhostringobrigatórioId do arquivo.
Limite: 60 por minuto.
Recusas
BLOB_NOT_FOUND/v1/public/blobblob:writeEnvia um arquivo e o publica no CDN.
multipart/form-data com um arquivo. A resposta traz o objeto — com a URL pública — e o uso da cota já atualizado.
Parâmetros
filemultipartfileobrigatórioO arquivo. Máximo de 50 MB.
Executáveis e arquivos interpretáveis por servidor são recusados por extensão e pelos primeiros bytes — renomear não contorna.
BLOB_NOT_IN_PLAN e BLOB_QUOTA_EXCEEDED são recusas diferentes: a primeira é “seu plano não inclui blob”, e apagar arquivo não resolve.
Recusas
NO_FILEFILE_TOO_LARGEEMPTY_FILEBLOB_NOT_IN_PLANBLOB_QUOTA_EXCEEDEDBLOB_UPLOAD_FAILED/v1/public/blob/:idblob:writeApaga um arquivo do CDN e libera a cota.
Parâmetros
idcaminhostringobrigatórioId do arquivo.
Recusas
BLOB_NOT_FOUNDBLOB_DELETE_FAILED/v1/public/blobblob:writeApaga todo o blob storage da conta.
Não há confirmação no protocolo — o método e o caminho já dizem o que a chamada faz. Quem confirma é a interface que a chamar.