Páginas: o JSON do documento v2

Guia completo para criar, editar e publicar páginas por API (e por agentes de IA): modelo mental, todos os campos de todos os itens, validação e erros, mídia, fluxos seguros, receitas e prompt pronto.

Documento de página v2: guia completo para agentes

Este guia ensina uma pessoa ou um agente de IA a ler, criar, editar e publicar páginas e formulários do Asender Pages pela API pública, produzindo o JSON do documento v2 certo na primeira tentativa. As tabelas de campos, limites e tipos são geradas do JSON Schema do contrato (asender_docs/contratos/pages-documento-v2.schema.json), o mesmo que os validadores Go (autoridade, roda no servidor) e TypeScript (roda no editor) provam concordar; por isso elas não envelhecem. Tudo que aparece em JSON aqui foi validado nos três lados.

Regra de ouro para agentes: o servidor é a autoridade. Valide localmente contra o schema, envie, e se vier 422 leia codigo e caminho (seção 4), corrija só aquele nó e reenvie. Nunca invente campo: campo desconhecido é recusado.

1. Início rápido para agentes

1.1 Credenciais: o que cada uma alcança

Um agente externo trabalha com uma API key (sk_live_... / sk_test_...), criada pelo dono da conta em Desenvolvedores → Chaves de API com os escopos mínimos da tarefa. A conta é sempre a da chave (validada no servidor a cada chamada; chave revogada para na hora): nenhum header nem campo do corpo escolhe a conta, e um tenant_id no corpo é recusado. Página, rascunho, mídia ou domínio de outra conta responde 404, igual a um id que não existe.

Escopo da chaveO que permite
pages:readler: GET /v1/paginas, GET /v1/paginas/{id}, GET /v1/paginas/{id}/rascunho, GET /v1/paginas/{id}/seo, GET /v1/dominios, GET /v1/midias
pages:writecriar e editar, sem publicar: POST /v1/paginas, POST /v1/paginas/{id}/versoes, PUT/DELETE /v1/paginas/{id}/rascunho, PUT /v1/paginas/{id}/seo, POST /v1/paginas/importar, POST /v1/paginas/{id}/midias/copiar, PUT /v1/paginas/{id}/dominio, POST /v1/paginas/lote com duplicar/mudar_dominio, POST /v1/midias, POST /v1/midias/de-url
pages:publishpublicar e despublicar (o ato visível ao público e indexável): POST /v1/paginas/{id}/publicar e POST /v1/paginas/lote com publicar/despublicar
forms:read / forms:writeformulários e o envio de leads (seção 3.8)

Os escopos não se implicam: pages:write não lê (precisa de pages:read para listar) nem publica. Um agente que cria, confere e publica precisa dos três. Sem o escopo da rota, 403 ({"erro":"a chave não tem o escopo pages:publish"}); rota que não aceita chave, 401. A sessão OIDC de uma pessoa (Authorization: Bearer <token-de-sessão> + X-Asender-Tenant: <slug-da-conta>) continua alcançando tudo de autoria e é o que o painel usa; a chave não alcança editar slug/título (PATCH), testes A/B, roteamento, apagar mídia, SEO do site, redirects nem marca.

Regras que protegem o trabalho de pessoas (valem só para chave):

Os exemplos usam $KEY (a API key) e $API; o mesmo curl funciona com sessão trocando o header.

export API=https://api.pages.asender.net
export KEY='sk_live_...'        # escopos: pages:read pages:write pages:publish
H=(-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json')
# Com sessão de pessoa: -H "Authorization: Bearer $TOKEN" -H "X-Asender-Tenant: $CONTA"

1.2 O documento mínimo válido

{ "versao": 2, "secoes": [ { "id": "a", "colunas": [ { "id": "ac", "itens": [] } ] } ] }

Uma seção, uma coluna, zero itens. Com um título:

{
  "versao": 2,
  "secoes": [
    { "id": "s1", "colunas": [
      { "id": "s1c1", "itens": [
        { "id": "s1c1i1", "tipo": "titulo", "props": { "texto": "Olá, mundo", "nivel": 1 } }
      ] }
    ] }
  ]
}

Todo item tem id, tipo e props (objeto, pode ser {}).

1.3 Criar, editar e publicar (o caminho feliz)

# 1) criar a página (nasce DESPUBLICADA, com a versão 1 = o template enviado)
curl -sS -X POST "$API/v1/paginas" "${H[@]}" -d '{
  "titulo": "Lançamento",
  "slug": "lancamento",
  "template": { "versao": 2, "secoes": [ { "id": "s1", "colunas": [ { "id": "s1c1", "itens": [
    { "id": "t1", "tipo": "titulo", "props": { "texto": "Olá, mundo", "nivel": 1 } } ] } ] } ] }
}'
# -> 201 { "id":"<pagina-id>", "slug":"lancamento", "dominio":"<conta>.apages.xyz", "titulo":"Lançamento",
#          "versao_publicada":0, "ultima_versao":1, "url_publica":"https://<conta>.apages.xyz/lancamento" }

# 2) salvar uma NOVA versão (cada POST cria a versão seguinte; nada é sobrescrito)
curl -sS -X POST "$API/v1/paginas/<pagina-id>/versoes" "${H[@]}" -d @corpo-versao.json   # {"template": {...}}
# -> 201 { "versao": 2 }     |  422 { "erro":"...", "codigo":"ErrPropInvalida", "caminho":"secoes[0]..." }

# 3) publicar UMA versão, pelo número (chave: escopo pages:publish e `versao` obrigatória)
curl -sS -X POST "$API/v1/paginas/<pagina-id>/publicar" "${H[@]}" -d '{ "versao": 2 }'
# -> 200 { "versao_publicada": 2 }

# Rascunho (auto-save, sem versão): leia o rascunho_em e devolva em ?base= (obrigatório com chave)
curl -sS "$API/v1/paginas/<pagina-id>/rascunho" "${H[@]}"            # -> 200 {template, rascunho_em} | 204
curl -sS -X PUT "$API/v1/paginas/<pagina-id>/rascunho?base=<rascunho_em>" "${H[@]}" -d '{"template": {...}}'
# -> 200 { "rascunho_em": "..." } | 409 RascunhoConflito (com o rascunho do servidor) | 428 sem ?base=

Sem template no POST /v1/paginas, a página nasce com um documento inicial (uma seção hero com o título digitado). Corpo máximo: 512 KiB.

1.4 O endereço da página e o domínio padrão

Toda conta tem um domínio padrão num subdomínio de apages.xyz (ex.: minhaconta.apages.xyz). Uma página criada sem dominio nasce nele; a url_publica da resposta é o endereço para abrir. Para usar outro domínio (um próprio, já verificado), crie/atualize a página com dominio ou, depois, mova com PUT /v1/paginas/{id}/dominio (API key pages:write):

curl -sS "$API/v1/dominios" "${H[@]}"          # pages:read, o padrão vem primeiro
curl -sS -X PUT "$API/v1/paginas/<pagina-id>/dominio" "${H[@]}" -d '{ "dominio_id": "<id>", "caminho": "novo-slug" }'

Detalhes (301 do endereço antigo, erros 409/422) na seção 6.5.

1.5 Antes de gerar JSON

  1. Escolha a estrutura (seção 2) e os tipos de item (seção 3.1).
  2. Gere ids únicos no documento inteiro (sugestão: s1, s1c1, s1c1i1...).
  3. Use somente os campos das tabelas da seção 3; tudo que não está lá é recusado.
  4. Imagens: URL da galeria da conta ou https:// externa (seção 5).
  5. Valide contra o schema, envie, leia o 422 se vier (seção 4).

2. Modelo mental

documento (versao: 2)
 |- configuracoes   (livre, passthrough)
 |- estilo          (a PÁGINA: tema, fundo, textura, fontes, caixa do conteúdo)
 '- secoes[]        (faixas horizontais, de cima para baixo)
     '- colunas[]   (células lado a lado dentro da seção)
         '- itens[] (objetos atômicos: titulo, texto, imagem, botao...)
              '- abas / acordeao: painéis com itens aninhados (um único nível)

Responsividade. Os pontos de quebra são fixos: celular até 767 px, tablet 768 a 1023 px, computador a partir de 1024 px. No celular as colunas empilham (layout_celular: empilhar, o padrão) ou ficam lado a lado (manter); inverter_celular inverte a ordem da pilha. padding_celular e espacador.altura_celular ajustam o respiro no celular. ocultar_em (seção ou item) esconde por dispositivo. Não há CSS livre: tudo é campo fechado.

Ids. ^[A-Za-z0-9_-]{1,64}$, únicos no documento inteiro: seção, coluna, item e os itens dentro de painéis dividem o mesmo espaço (um item de painel com o id de uma seção é ErrID). Âncoras (secao.ancora): ^[a-z][a-z0-9-]{0,63}$, únicas na página; viram o id HTML da seção e o alvo de #ancora em botões e menus.

Ordem e tamanho. As seções são renderizadas na ordem do array. Tetos importantes: 200 seções, 12 colunas por seção, 100 itens por coluna, 1000 itens por página (contando os de painéis). Tabela completa na seção 3.

Versões do formato. Só o versao: 2 deve ser escrito. O formato v1 (lista plana de blocos) ainda é lido, mas está em saída; não gere v1.

Normalização. O servidor valida e regrava o documento na forma canônica; o que você lê de volta pode ter a ordem das chaves diferente do que enviou.

3. Referência de campos

Tudo nesta seção vem do schema. Convenções das tabelas: Tipo é o tipo JSON; "cor" e "url de mídia" são tipos nomeados (seção 3.4); Padrão é o que o renderer aplica quando a prop está ausente (só aparece quando verificado); "obrigatório" marca campos sem os quais o documento é recusado. Todas as props de item são opcionais, mas um item sem conteúdo (por exemplo um botao sem rotulo) não desenha nada útil.

3.1 Limites do documento

LimiteValorO que limita
MaxSecoes200seções por página
MaxColunas12colunas por seção
MaxPesoColuna12peso (largura) máximo de uma coluna
MaxItensPorColuna100itens por coluna
MaxItensTotal1000itens na página inteira (inclui os aninhados em abas/acordeão)
MaxItensLista50entradas em links, tags, cartoes, redes, menu
MaxEspaco400teto de padding/margem/gap/altura de espaçador (px)
MaxRaio200teto de raio (px)
MaxBorda20teto de espessura de borda (px)
MinLarguraMax320menor largura_max de seção (px)
MaxLarguraMax2400maior largura_max (px)
MaxAlturaPx2000maior altura_minima em px
MaxAlturaVh100maior altura_minima em vh
MaxAtrasoPopup120maior atraso_popup (segundos)
GapPadraoItens16gap padrão entre itens (px)
GapPadraoColunas24gap padrão entre colunas (px)
LarguraMaxPadrao1080largura do conteúdo contido sem largura_max (px)
MaxTamanhoID64caracteres de um id
MaxTamanhoNome80caracteres de secao.nome (conta code points, não bytes)
MaxTamanhoURL2048caracteres de uma URL
MaxTextoCurto300caracteres de títulos, rótulos, alt
MaxTextoLongo20000caracteres do texto de um item texto
MaxTamanhoHTML200000caracteres do item html
MaxTamanhoPrazo64caracteres do prazo do contador
MaxTextoTag60caracteres do texto de um chip / tag de cartão
MaxPaineis20abas ou painéis por item
MaxItensPorPainel20itens dentro de UM painel
MaxTituloPainel200caracteres do título de aba/pergunta
MaxIconeTag48maior tamanho_icone dos chips (px)
MaxFAQResposta4000caracteres da resposta de uma pergunta de FAQ
MaxFAQPagina50perguntas de FAQ somadas na página
MaxSubir200maior estilo.subir (px)
MaxPaddingImagem40maior padding da imagem (px)
MinIconeFundo24menor contêiner de ícone (px)
MaxIconeFundo72maior contêiner de ícone (px)
MaxColunasCartoes4colunas da grade de cartões
MinLarguraCartao96menor largura_cartao (px)
MaxLarguraCartao400maior largura_cartao (px)
MinMiniatura56menor miniatura (px)
MaxMiniatura96maior miniatura (px)
MaxInclinar12maior inclinar (graus)
MaxRotacaoCartao15maior rotacao de um cartão (graus, para os dois lados)

3.2 Os 20 tipos de item

TipoPara que serve
tituloTítulo (h1..h6). Aceita marcação inline [rótulo](url) e [[trecho]].
textoParágrafo de texto. Aceita a mesma marcação inline do título e quebras de linha.
imagemImagem, com forma, proporção, moldura e link opcional.
botaoBotão (ou link-botão) com visual granular, vidro, ícones e imagem.
tagsChips (etiquetas) com ícone, link e visual por chip.
linksLista de botões de link (o miolo de um link-na-bio), com visual por entrada.
cartoesGaleria de cartões (foto, título, texto, tag, ícone, link) em grade, carrossel ou lista.
abasAbas; cada aba é um painel com itens aninhados (um nível só).
acordeaoAcordeão (sanfona); com faq: true gera FAQPage no JSON-LD da página.
redesÍcones de redes sociais (Instagram, WhatsApp...) com link.
menuMenu de navegação (links de texto), horizontal ou vertical; pode colapsar no celular.
formularioEmbute um formulário do Asender (campos reais, anti-spam e captura de lead).
videoVídeo incorporado (<iframe>) a partir de uma URL de embed.
divisorLinha divisória horizontal.
espacadorEspaço vertical em branco.
iconeUm ícone avulso (kit de ícones ou ícone clássico).
seloSelo (pílula de destaque com um texto curto).
contadorContagem regressiva até um prazo.
marcaLogo e/ou nome da conta (vindos do kit de marca efetivo); útil em cabeçalhos.
htmlHTML cru. PRIVILEGIADO: só quem tem o nível elevado grava; sem ele a escrita é barrada (403).

3.3 Documento, estilo da página, seção e coluna

Documento e estilo da página

Documento (raiz):

PropTipoValores / faixaPadrãoDescrição
versao (obrigatório)const2Sempre 2. Qualquer outro valor é ErrVersao.
configuracoesqualquer JSONPassthrough (objeto livre, ex.: encurtar links por padrão). Não é layout.
estiloestilo da páginaObjeto de estilo (ver a tabela do contexto).
secoes (obrigatório)lista de secao≥1 · ≤200Lista de seções (1..200), de cima para baixo.

estilo (a página inteira):

PropTipoValores / faixaPadrãoDescrição
temaenumclaro · escuro · autoclaroclaro (padrão), escuro ou auto (segue o aparelho).
fundofundoFundo da caixa. tipo decide quais campos valem: cor exige cor; gradiente exige gradiente; imagem exige imagem.url.
padraoobjetoTextura sutil desenhada sobre o fundo da página.
padrao.tipo (obrigatório)enumnenhum · pontos · grade · diagonalnenhum, pontos, grade ou diagonal.
padrao.corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da textura (padrão: a cor do texto).
padrao.opacidadeinteiro0..1008Opacidade da textura, em % (0..100).
padrao.tamanhoconst ou inteiro0 ou 8..9624Módulo da textura em px: 0 (padrão = 24) ou 8..96.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
fonte_titulosconst ou enum"" ou comfortaa · urbanist · montserrat · inter · poppins · open-sans · nunito · playfair-display · merriweather · dm-sans · manrope · ralewayFamília dos títulos h1..h6. Vazio herda do kit de marca. Só os ids da allowlist (auto-hospedados em /_f/).
fonte_textoconst ou enum"" ou comfortaa · urbanist · montserrat · inter · poppins · open-sans · nunito · playfair-display · merriweather · dm-sans · manrope · ralewayFamília do texto corrido. Mesma regra de fonte_titulos.
conteudoestiloCaixaA caixa do miolo CONTIDO de toda seção (a coluna estreita de uma página de links): fundo, borda, raio, sombra, padding.

Famílias de fonte aceitas em estilo.fonte_titulos e estilo.fonte_texto (ids exatos, em minúsculas; vazio herda do kit de marca; qualquer outro valor é ErrEstiloInvalido):

comfortaa, urbanist, montserrat, inter, poppins, open-sans, nunito, playfair-display, merriweather, dm-sans, manrope, raleway São auto-hospedadas pelo runtime (/_f/), sem chamada a terceiros.

Seção

Seção:

PropTipoValores / faixaPadrãoDescrição
id (obrigatório)id^[A-Za-z0-9_-]{1,64}$Único no documento inteiro (seção, coluna, item e itens de painel dividem o mesmo espaço).
presettexto^[a-z0-9_-]{1,40}$Só registra de que fábrica a seção nasceu; o renderer não desenha diferente por causa dele.
nometexto≤80Rótulo livre, só para a árvore do editor.
ancoraâncora^[a-z][a-z0-9-]{0,63}$Vira o id HTML da seção; alvo de #ancora em botões e menus. Única na página.
comportamentoenumnormal · fixa_topo · popupnormalnormal; fixa_topo gruda no topo ao rolar; popup abre por cima após atraso_popup s.
atraso_popupinteiro0..120Segundos até o popup abrir (só com comportamento: popup).
ocultar_emlista de enumsem repetição · valores: computador, tablet, celularDispositivos em que o nó não aparece. Pontos de quebra: celular até 767 px, tablet 768-1023 px, computador a partir de 1024 px.
ocultar_se_vaziabooleanotrue / falseA seção some quando nenhum item dela desenha algo (ex.: marca numa conta sem logo nem nome).
layout_celularenumempilhar · manterempilharempilhar (padrão): uma coluna por linha no celular; manter conserva as colunas lado a lado.
inverter_celularbooleanotrue / falseEmpilha as colunas na ordem inversa no celular.
estiloestiloSecaoObjeto de estilo (ver a tabela do contexto).
colunas (obrigatório)lista de coluna≥1 · ≤12Lista de colunas da seção (1..12).

estilo da seção (estiloSecao):

PropTipoValores / faixaPadrãoDescrição
paddingladosRespiro interno em px por lado (0..400).
padding_celularladosSubstitui padding abaixo de 768 px; ausente, o celular usa padding.
fundofundoFundo da caixa. tipo decide quais campos valem: cor exige cor; gradiente exige gradiente; imagem exige imagem.url.
bordabordaObjeto de borda (ver borda).
raiointeiro0..200Raio dos cantos em px (0..200).
raio_sup_esqinteiro0..200Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq.
raio_sup_dirinteiro0..200Raio do canto superior direito (ver raio_sup_esq).
raio_inf_dirinteiro0..200Raio do canto inferior direito (ver raio_sup_esq).
raio_inf_esqinteiro0..200Raio do canto inferior esquerdo (ver raio_sup_esq).
sombraenumnenhuma · suave · media · forteSombra da caixa (vocabulário de caixa: suave/media/forte).
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
larguraenumcontida · totalcontidacontida: o conteúdo respeita largura_max; total: ocupa a largura toda.
largura_maxconst ou qualquer JSON01080Largura do conteúdo contido, em px (320..2400); 0/ausente = 1080. Só vale com largura: contida.
altura_minimainteiro0..2000Altura mínima da seção; a unidade é altura_unidade (px até 2000, vh até 100).
altura_unidadeenumpx · vhpx (padrão) ou vh.
alinhamento_verticalenumtopo · centro · base · esticarPosição das colunas (seção) ou do conteúdo (coluna) no eixo vertical.
gap_colunasinteiro0..40024Espaço entre as colunas da seção, em px (padrão 24).

Para uma seção popup, atraso_popup é em segundos (0..120). fixa_topo serve para cabeçalhos. ocultar_se_vazia esconde a seção quando nenhum item desenha algo.

Coluna

Coluna:

PropTipoValores / faixaPadrãoDescrição
id (obrigatório)id^[A-Za-z0-9_-]{1,64}$Único no documento inteiro (seção, coluna, item e itens de painel dividem o mesmo espaço).
largurainteiro0..121PESO da coluna (unidade fr): 1+2 dá 1/3 + 2/3. Ausente/0 = peso 1.
alinhamento_verticalenumtopo · centro · base · esticarPosição das colunas (seção) ou do conteúdo (coluna) no eixo vertical.
alinhamento_horizontalenuminicio · centro · fim · esticarPosição do conteúdo da coluna no eixo horizontal.
gapinteiro0..40016Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos.
estiloestiloCaixaObjeto de estilo (ver a tabela do contexto).
itens (obrigatório)lista de item≤100

estilo da coluna (estiloCaixa, o mesmo de estilo.conteudo da página):

PropTipoValores / faixaPadrãoDescrição
paddingladosRespiro interno em px por lado (0..400).
padding_celularladosSubstitui padding abaixo de 768 px; ausente, o celular usa padding.
fundofundoFundo da caixa. tipo decide quais campos valem: cor exige cor; gradiente exige gradiente; imagem exige imagem.url.
bordabordaObjeto de borda (ver borda).
raiointeiro0..200Raio dos cantos em px (0..200).
raio_sup_esqinteiro0..200Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq.
raio_sup_dirinteiro0..200Raio do canto superior direito (ver raio_sup_esq).
raio_inf_dirinteiro0..200Raio do canto inferior direito (ver raio_sup_esq).
raio_inf_esqinteiro0..200Raio do canto inferior esquerdo (ver raio_sup_esq).
sombraenumnenhuma · suave · media · forteSombra da caixa (vocabulário de caixa: suave/media/forte).
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.

O envelope do item

PropTipoValores / faixaPadrãoDescrição
id (obrigatório)id^[A-Za-z0-9_-]{1,64}$Único no documento inteiro (seção, coluna, item e itens de painel dividem o mesmo espaço).
tipo (obrigatório)enumtitulo · texto · imagem · botao · tags · links · cartoes · abas · acordeao · redes · menu · formulario · video · divisor · espacador · icone · selo · contador · marca · htmlTipo do item (lista fechada).
props (obrigatório)objetoProps do tipo (tabela do tipo); campo desconhecido é recusado.
estiloobjetoVisual do item na coluna (margem, alinhamento, largura máxima, cor do texto, subir).
estilo.margemladosRespiro externo do item, por lado, em px (0..400). subir > 0 substitui a margem de topo.
estilo.alinhamentoenumherdar · inicio · centro · fimherdarSobrepõe o alinhamento horizontal da coluna; herdar (padrão) mantém o da coluna.
estilo.largura_maxinteiro0..2400Largura máxima do item, em px (0 = sem limite).
estilo.cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
estilo.subirinteiro0..200Puxa o item para cima, sobre o anterior (margin-top negativo), 0..200 px. Substitui a margem de topo.
ocultar_emlista de enumsem repetição · valores: computador, tablet, celularDispositivos em que o nó não aparece. Pontos de quebra: celular até 767 px, tablet 768-1023 px, computador a partir de 1024 px.

Os campos id, tipo e props são obrigatórios. O estilo do item é opcional e comum a todos os tipos: margem (por lado), alinhamento, largura_max, cor_texto e subir.

3.4 Objetos e tipos reutilizados

Cores (cor)

Uma cor é um hex #rrggbb / #rrggbbaa OU um token da paleta da página: transparente, acento, texto, suave, fundo, superficie, borda. acento segue a cor da marca da conta; transparente serve de ponta de degradê (fade). Nome de cor CSS (red), rgb(), hex curto (#fff) e qualquer texto livre são recusados. Onde o schema diz "cor ou vazio", "" significa "use o padrão do tema".

lados

PropTipoValores / faixaPadrãoDescrição
topointeiro0..400Px do lado superior.
direitainteiro0..400Px do lado direito.
baseinteiro0..400Px do lado inferior.
esquerdainteiro0..400Px do lado esquerdo.

fundo

PropTipoValores / faixaPadrãoDescrição
tipoenumnenhum · cor · gradiente · imagemnenhum, cor, gradiente ou imagem.
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do fundo (obrigatória quando tipo é cor).
cor_basecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor sólida sob as demais camadas (gradiente/imagem/película).
gradientegradienteDegradê (ver gradiente). Obrigatório quando fundo.tipo é gradiente; na película, use-o no lugar de cor.
imagemobjetoImagem de fundo (obrigatória quando tipo é imagem).
imagem.url (obrigatório)url de mídia≤2048 · http(s) com host ou /caminhoURL da imagem de fundo (galeria da conta ou https://). Obrigatória quando fundo.tipo é imagem.
imagem.posicaoenumcentro · topo · base · esquerda · direita · topo-esquerda · topo-direita · base-esquerda · base-direitaPosição da imagem de fundo.
imagem.tamanhoenumcobrir · conter · autocobrir (preenche cortando), conter (mostra inteira) ou auto (tamanho original).
imagem.repetirbooleanotrue / falseRepete a imagem de fundo.
imagem.fixobooleanotrue / falseFundo fixo (não rola com a página).
sobreposicaoum dePelícula por cima do fundo: exige cor OU gradiente (um só) e opacidade 0..100 na camada inteira.
sobreposicao.corcor#rrggbb, #rrggbbaa ou token (ver Cores)Cor da película (use esta OU gradiente).
sobreposicao.gradientegradienteDegradê (ver gradiente). Obrigatório quando fundo.tipo é gradiente; na película, use-o no lugar de cor.
sobreposicao.opacidade (obrigatório)inteiro0..100Opacidade da película na camada inteira, em % (0..100).

gradiente

PropTipoValores / faixaPadrãoDescrição
tipoenumlinear · radiallinear (padrão, no angulo) ou radial (círculo a partir do centro).
de (obrigatório)cor#rrggbb, #rrggbbaa ou token (ver Cores)Cor inicial do degradê (aceita transparente).
meiocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor intermediária opcional do degradê.
para (obrigatório)cor#rrggbb, #rrggbbaa ou token (ver Cores)Cor final do degradê (aceita transparente).
angulointeiro0..360Ângulo do degradê, em graus (0..360).

borda

PropTipoValores / faixaPadrãoDescrição
largurainteiro0..20Espessura da borda em px (0..20).
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
estiloenumsolida · tracejada · pontilhadasolida, tracejada ou pontilhada.
ladoslista de enumsem repetição · valores: topo, direita, base, esquerdaLados que recebem a borda (sem repetir); ausente = os quatro.

3.5 Cada tipo de item, campo a campo

titulo

Título (h1..h6). Aceita marcação inline [rótulo](url) e [[trecho]].

PropTipoValores / faixaPadrãoDescrição
textotexto≤300Texto do título. Aceita a marcação inline ([rótulo](url), [[destaque]]).
nivelinteiro1..6Nível do cabeçalho (h1..h6). Use um único h1 por página.
tamanhoenumauto · p · m · g · ggautoEscala tipográfica: auto (padrão do nível), p, m, g, gg.
transformarenumnenhum · caixa_alta · caixa_baixa · capitalizartext-transform: nenhum, caixa_alta, caixa_baixa, capitalizar.
espacamentointeiro0..6Espaçamento entre letras (letter-spacing) em px, 0..6.
destaque_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor aplicada aos trechos [[destaque]] do texto (token ou hex).

texto

Parágrafo de texto. Aceita a mesma marcação inline do título e quebras de linha.

PropTipoValores / faixaPadrãoDescrição
textotexto≤20000Texto do parágrafo. Aceita a marcação inline ([rótulo](url), [[destaque]]) e quebras de linha.
varianteenumnormal · suave · destaque · citacaonormalnormal, suave (cor atenuada), destaque, citacao.
tamanhoenumauto · p · m · g · ggautoEscala tipográfica: auto (padrão), p, m, g, gg.
transformarenumnenhum · caixa_alta · caixa_baixa · capitalizartext-transform: nenhum, caixa_alta, caixa_baixa, capitalizar.
espacamentointeiro0..6Espaçamento entre letras (letter-spacing) em px, 0..6.
destaque_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor aplicada aos trechos [[destaque]] do texto (token ou hex).

imagem

Imagem, com forma, proporção, moldura e link opcional.

PropTipoValores / faixaPadrãoDescrição
urlurl de mídia≤2048 · http(s) com host ou /caminhoURL da imagem: da galeria da conta (/v1/public/midias/<id>) ou https:// externa. Sem aspas, espaços, parênteses ou <>.
alttexto≤300Texto alternativo (acessibilidade e SEO). Descreva a imagem; vazio só para imagem decorativa.
linkurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino ao clicar na imagem (regra de href).
formaenumnormal · arredondada · circulonormalnormal, arredondada ou circulo. raio presente vence forma.
largurainteiro16..2400Largura em px (16..2400). Ausente = a imagem ocupa a coluna.
proporcaoenumauto · 1:1 · 4:3 · 3:4 · 16:9 · 9:16autoProporção da caixa: auto (padrão) ou largura:altura.
ajusteenumcobrir · contercobrircobrir (padrão: preenche cortando) ou conter (mostra inteira).
bordainteiro0..20Espessura da borda em px (0..20).
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
sombraenumnenhuma · leve · forteSombra do item (vocabulário de item: leve/forte). Não misture com o de caixa.
cor_fundocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo atrás da imagem (aparece na moldura/padding).
paddinginteiro0..40Respiro interno em px por lado (0..400).
raiointeiro0..200Raio dos cantos em px (0..200).
raio_sup_esqinteiro0..200Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq.
raio_sup_dirinteiro0..200Raio do canto superior direito (ver raio_sup_esq).
raio_inf_dirinteiro0..200Raio do canto inferior direito (ver raio_sup_esq).
raio_inf_esqinteiro0..200Raio do canto inferior esquerdo (ver raio_sup_esq).
link_rastreioobjeto ou nullObjeto do encurtador para link (ver url_rastreio).

botao

Botão (ou link-botão) com visual granular, vidro, ícones e imagem.

PropTipoValores / faixaPadrãoDescrição
rotulotexto≤300Texto do botão.
transformarenumnenhum · caixa_alta · caixa_baixa · capitalizartext-transform: nenhum, caixa_alta, caixa_baixa, capitalizar.
espacamentointeiro0..6Espaçamento entre letras (letter-spacing) em px, 0..6.
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>).
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
varianteenumsolido · contorno · textosolidosolido (padrão), contorno ou texto.
tamanhoenump · m · gmp, m (padrão) ou g.
largura_totalbooleanotrue / falsefalseO botão ocupa a largura toda da coluna.
nova_ababooleanotrue / falsefalseAbre em nova aba (target=_blank com rel=noopener).
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
bordainteiro0..20Espessura da borda em px (0..20).
raiointeiro0..200Raio dos cantos em px (0..200).
raio_sup_esqinteiro0..200Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq.
raio_sup_dirinteiro0..200Raio do canto superior direito (ver raio_sup_esq).
raio_inf_dirinteiro0..200Raio do canto inferior direito (ver raio_sup_esq).
raio_inf_esqinteiro0..200Raio do canto inferior esquerdo (ver raio_sup_esq).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
sombraenumnenhuma · leve · forteSombra do item (vocabulário de item: leve/forte). Não misture com o de caixa.
iconenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioNome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link).
icone_dirnome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioÍcone do FIM (direita) do botão/entrada. Mesmas regras de icone.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda no hover.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
cor_icone_iniciocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do início (vence cor_icone).
cor_icone_fimcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do fim (vence cor_icone).
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
imagemurl de mídia≤2048 · http(s) com host ou /caminhoImagem DENTRO do botão/entrada: URL de mídia (galeria ou https://).
imagem_alttexto≤300Texto alternativo da imagem do botão.
imagem_posicaoenuminicio · fim · topoinicioOnde fica a imagem: inicio (padrão), fim ou topo.
imagem_tamanhoenump · m · gmTamanho da imagem: p, m (padrão) ou g.
imagem_formaenumquadrada · arredondada · circuloarredondadaquadrada, arredondada (padrão) ou circulo.
icone_imgurl de mídia≤2048 · http(s) com host ou /caminhoÍcone PERSONALIZADO do início: URL de mídia (vira <img>). Vence o glifo icone; cores de ícone não se aplicam.
icone_dir_imgurl de mídia≤2048 · http(s) com host ou /caminhoÍcone personalizado do fim (ver icone_img).
url_rastreioobjeto ou nullObjeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido.

tags

Chips (etiquetas) com ícone, link e visual por chip.

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤50Até 50 chips.
presetenumtranslucido · solido · contornotranslucidoAparência base dos chips: translucido (padrão), solido, contorno.
iconenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioNome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link).
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
tamanho_iconeinteiro10..48Tamanho do ícone em px.
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda no hover.
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
gapinteiro0..400Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos.
alinhamentoenuminicio · centro · fiminicioAlinhamento do conjunto de chips.
quebraenumquebrar · linhaquebrarquebrar (padrão) quebra linha; linha mantém uma linha só.

Cada entrada de tags.itens[]:

PropTipoValores / faixaPadrãoDescrição
textotexto≤60Texto do chip.
iconenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioNome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link).
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>).
nova_ababooleanotrue / falseAbre em nova aba (target=_blank com rel=noopener).
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda no hover.
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
sombraenumnenhuma · leve · forteSombra do item (vocabulário de item: leve/forte). Não misture com o de caixa.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
imagemurl de mídia≤2048 · http(s) com host ou /caminhoImagem DENTRO do botão/entrada: URL de mídia (galeria ou https://).
imagem_alttexto≤300Texto alternativo da imagem do botão.
imagem_posicaoenuminicio · fim · topoOnde fica a imagem: inicio (padrão), fim ou topo.
imagem_tamanhoenump · m · gTamanho da imagem: p, m (padrão) ou g.
imagem_formaenumquadrada · arredondada · circuloquadrada, arredondada (padrão) ou circulo.
icone_imgurl de mídia≤2048 · http(s) com host ou /caminhoÍcone PERSONALIZADO do início: URL de mídia (vira <img>). Vence o glifo icone; cores de ícone não se aplicam.
icone_dir_imgurl de mídia≤2048 · http(s) com host ou /caminhoÍcone personalizado do fim (ver icone_img).
cor_icone_iniciocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do início (vence cor_icone).
url_rastreioobjeto ou nullObjeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido.

Lista de botões de link (o miolo de um link-na-bio), com visual por entrada.

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤50Até 50 botões. Entrada sem titulo e sem URL válida é ignorada; sem titulo, a URL vira o texto do botão.
estiloenumcartao · preenchido · contorno · fantasma · suave · sombracartaoAparência dos botões: cartao (padrão), preenchido, contorno, fantasma, suave, sombra.
tamanhoenump · m · gmp, m (padrão) ou g.
larguraenumtotal · conteudototaltotal: cada botão ocupa a largura da coluna; conteudo: só o tamanho do conteúdo.
alinhamento_textoenumcentro · iniciocentroAlinhamento do texto do botão/cartão: centro ou inicio.
efeitoenumelevar · escala · brilho · fundo · sublinhado · nenhumelevarEfeito no hover/foco: elevar (padrão), escala, brilho, fundo, sublinhado, nenhum. Desligado em prefers-reduced-motion.
efeito_iconeenumnenhum · deslizar · destacar · girarnenhumgirar gira o ícone do fim no hover (bola de seta); deslizar, destacar, nenhum (padrão).
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
espacointeiro0..400Espaço entre os botões da lista, em px.
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).
cor_icone_iniciocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do início (vence cor_icone).
cor_icone_fimcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do fim (vence cor_icone).
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
tamanho_iconeinteiro12..64Tamanho do ícone em px.

Cada entrada de links.itens[]:

PropTipoValores / faixaPadrãoDescrição
titulotexto≤300Texto principal do botão.
textotexto≤300Linha secundária sob o título do botão.
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>).
iconenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioNome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link).
icone_imgurl de mídia≤2048 · http(s) com host ou /caminhoÍcone PERSONALIZADO do início: URL de mídia (vira <img>). Vence o glifo icone; cores de ícone não se aplicam.
icone_dirnome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioÍcone do FIM (direita) do botão/entrada. Mesmas regras de icone.
icone_dir_imgurl de mídia≤2048 · http(s) com host ou /caminhoÍcone personalizado do fim (ver icone_img).
destaquebooleanotrue / falseRealça a entrada (visual de destaque do tema).
nova_ababooleanotrue / falseAbre em nova aba (target=_blank com rel=noopener).
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda no hover.
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
sombraenumnenhuma · leve · forteSombra do item (vocabulário de item: leve/forte). Não misture com o de caixa.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
cor_icone_iniciocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do início (vence cor_icone).
cor_icone_fimcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone do fim (vence cor_icone).
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
imagemurl de mídia≤2048 · http(s) com host ou /caminhoImagem DENTRO do botão/entrada: URL de mídia (galeria ou https://).
imagem_alttexto≤300Texto alternativo da imagem do botão.
imagem_posicaoenuminicio · fim · topoOnde fica a imagem: inicio (padrão), fim ou topo.
imagem_tamanhoenump · m · gTamanho da imagem: p, m (padrão) ou g.
imagem_formaenumquadrada · arredondada · circuloquadrada, arredondada (padrão) ou circulo.
url_rastreioobjeto ou nullObjeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido.

cartoes

Galeria de cartões (foto, título, texto, tag, ícone, link) em grade, carrossel ou lista.

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤50Até 50 cartões.
layoutenumgrade · carrossel · listagradegrade (padrão), carrossel (rolagem com snap, sem JS) ou lista (miniatura + texto).
colunasinteiro1..4Colunas da grade (1..4).
largura_cartaointeiro96..400Largura de cada cartão no carrossel, em px (96..400).
proporcaoenumauto · 1:1 · 4:3 · 3:4 · 16:9 · 9:16 · 4:5autoProporção da caixa: auto (padrão) ou largura:altura.
ajusteenumcobrir · contercobrircobrir (padrão: preenche cortando) ou conter (mostra inteira).
legendaenumabaixo · sobre · nenhumaabaixoabaixo (padrão), sobre (texto sobre a foto, com degradê automático) ou nenhuma.
miniaturainteiro56..96Lado da miniatura no layout lista, em px (56..96).
forma_miniaturaenumquadrada · arredondada · circuloarredondadaForma da miniatura da lista: quadrada, arredondada (padrão), circulo.
molduraenumnenhuma · polaroidnenhumanenhuma (padrão) ou polaroid.
inclinarinteiro0..12Inclinação alternada do conjunto, em graus (0..12), típica da moldura polaroid.
rotulotexto≤300Rótulo acessível (aria-label) da galeria.
raiointeiro0..200Raio dos cantos em px (0..200).
raio_sup_esqinteiro0..200Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq.
raio_sup_dirinteiro0..200Raio do canto superior direito (ver raio_sup_esq).
raio_inf_dirinteiro0..200Raio do canto inferior direito (ver raio_sup_esq).
raio_inf_esqinteiro0..200Raio do canto inferior esquerdo (ver raio_sup_esq).
bordainteiro0..20Espessura da borda em px (0..20).
sombraenumnenhuma · leve · forteSombra do item (vocabulário de item: leve/forte). Não misture com o de caixa.
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda no hover.
gapinteiro0..400Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos.
efeitoenumelevar · escala · brilho · nenhumnenhumEfeito no hover/foco: elevar, escala, brilho, nenhum (padrão).
alinhamento_textoenumcentro · inicioinicioAlinhamento do texto do botão/cartão: centro ou inicio.
tamanho_iconeinteiro12..64Tamanho do ícone em px.
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).

Cada entrada de cartoes.itens[]:

PropTipoValores / faixaPadrãoDescrição
imgurl de mídia≤2048 · http(s) com host ou /caminhoFoto do cartão (URL de mídia).
alttexto≤300Texto alternativo (acessibilidade e SEO). Descreva a imagem; vazio só para imagem decorativa.
titulotexto≤300Título do cartão.
textotexto≤300Texto do cartão.
tagtexto≤60Etiqueta curta do cartão (até 60).
iconenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioNome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link).
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>).
nova_ababooleanotrue / falseAbre em nova aba (target=_blank com rel=noopener).
rotacaointeiro-15..15Rotação deste cartão em graus (-15..15). Vence inclinar do conjunto.
cor_fimcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Liga o degradê do fundo do cartão: cor é o início e cor_fim o fim.
angulointeiro0..360Ângulo do degradê, em graus (0..360).
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda no hover.
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
sombraenumnenhuma · leve · forteSombra do item (vocabulário de item: leve/forte). Não misture com o de caixa.
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone no hover.
vidrobooleanotrue / falseLiga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados.
vidro_opacidadeinteiro0..100Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30.
vidro_desfoqueinteiro0..40Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14.
vidro_saturacaointeiro100..200Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).
url_rastreioobjeto ou nullObjeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido.

abas

Abas; cada aba é um painel com itens aninhados (um nível só).

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤20Até 20 abas. Cada uma: titulo (obrigatório, não vazio) e itens aninhados.
abertainteiro0..19Índice (0 = primeira) da aba aberta de início. Tem de existir.
rotulotexto≤300Rótulo acessível (aria-label) da lista de abas.
estiloenumlinha · pilula · cartaolinhaAparência da barra: linha (padrão), pilula, cartao.
alinhamentoenuminicio · centro · fim · esticarinicioAlinhamento da barra de abas; esticar reparte a largura.
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
cor_ativacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Fundo da aba ativa.
cor_texto_ativacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Texto da aba ativa.
cor_borda_ativacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Borda da aba ativa.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
gapinteiro0..400Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos.
painel_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Fundo da área de conteúdo do painel.
painel_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Texto da área de conteúdo do painel.
painel_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Borda da área de conteúdo do painel.
painel_bordainteiro0..20Espessura da borda do painel (0..20).
painel_raiointeiro0..200Raio do painel (0..200).
painel_paddinginteiro0..400Respiro interno do painel em px.

Cada entrada de abas.itens[]:

PropTipoValores / faixaPadrãoDescrição
titulotexto≤200Título da aba (obrigatório).
itenslista de itens aninhados≤20 · tipos: titulo, texto, imagem, botao, tags, links, cartoes, redes, menu, video, divisor, espacador, icone, selo, contador, marcaAté 20 abas. Cada uma: titulo (obrigatório, não vazio) e itens aninhados.

acordeao

Acordeão (sanfona); com faq: true gera FAQPage no JSON-LD da página.

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤20Até 20 painéis. Cada um: titulo (obrigatório, não vazio), aberto e itens aninhados.
um_por_vezbooleanotrue / falsefalseAbrir um painel fecha os outros.
faqbooleanotrue / falseGera FAQPage no JSON-LD. Exige texto de resposta em cada painel (itens texto/titulo), até 4000 caracteres; até 50 perguntas na página.
nivelinteiro2..6Nível do cabeçalho de cada pergunta (2..6).
estiloenumcartao · linha · simplescartaoAparência: cartao (padrão), linha, simples.
indicadorenumseta · mais · nenhumsetaMarcador de aberto/fechado: seta (padrão), mais ou nenhum.
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema.
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto. Herda da caixa/página quando vazia.
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da borda.
cor_abertocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Fundo do painel aberto.
cor_texto_abertocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Texto do painel aberto.
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor de fundo ao passar o mouse/foco.
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do texto no hover.
raiointeiro0..200Raio dos cantos em px (0..200).
bordainteiro0..20Espessura da borda em px (0..20).
padding_vinteiro0..400Respiro vertical interno em px (0..400).
padding_hinteiro0..400Respiro horizontal interno em px (0..400).
fonte_pesoenum400 · 500 · 600 · 700 · 800Peso da fonte, como TEXTO: "400", "500", "600", "700", "800".
fonte_tamanhointeiro10..72Tamanho da fonte em px (10..72).
gapinteiro0..400Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos.
painel_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Fundo da área de conteúdo do painel.
painel_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Texto da área de conteúdo do painel.
painel_paddinginteiro0..400Respiro interno do painel em px.

Cada entrada de acordeao.itens[]:

PropTipoValores / faixaPadrãoDescrição
titulotexto≤200Pergunta/título do painel (obrigatório).
abertobooleanotrue / falsePainel aberto de início. Com um_por_vez, no máximo um.
itenslista de itens aninhados≤20 · tipos: titulo, texto, imagem, botao, tags, links, cartoes, redes, menu, video, divisor, espacador, icone, selo, contador, marcaAté 20 painéis. Cada um: titulo (obrigatório, não vazio), aberto e itens aninhados.

redes

Ícones de redes sociais (Instagram, WhatsApp...) com link.

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤50Até 50 redes.
tamanhoenump · m · gTamanho dos ícones: p, m ou g.
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do(s) ícone(s). Vazio herda a cor do texto.
icone_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado.
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do início.
icone_fundo_tamanhointeiro24..72Lado do contêiner em px (24..72).
icone_dir_fundoenumnenhum · circulo · quadradoContêiner atrás do ícone do FIM: nenhum, circulo, quadrado.
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do contêiner do ícone do fim.
icone_dir_fundo_tamanhointeiro24..72Lado do contêiner do fim em px (24..72).

Cada entrada de redes.itens[]:

PropTipoValores / faixaPadrãoDescrição
redenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioNome da rede: instagram, x, facebook, linkedin, youtube, tiktok, whatsapp, telegram, email, site, github, pinterest. Outro nome vira o ícone genérico de link.
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>).
url_rastreioobjeto ou nullObjeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido.

Menu de navegação (links de texto), horizontal ou vertical; pode colapsar no celular.

PropTipoValores / faixaPadrãoDescrição
itenslista de objeto≤50Até 50 links.
orientacaoenumhorizontal · verticalhorizontalhorizontal (padrão) ou vertical.
colapsar_celularbooleanotrue / falsefalseNo celular o menu vira um botão que abre/fecha.

Cada entrada de menu.itens[]:

PropTipoValores / faixaPadrãoDescrição
rotulotexto≤300Texto do link do menu.
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoDestino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>).
url_rastreioobjeto ou nullObjeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido.

formulario

Embute um formulário do Asender (campos reais, anti-spam e captura de lead).

PropTipoValores / faixaPadrãoDescrição
form_idid^[A-Za-z0-9_-]{1,64}$ ou vazioId do formulário (criado em /v1/formularios). Vazio = "ainda não configurado" (nada é desenhado). Id de outra conta é removido na importação.
rotulotexto≤300Texto do botão de envio do formulário embutido (sobrepõe o do formulário).

video

Vídeo incorporado (<iframe>) a partir de uma URL de embed.

PropTipoValores / faixaPadrãoDescrição
urlurl de link≤2048 · http/https/mailto/tel, #ancora, /caminhoURL de EMBED (ex.: https://www.youtube.com/embed/<id>). Mesma regra de href (http/https/mailto/tel, #âncora, /caminho). Sem irmã url_rastreio.
titulotexto≤300Título acessível do <iframe>.

divisor

Linha divisória horizontal.

PropTipoValores / faixaPadrãoDescrição
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor da linha.
espessurainteiro1..20Espessura da linha em px (1..20).
estiloenumsolida · tracejada · pontilhadaObjeto de estilo (ver a tabela do contexto).
largurainteiro10..100Largura da linha em % da coluna (10..100).

espacador

Espaço vertical em branco.

PropTipoValores / faixaPadrãoDescrição
alturainteiro0..400Altura do espaço em px (0..400).
altura_celularinteiro0..400Altura do espaço no celular, em px.

icone

Um ícone avulso (kit de ícones ou ícone clássico).

PropTipoValores / faixaPadrãoDescrição
nomenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vazioRótulo livre, só para a árvore do editor.
tamanhointeiro12..256Lado do ícone em px (12..256).
corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)Cor do ícone.

selo

Selo (pílula de destaque com um texto curto).

PropTipoValores / faixaPadrãoDescrição
textotexto≤300Texto do selo.

contador

Contagem regressiva até um prazo.

PropTipoValores / faixaPadrãoDescrição
prazotexto≤64Data-hora final em RFC 3339 (ex.: 2026-12-31T23:59:00-03:00). Ilegível = só o rótulo.
rotulotexto≤300Texto que acompanha a contagem.

marca

Logo e/ou nome da conta (vindos do kit de marca efetivo); útil em cabeçalhos.

PropTipoValores / faixaPadrãoDescrição
mostrar_logobooleanotrue / falsetrueMostra o logo do kit de marca (padrão true).
mostrar_nomebooleanotrue / falsetrueMostra o nome da conta (padrão true).
altura_logointeiro16..200Altura do logo em px (16..200).

html

HTML cru. PRIVILEGIADO: só quem tem o nível elevado grava; sem ele a escrita é barrada (403).

PropTipoValores / faixaPadrãoDescrição
htmltexto≤200000HTML cru (até 200000 caracteres). Privilegiado; exige nível elevado.

3.6 Campos visuais compartilhados

Os mesmos nomes aparecem em vários tipos e têm o mesmo significado. A tabela abaixo é gerada: lista todo campo presente em três ou mais tipos.

CampoTipoValores / faixaPresente em
alinhamentoenumherdar · inicio · centro · fimitem
alinhamentoenuminicio · centro · fimtags
alinhamentoenuminicio · centro · fim · esticarabas
cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)imagem, botao, tags, links, cartoes, abas, acordeao
cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes, redes
cor_icone_iniciocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links
cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)pagina, secao, coluna, item, botao, tags, links, cartoes, abas, acordeao
espacamentointeiro0..6titulo, texto, botao
fonte_pesoenum400 · 500 · 600 · 700 · 800botao, tags, links, cartoes, abas, acordeao
fonte_tamanhointeiro10..72botao, tags, links, cartoes, abas, acordeao
gapinteiro0..400coluna, tags, cartoes, abas, acordeao
hover_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes, abas, acordeao
hover_cor_bordacor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes
hover_cor_iconecor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes
hover_cor_textocor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes, abas, acordeao
iconenome (ícone/rede)^[a-z0-9_-]{1,40}$ ou vaziobotao, tags, links, cartoes
icone_dir_fundoenumnenhum · circulo · quadradobotao, tags, links, cartoes, redes
icone_dir_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes, redes
icone_dir_fundo_tamanhointeiro24..72botao, tags, links, cartoes, redes
icone_dir_imgurl de mídia≤2048 · http(s) com host ou /caminhobotao, tags, links
icone_fundoenumnenhum · circulo · quadradobotao, tags, links, cartoes, redes
icone_fundo_corcor ou vazio#rrggbb, #rrggbbaa ou token (ver Cores)botao, tags, links, cartoes, redes
icone_fundo_tamanhointeiro24..72botao, tags, links, cartoes, redes
icone_imgurl de mídia≤2048 · http(s) com host ou /caminhobotao, tags, links
imagemurl de mídia≤2048 · http(s) com host ou /caminhobotao, tags, links
imagemobjetofundo
imagem_alttexto≤300botao, tags, links
imagem_formaenumquadrada · arredondada · circulobotao, tags, links
imagem_posicaoenuminicio · fim · topobotao, tags, links
imagem_tamanhoenump · m · gbotao, tags, links
larguraenumcontida · totalsecao
largurainteiro0..12coluna
largurainteiro16..2400imagem
larguraenumtotal · conteudolinks
largurainteiro10..100divisor
largurainteiro0..20borda
nova_ababooleanotrue / falsebotao, tags, links, cartoes
padding_hinteiro0..400botao, tags, links, cartoes, abas, acordeao
padding_vinteiro0..400botao, tags, links, cartoes, abas, acordeao
raiointeiro0..200secao, coluna, imagem, botao, tags, links, cartoes, abas, acordeao
raio_inf_dirinteiro0..200secao, coluna, imagem, botao, cartoes
raio_inf_esqinteiro0..200secao, coluna, imagem, botao, cartoes
raio_sup_dirinteiro0..200secao, coluna, imagem, botao, cartoes
raio_sup_esqinteiro0..200secao, coluna, imagem, botao, cartoes
sombraenumnenhuma · suave · media · fortesecao, coluna
sombraenumnenhuma · leve · forteimagem, botao, tags, links, cartoes
tamanhoconst ou inteiro0 ou 8..96pagina
tamanhoenumauto · p · m · g · ggtitulo, texto
tamanhoenump · m · gbotao, links, redes
tamanhointeiro12..256icone
tamanhoenumcobrir · conter · autofundo
tamanho_iconeinteiro10..48tags
tamanho_iconeinteiro12..64links, cartoes
transformarenumnenhum · caixa_alta · caixa_baixa · capitalizartitulo, texto, botao
url_rastreioobjeto ou nullbotao, tags, links, cartoes, redes, menu
vidrobooleanotrue / falsebotao, tags, links, cartoes
vidro_desfoqueinteiro0..40botao, tags, links, cartoes
vidro_opacidadeinteiro0..100botao, tags, links, cartoes
vidro_saturacaointeiro100..200botao, tags, links, cartoes

Como pensar neles:

{ "tipo": "imagem", "cor_base": "#111111",
  "imagem": { "url": "https://exemplo.test/capa.jpg", "tamanho": "cobrir", "posicao": "centro" },
  "sobreposicao": { "gradiente": { "de": "#000000", "para": "transparente", "angulo": 180 }, "opacidade": 60 } }

3.7 Marcação inline em titulo.texto e texto.texto

Dentro do texto de um título ou parágrafo (e só nesses dois campos) valem duas marcações. Todo o resto é texto: HTML não é interpretado (< e & são escapados), então não envie tags.

MarcaçãoResultado
[rótulo](https://exemplo.test)link <a rel="noopener noreferrer">. Endereço permitido: http://, https://, mailto:, tel:
[[trecho]]trecho em destaque (span.pg-destaque); a cor vem de destaque_cor

Regras: sem aninhamento; o rótulo não pode ter [ ou ]; o endereço vai até o primeiro ), sem espaço, aspas, <, >, \ ou crase, até 2048 caracteres; em http(s) o que vem depois de // não pode começar com /. Link com endereço não permitido reprova a validação (ErrPropInvalida, apontando ...props.texto); não use javascript:, data: nem caminho relativo na marcação (use um item botao ou links para isso). Quebras de linha são mantidas.

{ "id": "t1", "tipo": "titulo",
  "props": { "texto": "Organize seus pedidos sem [[planilhas]]", "nivel": 1, "destaque_cor": "acento" } }
{ "id": "t2", "tipo": "texto",
  "props": { "texto": "Veja o [portfólio](https://exemplo.test/portfolio) ou escreva para [oi@exemplo.test](mailto:oi@exemplo.test)." } }

3.8 Formulários embutidos

O item formulario renderiza um formulário real do Asender (campos, anti-spam, captura de lead). Ele referencia um formulário existente pelo form_id; a ordem é:

  1. Crie o formulário: POST /v1/formularios (sessão ou API key forms:write):
curl -sS -X POST "$API/v1/formularios" "${H[@]}" -d '{
  "nome": "Contato do site",
  "external_id": "site-contato",
  "campos": [
    { "nome": "nome",  "rotulo": "Nome",   "tipo": "texto", "obrigatorio": true },
    { "nome": "email", "rotulo": "E-mail", "tipo": "email", "obrigatorio": true },
    { "nome": "mensagem", "rotulo": "Mensagem", "tipo": "texto_longo" }
  ],
  "texto_botao": "Enviar",
  "mensagem_pos_envio": "Recebemos, obrigado."
}'
# -> 201 { "id": "<form-id>", "external_id": "site-contato", ... }
  1. Use o id devolvido no item: { "tipo": "formulario", "props": { "form_id": "<form-id>" } }.
  2. Páginas publicadas mostram o formulário na hora; capturas viram leads no CRM. Fora de produção, use endereços @exemplo.test em testes: nada sai para ninguém.

form_id vazio significa "ainda não configurado" (o item não desenha nada). Ao importar uma página para outra conta, form_id que a conta de destino não tem é zerado, com aviso. O tipo formulario não pode ficar dentro de abas/acordeão. Campos, destinos e envio de leads por chave: guia de Páginas.

3.9 Abas, acordeão e FAQ (JSON-LD)

abas e acordeao guardam os painéis em props.itens. Cada painel tem titulo (obrigatório, não vazio) e itens: objetos de item completos (id, tipo, props obrigatórios) dos tipos permitidos em painel (titulo, texto, imagem, botao, tags, links, cartoes, redes, menu, video, divisor, espacador, icone, selo, contador, marca). Nunca abas, acordeao, html, formulario (ErrEstruturaInvalida).

3.10 SEO e meta da página

O SEO não mora no documento: é uma rota própria, GET/PUT /v1/paginas/{id}/seo (sessão ou chave: pages:read / pages:write), e vale sem publicar nova versão (na próxima resolução do runtime). Campos: titulo (até 120), descricao (até 320), canonical_url, noindex, og_titulo, og_descricao, og_imagem_url (só https), og_imagem_alt, og_imagem_largura/og_imagem_altura (juntas, 1..10000). Vazio volta ao padrão do runtime (título da página, primeiro texto, primeira imagem).

curl -sS -X PUT "$API/v1/paginas/<pagina-id>/seo" "${H[@]}" -d '{
  "titulo": "Lançamento | Minha marca", "descricao": "Conheça a novidade de 2026.",
  "og_imagem_url": "https://exemplo.test/og.jpg", "og_imagem_alt": "Capa do lançamento",
  "og_imagem_largura": 1200, "og_imagem_altura": 630
}'

PUT substitui todos os campos de uma vez: leia com GET, altere e devolva.

4. Validação e erros comuns

O servidor valida tudo na escrita (POST /v1/paginas, POST /v1/paginas/{id}/versoes, importação). O rascunho (seção 6.2) só confere a forma, de propósito.

4.1 O formato do erro

Recusa de documento v2 = 422 com três campos:

{
  "erro": "documento: prop de item inválida: secoes[0].colunas[0].itens[0].props.url",
  "codigo": "ErrPropInvalida",
  "caminho": "secoes[0].colunas[0].itens[0].props.url"
}

caminho aponta o nó culpado (índices de array entre colchetes); sem nó, vale versao, secoes ou documento. O servidor devolve o primeiro erro; corrija e reenvie até passar. Os códigos:

codigoQuandoComo corrigir
ErrMalformadoJSON inválido, campo desconhecido em estrutura/estilo, ou lixo depois do objeto.Remova o campo citado; confira vírgulas e aspas. Só use os campos das tabelas.
ErrVersaoversao diferente de 2.Envie "versao": 2 (número, não texto).
ErrSemSecoessecoes vazia ou ausente.Inclua ao menos uma seção.
ErrLimiteAlgum teto foi excedido (itens, colunas, entradas de lista, FAQ...).Reduza ou divida em seções; veja a tabela de limites.
ErrSemColunasSeção sem coluna.Toda seção precisa de 1..12 colunas.
ErrIDid com forma inválida ou repetido.Use ^[A-Za-z0-9_-]{1,64}$ e ids ÚNICOS no documento inteiro (seção, coluna, item e itens de painel).
ErrAncoraancora inválida ou repetida.Use ^[a-z][a-z0-9-]{0,63}$, única na página.
ErrTipoDesconhecidotipo de item fora da lista.Use um dos 20 tipos (tabela de tipos).
ErrPropInvalidaProp inexistente no tipo, valor fora da faixa/enum, URL fora da allowlist, cor inválida, link da marcação recusado...Leia o caminho; confira a tabela do tipo (nome, tipo, faixa).
ErrEstiloInvalidoValor de estilo inválido (fundo, borda, raio, fonte fora da allowlist, cor, faixa...).Leia o caminho; confira as tabelas de estilo.
ErrEstruturaInvalidaValor estrutural inválido (enum de comportamento/dispositivo, peso de coluna, tipo proibido dentro de painel...).Leia o caminho; dentro de abas/acordeão só entram tipos permitidos (nunca abas, acordeao, html, formulario).

Outros status das rotas de página: 400 corpo inválido (campo desconhecido no corpo da requisição, como tenant_id, também é 400), 401 sem credencial (ou rota que não aceita chave), 403 item html sem nível ou chave sem escopo, 404 página inexistente ou de outra conta, 409 endereço em uso, 413 corpo grande demais, 422 regra de negócio (domínio não verificado, título vazio).

4.2 Regras que valem para todo valor

4.3 Exemplos reais do corpus de testes

Estes são casos do corpus hostil que os três validadores (Go, TS e schema) rodam em CI (asender_docs/contratos/fixtures/pages-v1-v2/validacao.json, centenas de casos). Cada um mostra o código e o fragmento enviado:

Caso (corpus validacao.json)codigoO que foi enviado (fragmento)
versao-1ErrVersao{"versao":1,"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}]}]}
sem-secoesErrSemSecoes{"versao":2,"secoes":[]}
treze-colunasErrLimite{"versao":2,"secoes":[{"id":"a","colunas":[{"id":"c0","itens":[]},{"id":"c1","itens":[]},{"id":"c2","itens":[]},{"id":"c3","itens":[]},{"id":"c4","itens":[]},{"id":"c5","itens":[]},{"id":"c6","itens":[]},{"id":"c7","itens":[]},{"id":"c8"...
id-repetidoErrID{"id":"a","tipo":"texto","props":{}}
id-com-espacoErrID{"versao":2,"secoes":[{"id":"a b","colunas":[{"id":"a bc","itens":[]}]}]}
ancora-repetidaErrAncora{"versao":2,"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}],"ancora":"x"},{"id":"b","colunas":[{"id":"bc","itens":[]}],"ancora":"x"}]}
tipo-desconhecidoErrTipoDesconhecido{"id":"b","tipo":"hero","props":{}}
prop-desconhecidaErrPropInvalida{"id":"b","tipo":"titulo","props":{"style":"color:red"}}
url-javascriptErrPropInvalida{"id":"b","tipo":"botao","props":{"url":"javascript:alert(1)"}}
url-protocolo-relativoErrPropInvalida{"id":"b","tipo":"botao","props":{"url":"//evil.test"}}
midia-dataErrPropInvalida{"id":"b","tipo":"imagem","props":{"url":"data:image/png;base64,AAAA"}}
cor-livre-propErrPropInvalida{"id":"b","tipo":"botao","props":{"cor":"red;x:y"}}
botao-cor-icone-styleErrPropInvalida{"id":"b","tipo":"botao","props":{"rotulo":"Ir","cor_icone":"</style><script>"}}
botao-vidro-opacidade-101ErrPropInvalida{"id":"b","tipo":"botao","props":{"rotulo":"Ir","vidro_opacidade":101}}
titulo-nao-aceita-vidroErrPropInvalida{"id":"b","tipo":"titulo","props":{"texto":"x","vidro":true}}
l4-sobreposicao-cor-e-gradienteErrEstiloInvalido{"versao":2,"secoes":[{"id":"a","estilo":{"fundo":{"tipo":"nenhum","sobreposicao":{"cor":"#000000","gradiente":{"tipo":"linear","de":"#ffffff","para":"transparente","angulo":90},"opacidade":50}}},"colunas":[{"id":"ac","itens":[]}]}]}
pagina-fonte-titulos-nome-do-kitErrEstiloInvalido{"versao":2,"estilo":{"fonte_titulos":"Open Sans"},"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}]}]}
pagina-fonte-titulos-injecao-cssErrEstiloInvalido{"versao":2,"estilo":{"fonte_titulos":"inter;}body{display:none}"},"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}]}]}
abas-item-aninhado-abasErrEstruturaInvalida{"id":"ab","tipo":"abas","props":{"itens":[{"titulo":"A","itens":[{"id":"n","tipo":"abas","props":{}}]}]}}
abas-item-aninhado-formularioErrEstruturaInvalida{"id":"ab","tipo":"abas","props":{"itens":[{"titulo":"A","itens":[{"id":"n","tipo":"formulario","props":{"form_id":"f1"}}]}]}}
acordeao-faq-sem-respostaErrPropInvalida{"id":"ac1","tipo":"acordeao","props":{"faq":true,"itens":[{"titulo":"Pergunta?","itens":[{"id":"b","tipo":"botao","props":{"rotulo":"x"}}]}]}}
acordeao-dois-abertos-um-por-vezErrPropInvalida{"id":"ac1","tipo":"acordeao","props":{"um_por_vez":true,"itens":[{"titulo":"A","itens":[],"aberto":true},{"titulo":"B","itens":[],"aberto":true}]}}
l7-titulo-href-javascriptErrPropInvalida{"id":"b","tipo":"titulo","props":{"texto":"[x](javascript:alert(1))"}}
l3-subir-201ErrEstiloInvalido{"id":"b","tipo":"texto","props":{"texto":"a"},"estilo":{"subir":201}}
lista-longaErrLimite{"id":"b","tipo":"menu","props":{"itens":[{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},...
estilo-campo-desconhecidoErrMalformado{"id":"i1","tipo":"marca","props":{"mostrar_logo":true,"mostrar_nome":false,"altura_logo":40}}

4.4 Como consertar, por classe

SintomaCausa provávelConserto
ErrMalformadocampo inventado ou vírgula sobrandoremova o campo; releia a tabela do nível
ErrPropInvalida com caminho em props.<x>x não existe no tipo, ou valor fora da faixa/enumconfira nome, tipo e faixa na tabela do tipo
ErrPropInvalida em props.textolink da marcação [x](y) com endereço não permitidouse https://, mailto: ou tel:
ErrEstiloInvalidocor, raio, fonte, sombra ou fundo inválidoveja 3.3/3.4; fonte só da allowlist
ErrIDid repetido (inclusive entre seção e item)gere ids únicos no documento inteiro
ErrEstruturaInvalida em painelabas/acordeao/html/formulario dentro de paineltire o item do painel
ErrLimitelista, colunas ou FAQ acima do tetodivida em seções ou reduza
403item html sem nívelremova o item html

4.5 O laço de validação do agente

  1. Gere o JSON.
  2. Valide localmente contra o schema (qualquer validador JSON Schema 2020-12). O schema não confere ids únicos, âncoras únicas, o teto de 1000 itens, as regras de painel, o limite de FAQ nem a marcação inline; esses o servidor confere (confira ids e âncoras você mesmo).
  3. Envie (POST /v1/paginas ou POST /v1/paginas/{id}/versoes).
  4. 422? Leia codigo + caminho, corrija somente aquele nó e volte ao passo 3. Não reescreva o documento inteiro a cada erro.
  5. 201? Confira a página renderizada (a url_publica só abre a versão publicada) antes de publicar.

5. Mídia

Uma imagem entra no documento por URL. Dois tipos servem:

  1. Galeria da conta (recomendado). Envie o arquivo e use o url devolvido:
# upload (multipart, campo "arquivo"); 201 novo, 200 se o MESMO conteúdo já existia (dedup por hash)
curl -sS -X POST "$API/v1/midias" -H "Authorization: Bearer $KEY" \
  -F 'arquivo=@capa.jpg'
# -> { "id":"<midia-id>", "nome":"capa.jpg", "mime":"image/jpeg", "tamanho":123456,
#      "url":"https://.../v1/public/midias/<midia-id>", ... }

# importar por URL (o servidor baixa, com defesa contra SSRF)
curl -sS -X POST "$API/v1/midias/de-url" "${H[@]}" -d '{ "url": "https://exemplo.test/foto.png", "nome": "foto" }'

Use exatamente o campo url da resposta (.../v1/public/midias/<id>) em imagem.url, fundo.imagem.url, icone_img, cartoes.itens[].img etc. A leitura é pública e anônima (a página publicada precisa dela). Variantes redimensionadas: .../v1/public/midias/<id>/w/<largura> (o renderer usa no srcset). Só imagens (JPG, PNG, GIF, WebP, AVIF, SVG; o tipo é decidido pelo conteúdo, não pelo nome; SVG é sanitizado; antivírus se configurado). GET /v1/midias lista a galeria; DELETE /v1/midias/{id} apaga (não apague mídia que uma página usa).

  1. Externa https://... : aceita pelo validador, mas a página passa a depender do host de terceiros (some se ele apagar). Para algo que importa, suba para a galeria.

Vídeo não é mídia da galeria: o item video recebe uma URL de embed (ex.: https://www.youtube.com/embed/<id>).

Cópia na importação. POST /v1/paginas/importar e a galeria de templates baixam de novo cada imagem referenciada (imagem de item, galeria, fundo de seção/coluna/página, *_img, cartoes[].img, imagem de botão...) para a galeria da conta de destino e trocam as URLs; apagar a origem depois não quebra o destino. url de link e de botão nunca é baixada. O que não puder ser copiado mantém a URL original e aparece no relatório (mantido_original + motivo). Tetos: 10 MB por arquivo, 50 MB por importação, 60 URLs únicas.

6. Fluxos de trabalho

6.1 Criar do zero

  1. (Opcional) POST /v1/formularios se a página tem formulário (seção 3.8).
  2. Suba as imagens (seção 5) e anote os url.
  3. Monte o documento (receitas na seção 7) e valide.
  4. POST /v1/paginas com titulo, slug (^[a-z0-9]+(-[a-z0-9]+)*$), opcional dominio, e o template. Resposta 201 traz id, url_publica, ultima_versao: 1, versao_publicada: 0.
  5. PUT /v1/paginas/{id}/seo (opcional).
  6. Revisão humana (a página ainda não está no ar).
  7. POST /v1/paginas/{id}/publicar com {"versao": 1}.

6.2 Editar com segurança (rascunho, versão, publicação)

Semântica. Uma página tem versões imutáveis (numeradas, só crescem), um ponteiro de publicada e, no máximo, um rascunho: o auto-save do editor, uma cópia de trabalho que não é versão e não está no ar. Publicar só move o ponteiro; versões antigas continuam e publicar uma delas de novo é o rollback.

# 1) ler o estado: a última versão (ou ?versao=N) e os contadores
curl -sS "$API/v1/paginas/<id>" "${H[@]}"
# -> { "pagina": {..., "ultima_versao": 3, "versao_publicada": 2, "url_publica": "..."},
#      "template": { "versao": 2, ... }, "versao": 3 }

# 2) existe rascunho de alguém? 204 = não; 200 = sim, com o instante da última gravação
curl -sS -i "$API/v1/paginas/<id>/rascunho" "${H[@]}"
# -> 200 { "template": {...}, "rascunho_em": "2026-10-09T12:00:00.123456Z" }   |   204

# 3) gravar o SEU rascunho com controle de concorrência
curl -sS -X PUT "$API/v1/paginas/<id>/rascunho?base=<rascunho_em lido, ou vazio se era 204>" "${H[@]}" \
  -d '{ "template": { "versao": 2, "secoes": [ ... ] } }'
# -> 200 { "rascunho_em": "..." }
# -> 409 { "erro":"o rascunho foi alterado em outra aba", "codigo":"RascunhoConflito",
#          "rascunho": { "template": {...do servidor...}, "rascunho_em": "..." } }

# 4) promover a versão (aqui o documento é validado por inteiro: 422 se inválido)
curl -sS -X POST "$API/v1/paginas/<id>/versoes" "${H[@]}" -d '{ "template": { ... } }'   # -> 201 {"versao": 4}

# 5) publicar a versão pelo NÚMERO
curl -sS -X POST "$API/v1/paginas/<id>/publicar" "${H[@]}" -d '{ "versao": 4 }'          # -> 200

Nunca perca trabalho humano (regras para o agente):

  1. Nunca sobrescreva página publicada sem ordem expressa. Para alterar uma página que está no ar, trabalhe em versão nova (não publique), ou duplique (6.6), edite a cópia e peça revisão.
  2. Rascunho presente = trabalho humano em andamento. Se GET .../rascunho devolveu 200, não o substitua: parta dele (ele é o estado mais novo), grave com ?base=<rascunho_em>, ou pare e informe. Nunca use DELETE .../rascunho por conta própria.
  3. Publique pelo número ({"versao": N}), a versão que você acabou de salvar e validar; não publique "a última" às cegas (uma pessoa pode ter salvado outra no meio).
  4. Para desfazer, publique a versão anterior (versao_publicada antes de você mexer).
  5. Conflito (409)? Leia o corpo, preserve os dois lados e decida com o humano; nunca force.
  6. Guarde o ultima_versao/versao_publicada que você leu e confira antes de publicar.

6.3 Importar e exportar (envelopes)

O arquivo exportado pelo editor (e os 15 link-bios de referência em asender_archive/link-bios/) tem este envelope (asender_pages_template: 2, até 256 KB):

{
  "asender_pages_template": 2,
  "nome": "Minha landing",
  "descricao": "opcional",
  "seo": { "titulo": "Minha landing", "descricao": "...", "og_titulo": "..." },
  "template": { "versao": 2, "secoes": [ ... ] }
}

seo é opcional e não leva canonical_url. Para importar por API, desembrulhe o envelope e chame POST /v1/paginas/importar, que valida como a criação, copia a mídia para a conta, cria a página despublicada e grava o SEO:

curl -sS -X POST "$API/v1/paginas/importar" "${H[@]}" -d '{
  "slug": "minha-landing", "titulo": "Minha landing",
  "template": { "versao": 2, "secoes": [ ... ] },
  "seo": { "titulo": "Minha landing" }
}'
# -> 201 { "pagina": {...}, "importacao": { "itens":[...], "avisos":[...], "copiadas":3, "ja_na_conta":0,
#                                           "mantidas":0, "copia_disponivel":true, "seo_aplicado":true } }

Se alguma imagem não pôde ser copiada, POST /v1/paginas/{id}/midias/copiar tenta de novo (grava versão nova só se algo mudou). 409 se o endereço (slug + domínio) já existe (checado antes de copiar). Para exportar: GET /v1/paginas/{id} e monte o envelope com o template.

6.4 Ações em massa

POST /v1/paginas/lote (sessão): publicar, despublicar, duplicar, mudar_dominio, até 100 páginas por chamada, resultado por página (sem tudo-ou-nada), simular: true para ver o efeito sem escrever. Detalhes e política de rascunho (pular / publicar_salva) no guia de Páginas.

6.5 Mudar o domínio (301 do endereço antigo)

PUT /v1/paginas/{id}/dominio com {"dominio_id": "...", "caminho": "novo-slug"} (sessão ou API key pages:write; dominio_id: "" = host da plataforma, caminho: "" mantém o slug). Se a página já esteve no ar, o endereço antigo passa a responder 301 (308 para métodos que não são GET/HEAD) para o novo, preservando a query string; repetir o pedido é idempotente. 409 com motivo: caminho_em_uso ou pagina_inicial; 422 com dominio_nao_verificado ou caminho_invalido. Domínio próprio exige posse verificada (TXT) antes de qualquer uso.

6.6 Duplicar

POST /v1/paginas/lote com {"acao":"duplicar","ids":["<id>"]} cria uma cópia despublicada (slug com -copia). É a forma segura de iterar sobre uma página que está no ar: edite a cópia, revise, publique a cópia e, se for o caso, troque os endereços com PUT .../dominio.

6.7 O que a API não faz

Não existe exclusão de página nem exclusão em massa, nem listagem de versões (use ultima_versao e GET /v1/paginas/{id}?versao=N). Páginas v1 antigas continuam lidas, mas o conteúdo novo deve ser v2.

7. Receitas completas

Todas validam no schema, no validador Go e no validador TS (teste de CI). As imagens usam o domínio de teste exemplo.test: troque pelos url da sua galeria. Os ids são só exemplos.

Uma coluna estreita, avatar, nome, bio com marcação inline, lista de links com vidro, redes sociais e rodapé; tema escuro com degradê e textura.

{
  "versao": 2,
  "estilo": {
    "tema": "escuro",
    "fonte_titulos": "montserrat",
    "fonte_texto": "inter",
    "fundo": {
      "tipo": "gradiente",
      "gradiente": {
        "tipo": "linear",
        "de": "#0f172a",
        "para": "#1e293b",
        "angulo": 160
      }
    },
    "padrao": {
      "tipo": "pontos",
      "opacidade": 6,
      "tamanho": 24
    }
  },
  "secoes": [
    {
      "id": "bio",
      "nome": "Perfil e links",
      "estilo": {
        "largura": "contida",
        "largura_max": 480,
        "padding": {
          "topo": 48,
          "direita": 16,
          "base": 48,
          "esquerda": 16
        }
      },
      "colunas": [
        {
          "id": "bio-col",
          "alinhamento_horizontal": "centro",
          "gap": 16,
          "itens": [
            {
              "id": "bio-foto",
              "tipo": "imagem",
              "props": {
                "url": "https://exemplo.test/avatar.jpg",
                "alt": "Foto da Ana Souza",
                "forma": "circulo",
                "largura": 112,
                "proporcao": "1:1",
                "borda": 3,
                "cor_borda": "acento"
              }
            },
            {
              "id": "bio-nome",
              "tipo": "titulo",
              "props": {
                "texto": "Ana Souza",
                "nivel": 1,
                "tamanho": "g"
              },
              "estilo": {
                "alinhamento": "centro"
              }
            },
            {
              "id": "bio-resumo",
              "tipo": "texto",
              "props": {
                "texto": "Designer de [[interfaces]] e marcas. Veja o [portfólio](https://exemplo.test/portfolio).",
                "variante": "suave",
                "destaque_cor": "acento"
              },
              "estilo": {
                "alinhamento": "centro"
              }
            },
            {
              "id": "bio-links",
              "tipo": "links",
              "props": {
                "estilo": "suave",
                "tamanho": "g",
                "efeito": "elevar",
                "raio": 16,
                "vidro": true,
                "vidro_opacidade": 30,
                "itens": [
                  {
                    "titulo": "Portfólio",
                    "texto": "Projetos recentes",
                    "url": "https://exemplo.test/portfolio",
                    "icone": "site",
                    "nova_aba": true,
                    "destaque": true
                  },
                  {
                    "titulo": "Agende uma conversa",
                    "url": "https://exemplo.test/agenda",
                    "icone": "calendario",
                    "icone_fundo": "circulo",
                    "cor": "acento",
                    "cor_texto": "#0f172a"
                  },
                  {
                    "titulo": "Fale no WhatsApp",
                    "url": "https://wa.me/5511900000000",
                    "icone": "whatsapp",
                    "nova_aba": true
                  },
                  {
                    "titulo": "E-mail",
                    "url": "mailto:ana@exemplo.test",
                    "icone": "email"
                  }
                ]
              }
            },
            {
              "id": "bio-redes",
              "tipo": "redes",
              "props": {
                "tamanho": "m",
                "itens": [
                  {
                    "rede": "instagram",
                    "url": "https://instagram.com/exemplo"
                  },
                  {
                    "rede": "linkedin",
                    "url": "https://linkedin.com/in/exemplo"
                  },
                  {
                    "rede": "github",
                    "url": "https://github.com/exemplo"
                  }
                ]
              }
            },
            {
              "id": "bio-rodape",
              "tipo": "texto",
              "props": {
                "texto": "© 2026 Ana Souza",
                "variante": "suave",
                "tamanho": "p"
              },
              "estilo": {
                "alinhamento": "centro",
                "margem": {
                  "topo": 16
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

7.2 Landing com hero, cartões e FAQ

Cabeçalho fixo com menu e âncoras, hero em duas colunas, três cartões em grade, FAQ (acordeao com faq: true, gera JSON-LD) e chamada final.

{
  "versao": 2,
  "estilo": {
    "tema": "claro",
    "fonte_titulos": "poppins",
    "fonte_texto": "inter",
    "fundo": {
      "tipo": "cor",
      "cor": "#ffffff"
    }
  },
  "secoes": [
    {
      "id": "topo",
      "nome": "Cabeçalho",
      "comportamento": "fixa_topo",
      "estilo": {
        "fundo": {
          "tipo": "cor",
          "cor": "#ffffff"
        },
        "borda": {
          "largura": 1,
          "cor": "borda",
          "lados": [
            "base"
          ]
        },
        "padding": {
          "topo": 12,
          "direita": 24,
          "base": 12,
          "esquerda": 24
        }
      },
      "colunas": [
        {
          "id": "topo-marca",
          "largura": 1,
          "alinhamento_vertical": "centro",
          "itens": [
            {
              "id": "topo-logo",
              "tipo": "marca",
              "props": {
                "mostrar_logo": true,
                "mostrar_nome": true,
                "altura_logo": 32
              }
            }
          ]
        },
        {
          "id": "topo-menu",
          "largura": 2,
          "alinhamento_vertical": "centro",
          "alinhamento_horizontal": "fim",
          "itens": [
            {
              "id": "topo-nav",
              "tipo": "menu",
              "props": {
                "orientacao": "horizontal",
                "colapsar_celular": true,
                "itens": [
                  {
                    "rotulo": "Benefícios",
                    "url": "#beneficios"
                  },
                  {
                    "rotulo": "Perguntas",
                    "url": "#faq"
                  },
                  {
                    "rotulo": "Contato",
                    "url": "#contato"
                  }
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "id": "hero",
      "nome": "Hero",
      "ancora": "inicio",
      "layout_celular": "empilhar",
      "estilo": {
        "fundo": {
          "tipo": "gradiente",
          "gradiente": {
            "tipo": "linear",
            "de": "#eef2ff",
            "para": "#ffffff",
            "angulo": 180
          }
        },
        "padding": {
          "topo": 80,
          "direita": 24,
          "base": 80,
          "esquerda": 24
        },
        "padding_celular": {
          "topo": 40,
          "direita": 16,
          "base": 40,
          "esquerda": 16
        },
        "alinhamento_vertical": "centro"
      },
      "colunas": [
        {
          "id": "hero-texto",
          "largura": 6,
          "gap": 20,
          "itens": [
            {
              "id": "hero-selo",
              "tipo": "selo",
              "props": {
                "texto": "Novo · versão 2"
              }
            },
            {
              "id": "hero-titulo",
              "tipo": "titulo",
              "props": {
                "texto": "Organize seus pedidos sem [[planilhas]]",
                "nivel": 1,
                "tamanho": "gg",
                "destaque_cor": "acento"
              }
            },
            {
              "id": "hero-sub",
              "tipo": "texto",
              "props": {
                "texto": "Cadastre, acompanhe e entregue. Tudo em um só lugar, em minutos.",
                "tamanho": "g",
                "variante": "suave"
              }
            },
            {
              "id": "hero-cta",
              "tipo": "botao",
              "props": {
                "rotulo": "Começar grátis",
                "url": "#contato",
                "variante": "solido",
                "tamanho": "g",
                "icone_dir": "seta"
              }
            },
            {
              "id": "hero-cta2",
              "tipo": "botao",
              "props": {
                "rotulo": "Ver como funciona",
                "url": "#beneficios",
                "variante": "texto",
                "tamanho": "m"
              }
            }
          ]
        },
        {
          "id": "hero-imagem",
          "largura": 6,
          "alinhamento_vertical": "centro",
          "itens": [
            {
              "id": "hero-foto",
              "tipo": "imagem",
              "props": {
                "url": "https://exemplo.test/produto.jpg",
                "alt": "Tela do aplicativo mostrando a lista de pedidos",
                "forma": "arredondada",
                "proporcao": "4:3",
                "sombra": "forte"
              }
            }
          ]
        }
      ]
    },
    {
      "id": "beneficios",
      "nome": "Benefícios",
      "ancora": "beneficios",
      "estilo": {
        "padding": {
          "topo": 64,
          "direita": 24,
          "base": 64,
          "esquerda": 24
        }
      },
      "colunas": [
        {
          "id": "ben-col",
          "gap": 24,
          "alinhamento_horizontal": "centro",
          "itens": [
            {
              "id": "ben-titulo",
              "tipo": "titulo",
              "props": {
                "texto": "Por que usar",
                "nivel": 2
              },
              "estilo": {
                "alinhamento": "centro"
              }
            },
            {
              "id": "ben-cartoes",
              "tipo": "cartoes",
              "props": {
                "layout": "grade",
                "colunas": 3,
                "efeito": "elevar",
                "raio": 16,
                "sombra": "leve",
                "alinhamento_texto": "inicio",
                "icone_fundo": "circulo",
                "itens": [
                  {
                    "icone": "raio",
                    "titulo": "Rápido",
                    "texto": "Cadastre um pedido em menos de dez segundos.",
                    "tag": "Produtividade"
                  },
                  {
                    "icone": "escudo",
                    "titulo": "Seguro",
                    "texto": "Seus dados ficam separados dos de outras contas.",
                    "tag": "Confiança"
                  },
                  {
                    "icone": "grafico",
                    "titulo": "Claro",
                    "texto": "Relatórios simples para decidir o que fazer amanhã.",
                    "tag": "Controle"
                  }
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "id": "faq",
      "nome": "Perguntas frequentes",
      "ancora": "faq",
      "estilo": {
        "largura": "contida",
        "largura_max": 760,
        "padding": {
          "topo": 64,
          "direita": 24,
          "base": 64,
          "esquerda": 24
        }
      },
      "colunas": [
        {
          "id": "faq-col",
          "gap": 24,
          "itens": [
            {
              "id": "faq-titulo",
              "tipo": "titulo",
              "props": {
                "texto": "Perguntas frequentes",
                "nivel": 2
              }
            },
            {
              "id": "faq-acordeao",
              "tipo": "acordeao",
              "props": {
                "faq": true,
                "um_por_vez": true,
                "nivel": 3,
                "estilo": "cartao",
                "indicador": "seta",
                "itens": [
                  {
                    "titulo": "Preciso instalar alguma coisa?",
                    "aberto": true,
                    "itens": [
                      {
                        "id": "faq-r1",
                        "tipo": "texto",
                        "props": {
                          "texto": "Não. Funciona no navegador, no computador ou no celular."
                        }
                      }
                    ]
                  },
                  {
                    "titulo": "Posso cancelar quando quiser?",
                    "itens": [
                      {
                        "id": "faq-r2",
                        "tipo": "texto",
                        "props": {
                          "texto": "Sim. Não há fidelidade e você exporta seus dados a qualquer momento."
                        }
                      }
                    ]
                  },
                  {
                    "titulo": "Como falo com o suporte?",
                    "itens": [
                      {
                        "id": "faq-r3",
                        "tipo": "texto",
                        "props": {
                          "texto": "Escreva para [suporte@exemplo.test](mailto:suporte@exemplo.test); respondemos em até um dia útil."
                        }
                      }
                    ]
                  }
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "id": "final",
      "nome": "Chamada final",
      "ancora": "contato",
      "estilo": {
        "fundo": {
          "tipo": "cor",
          "cor": "acento"
        },
        "padding": {
          "topo": 56,
          "direita": 24,
          "base": 56,
          "esquerda": 24
        }
      },
      "colunas": [
        {
          "id": "final-col",
          "gap": 16,
          "alinhamento_horizontal": "centro",
          "itens": [
            {
              "id": "final-titulo",
              "tipo": "titulo",
              "props": {
                "texto": "Pronto para começar?",
                "nivel": 2
              },
              "estilo": {
                "alinhamento": "centro"
              }
            },
            {
              "id": "final-botao",
              "tipo": "botao",
              "props": {
                "rotulo": "Criar minha conta",
                "url": "https://exemplo.test/cadastro",
                "variante": "contorno",
                "tamanho": "g",
                "nova_aba": true
              }
            }
          ]
        }
      ]
    }
  ]
}

7.3 Página com formulário

Crie o formulário (seção 3.8), copie o id e troque SUBSTITUA_PELO_ID_DO_FORMULARIO.

{
  "versao": 2,
  "estilo": {
    "tema": "claro",
    "fonte_titulos": "manrope",
    "fonte_texto": "inter"
  },
  "secoes": [
    {
      "id": "contato",
      "nome": "Contato",
      "ancora": "contato",
      "estilo": {
        "largura": "contida",
        "largura_max": 560,
        "padding": {
          "topo": 64,
          "direita": 16,
          "base": 64,
          "esquerda": 16
        }
      },
      "colunas": [
        {
          "id": "contato-col",
          "gap": 16,
          "itens": [
            {
              "id": "contato-titulo",
              "tipo": "titulo",
              "props": {
                "texto": "Fale com a gente",
                "nivel": 1
              }
            },
            {
              "id": "contato-texto",
              "tipo": "texto",
              "props": {
                "texto": "Deixe seu e-mail e retornamos em até um dia útil.",
                "variante": "suave"
              }
            },
            {
              "id": "contato-form",
              "tipo": "formulario",
              "props": {
                "form_id": "SUBSTITUA_PELO_ID_DO_FORMULARIO",
                "rotulo": "Enviar mensagem"
              }
            },
            {
              "id": "contato-lgpd",
              "tipo": "texto",
              "props": {
                "texto": "Usamos seus dados só para responder a esta mensagem.",
                "variante": "suave",
                "tamanho": "p"
              }
            }
          ]
        }
      ]
    }
  ]
}

8. Checklist e prompt para agentes

8.1 Checklist

8.2 Prompt para colar no agente

Você cria e edita páginas do Asender Pages pela API https://api.pages.asender.net.
Fonte da verdade: https://docs.asender.net/guias/pages-documento-v2.html (e llms-full.txt).

REGRAS
1. Escreva SEMPRE documentos {"versao": 2, "secoes": [...]} (seção > colunas > itens). Cada seção tem
   "id" e "colunas"; cada coluna tem "id" e "itens"; cada item tem "id", "tipo" e "props" (objeto).
2. Use SOMENTE os campos documentados para cada tipo (titulo, texto, imagem, botao, tags, links, cartoes,
   abas, acordeao, redes, menu, formulario, video, divisor, espacador, icone, selo, contador, marca, html).
   Campo desconhecido é recusado. Não use o tipo "html" (privilegiado).
3. "id": ^[A-Za-z0-9_-]{1,64}$, ÚNICO no documento inteiro (inclusive itens dentro de abas/acordeão).
   "ancora" de seção: ^[a-z][a-z0-9-]{0,63}$, única.
4. Cores: "#rrggbb", "#rrggbbaa" ou token (acento, texto, suave, fundo, superficie, borda, transparente).
   Nunca nomes de cor CSS, rgb() ou CSS livre. Fontes (estilo.fonte_titulos/fonte_texto): somente
   comfortaa, urbanist, montserrat, inter, poppins, open-sans, nunito, playfair-display, merriweather,
   dm-sans, manrope, raleway.
5. URLs de link: http, https, mailto, tel, "#ancora" ou "/caminho" (nunca "//" nem javascript:).
   URLs de mídia: https://host/... ou /caminho, sem aspas, espaços ou parênteses. Imagens: suba por
   POST /v1/midias (multipart, campo "arquivo") e use o campo "url" devolvido.
6. Texto de titulo/texto aceita [rótulo](https://...) e [[destaque]]; nada de HTML.
7. Limites: 200 seções, 12 colunas/seção, 100 itens/coluna, 1000 itens/página, listas até 50 entradas,
   abas/acordeão até 20 painéis (um nível, sem html/formulario/abas/acordeao dentro).

FLUXO
- Criar: POST /v1/paginas {"titulo","slug","template"} -> nasce DESPUBLICADA.
- Editar: GET /v1/paginas/{id} (template + ultima_versao + versao_publicada); GET /v1/paginas/{id}/rascunho.
  Se houver rascunho (200), é trabalho humano: parta dele e grave com PUT .../rascunho?base=<rascunho_em>
  (409 RascunhoConflito = preserve os dois lados, não force). Para versionar: POST .../versoes {"template"}.
- Publicar: SOMENTE com autorização do usuário, pelo número: POST .../publicar {"versao": N}.
  Nunca sobrescreva uma página publicada sem ordem expressa; prefira duplicar (POST /v1/paginas/lote
  {"acao":"duplicar","ids":[...]}) e editar a cópia. Rollback = publicar a versão anterior.
- Nunca chame DELETE .../rascunho. Não há exclusão de página.

VALIDAÇÃO
- Valide o JSON contra o schema (pages-documento-v2.schema.json) antes de enviar.
- Se vier 422 {"erro","codigo","caminho"}: corrija SOMENTE o nó em "caminho" conforme "codigo" e reenvie
  (ErrPropInvalida/ErrEstiloInvalido = valor ou campo fora do contrato; ErrID/ErrAncora = repetido ou
  mal formado; ErrLimite = teto; ErrEstruturaInvalida = tipo proibido em painel ou enum). Repita até 201.
- Em testes use apenas e-mails @exemplo.test e imagens de exemplo.test; nunca dados reais de terceiros.

9. Manutenção deste guia

As seções de referência (3.1 a 3.6, 4.1, 4.3 e 7) são geradas. Mudou o contrato do documento (schema, Go, TS)? Rode:

node scripts/docs-pages/gerar-referencia.mjs           # reescreve os blocos gerados deste arquivo
node scripts/docs-pages/gerar-referencia.mjs --check   # CI: falha se o guia está defasado
node --test scripts/docs-pages/documento-v2.test.mjs   # guia em dia + receitas no schema

e commite este arquivo. As notas em prosa das tabelas (finalidade de cada tipo, descrição e padrão de cada prop) ficam em scripts/docs-pages/referencia-notas.mjs; o gerador reprova nota sobre prop que saiu do schema. Receitas: asender_docs/apis/pages/exemplos-v2/*.json; cada uma é validada contra o schema (node), o validador Go (receitas_docs_test.go) e o validador TS (receitas-docs.test.ts).