Referência OpenAPI: API de conteúdo (canverly-api)
Esta página é gerada no build a partir de
docs/openapi.yamlno repositóriocanverly-api. Não edite à mão: a fonte é a especificação.
- Versão da especificação:
1.0.0 - Total de operações: 27
- Servidores declarados:
https://api.canverly.com - Especificação publicada (YAML): /specs/content-openapi.yaml
Public REST API for programmatic publishing into Canverly sites. Any tool can integrate (no-code autoposters, custom CMS bridges, AI agents, CI jobs).
Authentication: Authorization: Bearer ck_<token>. A key is created in
the admin under Configurações → Integrações API and shown once. Each key
is bound to exactly one site; the site_id is derived from the key, never
from the request body — a key can only ever write to its own site.
Rate limit: 60 requests/minute per key (token bucket) → 429.
Scopes: posts:write, posts:read, post_types:read, sites:read,
media:read, media:write, site:read, site:write, seo:read,
seo:write, analytics:read, leads:read, export, import. Scopes are
opt-in per key — a key only carries what was requested when it was created.
leads:read reads PII (form submissions): it is never granted by default,
every read/export is audited, and it has its own stricter rate limit
(10/min) on top of the general 60/min. Bulk import also requires
posts:write; bulk export of posts also requires posts:write (it
includes drafts), and bulk export of leads also requires leads:read.
Content is a block document (blocks_json), not raw HTML. Inline HTML
inside block text is allowlist-sanitized server-side (scripts stripped).
Operações
Seção intitulada “Operações”GET /v1/posts
Seção intitulada “GET /v1/posts”Listar publicações do site (leitura pública)
Acervo público paginado do site da chave. Devolve só o que é
público: rascunho, agendado no futuro e restrito não são filtrados na
apresentação — a consulta nunca os seleciona. Paginação por keyset
(cursor opaco sobre published_at + id), nunca OFFSET.
O corpo do post NÃO vem na listagem; use o detalhe.
Autenticação: apiKey, publicReadKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
limit |
query | não | 1..50. Fora da faixa devolve 400 — o valor NUNCA é cortado em silêncio. |
cursor |
query | não | Cursor opaco vindo do next_cursor da página anterior. |
category |
query | não | Slug de categoria; separe por vírgula para casar QUALQUER. |
tag |
query | não | Slug de tag; separe por vírgula para casar QUALQUER. |
q |
query | não | Busca em título e resumo. |
since |
query | não | RFC-3339. Só posts com updated_at >= since — é o gancho de sincronização incremental do instalável. |
language |
query | não | Tag BCP-47, ex. pt-BR. |
status |
query | não | Estados separados por vírgula: draft, scheduled, published, archived (deleted NÃO é listável — post apagado é soft-delete e fica fora da API pública). Mandar este parâmetro TROCA a superfície: passa a valer só chave secreta ck_ com o escopo posts:write (chave pública pk_ recebe 403, nunca conteúdo), os itens viram PostSummary (sem corpo) e a resposta deixa de ser cacheável (private, no-store, sem ETag). Valor desconhecido devolve 400. Omitir mantém exatamente o comportamento público de hoje. |
post_type |
query | não | Slug de tipo de post. Só vale junto de status — a listagem pública já se restringe aos tipos públicos no SQL do authoring. |
key |
query | não | Chave pública de leitura na query, para quem chama do navegador: mantém a requisição “simples” para o CORS e evita a viagem de preflight que o cabeçalho Authorization obriga. Só aceita pk_ — uma ck_ aqui devolve 400, porque vazaria para log de acesso, Referer e histórico do navegador. Ignorada quando há cabeçalho Authorization. |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Página do acervo público |
304 |
Não modificado (só no modo público — a listagem autenticada não emite ETag) |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
POST /v1/posts
Seção intitulada “POST /v1/posts”Criar (e opcionalmente publicar) um post
Cria um post no site da chave. Com status: "published" o post é
publicado e fica imediatamente visível no site. category_slugs /
tag_slugs são gravados em seo_jsonb (usados pelos arquivos de
categoria/tag do site público).
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
Idempotency-Key |
header | não | Opaque client-generated id. A replay with the same key AND the same body returns the original 201 (header Idempotency-Replayed: true) and does not create a duplicate. Cached 24h, scoped per api key. |
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: application/json (CreatePost)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
201 |
Post criado (e publicado, se solicitado) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
422 |
Requisição válida mas não-processável (ex. chave antiga sem contexto de autoria) |
429 |
Rate limit (60/min) excedido |
GET /v1/posts/{reference}
Seção intitulada “GET /v1/posts/{reference}”Obter uma publicação por id ou slug (leitura pública)
Mesmo portão público da listagem. Rascunho, agendado, restrito e post de outro site respondem 404 — indistinguível de inexistente, de propósito: um 403 confirmaria que o rascunho alheio existe.
content_html é o corpo já renderizado e sanitizado na saída
(allowlist). Sem <script>, <iframe> ou <form>; blocos de anúncio e
de cartão de produto são omitidos; embed de vídeo vira link.
Autenticação: apiKey, publicReadKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
reference |
path | sim | ULID (26), UUID (36) ou slug. |
key |
query | não | Chave pública de leitura na query, para quem chama do navegador: mantém a requisição “simples” para o CORS e evita a viagem de preflight que o cabeçalho Authorization obriga. Só aceita pk_ — uma ck_ aqui devolve 400, porque vazaria para log de acesso, Referer e histórico do navegador. Ignorada quando há cabeçalho Authorization. |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Publicação pública com corpo |
304 |
Não modificado |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
PATCH /v1/posts/{reference}
Seção intitulada “PATCH /v1/posts/{reference}”Editar um post existente, por id ou slug
Patch parcial — só os campos enviados mudam. A referência funciona como no GET: id (ULID/UUID) ou slug. Diferente do GET, a busca por slug aqui também encontra post que ainda NÃO está no ar (rascunho e agendado) — é o que permite corrigir pela API um post criado sem que o id tenha sido guardado.
published_at (RFC3339) move/retroage a data de um post no ar e
re-pinga o IndexNow. featured_image_id define a capa a partir de um id
de asset de POST /v1/media; mande null para limpar, ou omita o campo
para não mexer. A chave só edita post do próprio site.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
reference |
path | sim | Id do post (ULID 26 / UUID 36) ou slug. O slug é resolvido dentro do site desta chave: primeiro os publicados, depois TODOS os rascunhos e agendados — sem janela e sem teto de quantidade. Post ARQUIVADO continua sendo referenciado por id. Se o mesmo slug existir em mais de um idioma, a resposta é 400 pedindo ?language= — nunca uma escolha silenciosa, que editaria o post errado. |
language |
query | não | Tag BCP-47, usada SÓ para desambiguar slug — a unicidade é por (site, slug, language), então o mesmo slug pode existir em dois idiomas. Sem este parâmetro, esse caso devolve 400 pedindo desambiguação, em vez de editar o post errado em silêncio. Ignorado quando a referência já é um id. |
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: application/json (UpdatePost)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Post atualizado |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
GET /v1/post-types
Seção intitulada “GET /v1/post-types”Listar tipos de post (CPT) do site
Autenticação: apiKey
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Lista de tipos de post |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
GET /v1/sites/me
Seção intitulada “GET /v1/sites/me”Dados do site da chave
Autenticação: apiKey
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Site resolvido a partir da chave |
401 |
Chave ausente ou inválida |
GET /v1/media
Seção intitulada “GET /v1/media”Listar os assets de mídia do site
Mais recentes primeiro. Sem cursor: paginação por limit (1..500).
Filtros opcionais folder_id / tag_id.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
limit |
query | não | 1..500. Fora da faixa devolve 400 — nunca cortado em silêncio. |
folder_id |
query | não | — |
tag_id |
query | não | — |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Página de assets do site |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
POST /v1/media
Seção intitulada “POST /v1/media”Subir um asset de mídia (multipart)
Upload multipart com um campo file. O asset é gravado no site da chave;
as variantes são geradas de forma assíncrona (resposta com
status: processing). Teto de corpo: 8 MiB.
Autenticação: apiKey
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: multipart/form-data (object)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
202 |
Aceito — asset gravado, variantes processando |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
413 |
Corpo do upload acima de 8 MiB |
415 |
Tipo de mídia não suportado |
429 |
Rate limit (60/min) excedido |
GET /v1/media/{id}
Seção intitulada “GET /v1/media/{id}”Obter um asset de mídia
Um id de outro site responde 404 — a existência não é revelada.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
id |
path | sim | — |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Asset de mídia |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
DELETE /v1/media/{id}
Seção intitulada “DELETE /v1/media/{id}”Apagar um asset de mídia
Soft-delete do asset. Um id de outro site responde 404.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
id |
path | sim | — |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
204 |
Apagado |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
GET /v1/sites/me/settings
Seção intitulada “GET /v1/sites/me/settings”Ler as configurações editáveis do site
Autenticação: apiKey
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Configurações do site |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
PATCH /v1/sites/me/settings
Seção intitulada “PATCH /v1/sites/me/settings”Atualizar as configurações do site
Só campos permitidos são aplicados; settings é MESCLADO sobre o blob
gravado (chaves: social, footer_columns, legal_links, search,
customization, advanced, subscriptions_enabled, language_url_mode).
org_id/status/site_id/slug do corpo são ignorados. Corpo sem
nada editável é 400.
Autenticação: apiKey
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: application/json (SiteSettingsPatch)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Configurações atualizadas |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
GET /v1/sites/me/seo
Seção intitulada “GET /v1/sites/me/seo”Ler o SEO no nível do site
Autenticação: apiKey
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
SEO do site |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
PATCH /v1/sites/me/seo
Seção intitulada “PATCH /v1/sites/me/seo”Atualizar o SEO no nível do site
Chaves de SEO permitidas, mescladas em settings.seo. Corpo sem nada
editável é 400.
Autenticação: apiKey
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: application/json (SiteSeo)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
SEO atualizado |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
POST /v1/posts/{reference}/unpublish
Seção intitulada “POST /v1/posts/{reference}/unpublish”Tirar do ar um post publicado
Move o post de published para archived, emite o evento de
despublicação e PURGA a página em cache. A referência é o id (ULID) ou o
slug.
NÃO é remoção: o post sai do site e continua no acervo. Post que não está publicado responde 409 — conflito de estado, não falha de servidor.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
reference |
path | sim | — |
language |
query | não | Desambigua um slug que existe em mais de um idioma. |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Post despublicado |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
409 |
O post não está publicado (conflito de estado) |
429 |
Rate limit (60/min) excedido |
GET /v1/posts/{reference}/seo
Seção intitulada “GET /v1/posts/{reference}/seo”Ler o SEO de um post
A referência é o id do post (ULID) ou o slug, com a mesma resolução
do GET /v1/posts/{reference}. Post de outro site responde 404.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
reference |
path | sim | — |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
SEO do post |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
PATCH /v1/posts/{reference}/seo
Seção intitulada “PATCH /v1/posts/{reference}/seo”Atualizar o SEO de um post
Só chaves de SEO permitidas; mescladas no seo_json do post. Corpo sem
nada editável é 400.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
reference |
path | sim | — |
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: application/json (PostSeo)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
SEO atualizado |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
GET /v1/posts/{reference}/source
Seção intitulada “GET /v1/posts/{reference}/source”Ler a fonte editável de um post (documento de blocos)
O post como o dono o edita: metadados, taxonomia (lida do SEO do post)
e blocks_json EXATAMENTE como armazenado — sem renderizar e sem
sanitizar. Leia, modifique e devolva pelo
PATCH /v1/posts/{reference}.
Existe porque o GET /v1/posts/{reference} só devolve content_html
renderizado (blocos de anúncio/cartão de produto/story saem vazios), e
reconverter aquele HTML num PATCH apagaria conteúdo.
A referência é resolvida como no PATCH: id ou slug, inclusive
rascunho e agendado. Campo ausente sai null; taxonomia ausente sai
[]. Post de outro site responde 404. A resposta sai com
Cache-Control: private, no-store (pode carregar rascunho).
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
reference |
path | sim | Id do post (ULID 26 / UUID 36) ou slug. |
language |
query | não | Tag BCP-47, usada SÓ para desambiguar slug. Ignorado quando a referência já é um id. |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Fonte editável do post |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
502 |
Falha do serviço de conteúdo, ou corpo armazenado em formato não reconhecido (nunca é devolvido como corpo vazio). |
GET /v1/analytics/summary
Seção intitulada “GET /v1/analytics/summary”Resumo de views/visitantes do site
Acessos do site na janela pedida (humanos, sem bots). from/to
(YYYY-MM-DD, UTC) têm precedência; senão o preset days (1..365,
default 30). Encaminha ao canverly-analytics com o site_id da chave.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
from |
query | não | Início da janela (YYYY-MM-DD, UTC). |
to |
query | não | Fim da janela (YYYY-MM-DD, UTC, inclusivo). |
days |
query | não | Preset de janela; ignorado se from/to vierem. |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Resumo de acessos |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
GET /v1/analytics/posts
Seção intitulada “GET /v1/analytics/posts”Views por post/página do site (paginado)
Páginas/posts mais vistos na janela, paginado por limit/offset.
Derivado do top_paths do resumo.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
from |
query | não | — |
to |
query | não | — |
days |
query | não | — |
limit |
query | não | 1..200. Fora da faixa é 400 — nunca cortado em silêncio. |
offset |
query | não | — |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Página de posts mais vistos |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
429 |
Rate limit (60/min) excedido |
GET /v1/leads
Seção intitulada “GET /v1/leads”Listar os leads (submissões de formulário) do site
LEADS SÃO PII. Exige o escopo opt-in leads:read; toda leitura é
auditada e passa por um limite de taxa próprio, mais estrito (10/min).
Recorte por form_id/status/de/ate; paginação por cursor. Um site
sem o app de formulários (ou uma chave sem membership) recebe 404. Para
um lead único, ver GET /v1/leads/{id}.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
form_id |
query | não | Restringe a um formulário (id ULID/UUID). |
status |
query | não | — |
de |
query | não | Início do período (YYYY-MM-DD ou RFC3339). |
ate |
query | não | Fim do período (inclusivo quando data). |
cursor |
query | não | — |
limit |
query | não | — |
ordem |
query | não | — |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Página de leads do site |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
422 |
Requisição válida mas não-processável (ex. chave antiga sem contexto de autoria) |
429 |
Rate limit (60/min) excedido |
GET /v1/leads/{id}
Seção intitulada “GET /v1/leads/{id}”Ler um lead único (submissão de formulário) do site
LEAD É PII. Exige o escopo opt-in leads:read; a leitura é auditada e
passa pelo limite estrito (10/min). O lead é escopado ao site da chave:
um id de outro inquilino (ou inexistente, ou site sem o app) recebe o
MESMO 404 opaco — sem oráculo de existência. Retorna o lead na mesma
forma de um item da lista.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
id |
path | sim | Id do lead (ULID/UUID). |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
O lead do site |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
GET /v1/export
Seção intitulada “GET /v1/export”Exportar um recurso em massa (NDJSON ou CSV, streaming)
Transmite resource do site em format. NDJSON = um objeto por linha;
CSV = colunas planas.
posts só em NDJSON (CSV é 400 — blocos aninhados) e exige TAMBÉM
posts:write, com chave ck_: o export de posts é o acervo INTEIRO do
dono — rascunho, agendado, publicado e arquivado (apagado não), cada
linha com o corpo em blocks_json. Ver o que ainda não está no ar é a
mesma permissão do GET /v1/posts?status=, e uma chave pk_ (que viaja
no view-source de toda página com o widget) recebe 403.
A linha do export volta a entrar por POST /v1/import: os campos
derivados (id, created_at, canonical_url, …) são descartados lá, as
taxonomias do seo_json sobem para o topo, e um post com access
restrito FALHA a linha — post pago não vira público por descuido de
importação.
leads exige TAMBÉM leads:read (auditado + limite estrito); o CSV de
leads é o do canverly-forms (colunas por formulário). analytics
exporta a série temporal.
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
resource |
query | sim | — |
format |
query | não | — |
form_id |
query | não | leads: restringe a um formulário. |
status |
query | não | leads: clean | spam | all. |
de |
query | não | leads: início do período. |
ate |
query | não | leads: fim do período. |
from |
query | não | analytics: início da janela. |
to |
query | não | analytics: fim da janela. |
days |
query | não | analytics: preset de janela. |
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Stream do recurso. Content-Type application/x-ndjson ou text/csv; Content-Disposition attachment. |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
404 |
Não encontrado, ou não público |
429 |
Rate limit (60/min) excedido |
POST /v1/import
Seção intitulada “POST /v1/import”Importar posts em massa a partir de NDJSON
Corpo NDJSON, uma linha = um post (mesmo schema de POST /v1/posts).
Exige import E posts:write. site_id/org_id/author_id NUNCA vêm
do corpo — vêm da chave (um site_id numa linha é descartado).
Idempotência por conteúdo de linha (repetir não duplica). Teto 8 MiB /
1000 linhas. Só posts nesta versão (mídia por URL não é suportada).
Autenticação: apiKey
Parâmetros
Seção intitulada “Parâmetros”| Nome | Onde | Obrigatório | Descrição |
|---|---|---|---|
resource |
query | não | — |
Corpo da requisição
Seção intitulada “Corpo da requisição”Tipos de conteúdo: application/x-ndjson (string)
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Resumo por linha |
400 |
Parâmetro inválido (ex. limit fora da faixa, cursor corrompido) |
401 |
Chave ausente ou inválida |
403 |
Escopo insuficiente — ou, para chave pública (pk_), a origem da requisição não está na allowlist da chave. A chave é válida; o lugar de onde ela está sendo usada é que não é. Cadastre a origem no painel, em Configurações → Integrações API. |
413 |
Corpo acima de 8 MiB ou mais de 1000 linhas |
429 |
Rate limit (60/min) excedido |
GET /health
Seção intitulada “GET /health”Liveness probe
Autenticação: nenhuma declarada
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Process is alive |
GET /ready
Seção intitulada “GET /ready”Readiness probe
Autenticação: nenhuma declarada
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
Ready to serve |
503 |
Not ready (Redis/JWKS/OpenAPI not loaded) |
GET /metrics
Seção intitulada “GET /metrics”Prometheus metrics
Autenticação: nenhuma declarada
Respostas
Seção intitulada “Respostas”| Status | Descrição |
|---|---|
200 |
text/plain prometheus exposition format |