Templates API
A API de Templates permite consultar o catálogo público ou o catálogo da organização ativa, criar e revisar pontos de partida para aplicações HTTP e iniciar um projeto com uma revisão específica. As rotas de gerenciamento exigem autenticação de usuário (com o contexto x-organization-id) ou API key da organização. A listagem pública oficial possui uma rota separada sem autenticação.
Autenticação e contexto
Envie um token de usuário no header Authorization com o esquema Bearer ou uma API key de organização (x-api-key ou Authorization: Bearer znf_...). Com token de usuário, inclua x-organization-id; com API key da organização, a organização vem da própria chave. A organização ativa define os templates privados e o destino de um novo projeto.
Authorization: Bearer <token>
x-organization-id: <organization-id>
Content-Type: application/jsonGET /v1/public/templates é a única rota desta referência que não exige Authorization nem x-organization-id. Ela serve somente para consultar o catálogo oficial público. Criar projetos ou alterar templates continua exigindo autenticação e as permissões correspondentes.
Permissões necessárias
Use somente o scope da ação e o ID do template quando a operação for sobre um template específico:
| Ação | Scope mínimo |
|---|---|
| Listar ou visualizar template | template.read em template:<template-id>; templates públicos seguem o contrato público |
| Criar template privado | template.create em organization:* |
| Editar template | template.update em template:<template-id> |
| Publicar ou tornar privado | template.publish em template:<template-id> |
| Remover template | template.delete em template:<template-id> |
| Criar projeto a partir do template | template.read em template:<template-id> e o scope de criação do projeto correspondente |
owner tem acesso completo na sessão de usuário. assistant, member e API Keys da organização precisam dos grants específicos. A criação conjunta de aplicação e banco também exige database.create em organization:*. Templates não criam Key-Value, Cache ou Queue.
Listar o catálogo público oficial
Use esta rota em sites, vitrines e outras integrações que precisam exibir Templates oficiais sem abrir uma sessão de usuário:
GET /v1/public/templates?sort=most_used&page=1&limit=12Não envie Authorization nem x-organization-id nessa chamada.
| Parâmetro | Obrigatório | Valores e padrão |
|---|---|---|
sort | Não | most_used (padrão), newest ou updated |
page | Não | Página iniciando em 1; padrão 1 |
limit | Não | De 1 a 24 itens; padrão 12 |
A resposta inclui apenas Templates públicos e ativos de organizações oficiais ativas. most_used ordena por organizações consumidoras únicas, depois por implantações concluídas e data de criação. newest usa a data de criação; updated usa a última atualização. A ordenação possui desempate determinístico para manter a paginação estável.
Cada item público contém somente id, name, summary, description, tags, official, author.organization_name, requires_database e updated_at. Configuração da aplicação, variáveis, padrões de plano, dados de uso e identificadores da organização não fazem parte deste contrato.
Exemplo de estrutura da resposta:
{
"status": "success",
"data": {
"items": [
{
"id": "507f1f77bcf86cd799439011",
"name": "API de atendimento",
"summary": "Ponto de partida para uma API HTTP.",
"description": "Template oficial para iniciar uma API.",
"tags": ["api"],
"official": true,
"author": {
"organization_name": "Zenifra"
},
"requires_database": true,
"updated_at": "2026-09-03T12:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 12,
"total": 1,
"pages": 1
}
}
}Listar templates com autenticação
GET /v1/templates?scope=organization&sort=updated&page=1&limit=20| Parâmetro | Obrigatório | Valores |
|---|---|---|
scope | Sim | organization ou public |
sort | Sim | updated, newest ou most_used |
official | Não | true ou false; disponível com scope=public |
page | Não | Página iniciando em 1 |
limit | Não | Até 50 itens |
organization retorna templates acessíveis na organização ativa e public retorna templates publicados. A ordem segue sort: updated usa a última atualização, newest a data de criação e most_used usa organizações consumidoras únicas como critério principal e deploys concluídos como desempate. Use official=true para retornar somente Templates publicados pela Zenifra ou por parceiros oficiais.
Cada Template retornado informa apenas o nome público da organização autora. O identificador da organização não é compartilhado. owned_by_current_organization indica se o Template pertence à organização ativa, enquanto official informa se a autora é uma publicadora oficial. Os dois campos são informativos e não concedem permissões.
{
"author": {
"organization_name": "Organização autora"
},
"owned_by_current_organization": false,
"official": true
}Obter, criar e editar
GET /v1/templates/:id
POST /v1/templates
PATCH /v1/templates/:idO corpo de criação e edição contém name, summary, description, tags, application, variables e defaults. A aplicação informa reference, port e storage_path; os padrões informam plano, cobrança, exposição, instâncias, auto-scaling e storage. Um template que precisa de banco também pode incluir opcionalmente database_dependency.
Use uma referência completa de imagem pública em um registro compatível com OCI, com domínio, caminho e tag, por exemplo codeberg.org/forgejo/forgejo:16.0.5. Docker Hub, GHCR, Quay e GitLab Registry continuam aceitos. A Zenifra valida a aplicação antes de aceitar a revisão; o registro deve responder por HTTPS e permitir acesso público à imagem. Não envie credenciais, tokens ou valores secretos no template.
Cada edição exige expected_revision:
{
"expected_revision": 2,
"name": "atendimento-api v2",
"summary": "API HTTP para novos projetos",
"description": "Um ponto de partida seguro para uma API.",
"tags": ["api", "atendimento"],
"application": {
"reference": "ghcr.io/example/support:2.1.0",
"port": 3000,
"storage_path": "/app/data"
},
"variables": [
{ "name": "APP_ENV", "description": "Ambiente", "required": true, "secret": false, "default_value": "production" },
{ "name": "APP_SECRET", "description": "Segredo da aplicação", "required": true, "secret": true }
],
"defaults": {
"plan": "basic",
"payment_mode": "monthly",
"exposure": "public",
"instances": 1,
"storage": { "persistent": true, "capacity": 10 }
}
}Uma revisão antiga retorna 409 Conflict. Variáveis secretas não podem ter default_value.
Dependência de banco
Consulte o catálogo atual antes de criar ou editar uma dependência:
GET /v1/project/database/catalogA resposta lista IDs de mecanismos, planos, formas de cobrança, campos de configuração e campos de conexão. Use esses IDs em vez de manter uma lista fixa na sua integração. database_dependency declara mecanismos compatíveis, uma recomendação para cada mecanismo e vínculos opcionais de variáveis:
{
"database_dependency": {
"compatible_engine_ids": ["postgresql", "mariadb"],
"recommended_engine_id": "postgresql",
"recommendations": [
{ "engine_id": "postgresql", "plan_id": "db-basic", "payment_mode": "monthly", "configuration": { "version": "18", "instances": 1, "storage_capacity_gb": 10 } },
{ "engine_id": "mariadb", "plan_id": "db-basic", "payment_mode": "monthly", "configuration": { "version": "11", "instances": 3, "storage_capacity_gb": 10 } }
],
"environment_bindings": [
{ "variable_name": "DB_PASSWORD", "connection_field_id": "password" },
{ "variable_name": "DB_HOST", "connection_field_id": "host" }
]
}
}Cada vínculo deve apontar para uma variável declarada e para um campo de conexão suportado por todos os mecanismos compatíveis. Vínculos de campos sensíveis exigem variável secreta e não podem ter valor padrão. Vínculos não sensíveis podem fornecer um valor sugerido para banco externo; a criação conjunta o substitui pelos dados da nova conexão. Omitir database_dependency cria um template sem dependência de banco. Na edição, omita o campo para preservar a dependência atual ou envie null para removê-la.
Publicar e remover
PATCH /v1/templates/:id/visibility
DELETE /v1/templates/:idO corpo de visibilidade é { "visibility": "public", "expected_revision": 2 }. A criação começa privada. Publicar ou tornar privado exige template.publish; remoção exige template.delete e expected_revision. A remoção é lógica e não altera projetos já criados.
Criar projeto por template
Use o payload alternativo de POST /v1/project:
{
"template_id": "507f1f77bcf86cd799439011",
"template_revision": 2,
"name": "atendimento-api",
"description": "Projeto criado a partir de um template",
"plan": "basic",
"payment_mode": "monthly",
"config": {
"exposure": "public",
"instances": 1,
"storage": { "persistent": true, "capacity": 10 },
"envs": [
{ "name": "APP_ENV", "value": "production" },
{ "name": "APP_SECRET", "value": "valor-informado-no-deploy" }
],
"network_access": {
"ingress_white_list": [{ "cidr": "0.0.0.0/0", "description": "Acesso ao projeto" }],
"ingress_black_list": []
}
}
}A aplicação, porta, tipo HTTP e pasta persistente vêm da revisão do template. O request deve conter exatamente as variáveis declaradas. A implantação exige project.create e, para template privado, template.read. Falhas não contam uso nem alteram o ranking.
Criar aplicação e banco juntos
Para um template com dependência de banco, crie os dois recursos com:
POST /v1/templates/:id/deployments
Idempotency-Key: <chave-unica-com-ao-menos-16-caracteres>O Idempotency-Key é obrigatório e aceita de 16 a 200 caracteres (A-Z, a-z, 0-9, ., _ e -).
O corpo inclui expected_revision, a configuração habitual da aplicação e o banco selecionado:
{
"expected_revision": 2,
"application": { "name": "atendimento-api", "plan": "basic", "payment_mode": "monthly", "config": { "exposure": "public", "instances": 1, "storage": { "persistent": true, "capacity": 10 }, "envs": [{ "name": "APP_ENV", "value": "production" }], "network_access": { "ingress_white_list": [], "ingress_black_list": [] } } },
"database": { "name": "atendimento-db", "engine_id": "postgresql", "plan_id": "db-basic", "payment_mode": "monthly", "configuration": { "version": "18", "instances": 1, "storage_capacity_gb": 10 } }
}A chamada exige project.create e database.create. A resposta contém apenas ID e estado da implantação, além dos IDs dos projetos; nunca contém credenciais de conexão. Reutilize a mesma chave de idempotência e corpo idêntico para tentar novamente com segurança. Um corpo diferente com a mesma chave retorna 409 Conflict.
GET /v1/template-deployments/:deploymentIdUse esse endpoint para acompanhar creating, ready, rolling_back ou failed. Banco e aplicação criados com sucesso continuam sendo projetos independentes.
Se a resposta da criação se perder, recupere a implantação pela chave idempotente da organização:
GET /v1/template-deployments/idempotency/:idempotencyKeyA resposta tem o mesmo formato da consulta por deploymentId; retorna 404 quando não há implantação legível com essa chave.
Limites
O catálogo público oficial tem limite de 120 requisições por minuto por IP. Leituras autenticadas têm limite de 100 requisições por minuto. Criação e edição têm limite de 10 por minuto. Publicação e remoção têm limite de 5 por minuto. POST /v1/templates/:id/deployments tem limite de 5 por minuto, e GET /v1/template-deployments/* de 60 por minuto. Respeite respostas 429 e aguarde antes de tentar novamente.
Próximos passos
Última atualização em
Ambientes de Preview — API
Referência da API pública para habilitar, consultar, publicar e remover Ambientes de Preview de um projeto HTTP.
Bancos de dados pela API
Consulte estado e conexão de bancos PostgreSQL, MariaDB e ClickHouse, renove a senha, atualize a versão e liste aplicações vinculadas pela API.