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 ou API key da organização e o contexto x-organization-id. 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 conforme o fluxo de autenticação usado pela sua integração. Inclua x-organization-id nas chamadas autenticadas. 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. Um template que cria banco também exige database.create em organization:*; um template que cria cache ou queue exige managed_service.create em organization:*.
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, ordenados pela última atualização. public retorna templates publicados. 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.
Referências públicas são aceitas para Docker Hub, GHCR, Quay e GitLab Registry. A Zenifra valida a aplicação antes de aceitar a revisão. Não envie credenciais, tokens ou valores secretos no template.
Cada edição exige expected_revision e 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 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.
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. Respeite respostas 429 e aguarde antes de tentar novamente.