Pular para o conteúdo

Publicar posts

POST /v1/posts é a única chamada que cria conteúdo. Com status: "published" ela também publica, então uma única requisição leva um post do nada até o ar.

  • URL: POST https://api.canverly.com/v1/posts
  • Escopo: posts:write
  • Content-Type: application/json
  • Tamanho máximo do corpo: 4 MiB (maior → 413)
Campo Tipo Obrigatório Observações
title string sim O título do post.
blocks_json object sim O corpo como um documento de blocos: { "v": 1, "blocks": [...] }.
status string não "draft" (padrão) ou "published". "publish"/"public"/"live" são aceitos como aliases de publicado.
slug string não Slug da URL. Derivado automaticamente de title quando omitido.
excerpt string não Resumo curto; armazenado como a descrição de SEO.
language string não Tag BCP-47. O padrão é "pt-BR".
post_type string não "post" (padrão), "page" ou o slug de um tipo de post personalizado vindo de GET /v1/post-types.
category_slugs string[] não Slugs de categoria. Alimentam os arquivos de categoria do site.
tag_slugs string[] não Slugs de tag.
  • status: "draft" (padrão) — o post é criado, mas não fica visível no site público. Use isso para preparar conteúdo; publique depois pelo admin.
  • status: "published" — o post é criado, categorizado e publicado na mesma chamada. Ele fica no ar imediatamente em https://<site-domain>/<slug>.

category_slugs / tag_slugs são armazenados no post e alimentam os arquivos de categoria e de tag do site. Use os slugs configurados para o site (ex.: news, tutorials). Slugs desconhecidos são armazenados como vieram; crie a categoria/tag correspondente no admin para que a página de arquivo exista.

Isto publica um artigo completo — título, slug, resumo, categoria e um corpo com blocos variados (parágrafo, título, lista, código):

Janela do terminal
curl -X POST https://api.canverly.com/v1/posts \
-H "Authorization: Bearer ck_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Shipping faster with the Canverly API",
"slug": "shipping-faster-with-the-canverly-api",
"status": "published",
"language": "en",
"excerpt": "How to automate publishing end to end.",
"category_slugs": ["engineering"],
"tag_slugs": ["api", "automation"],
"blocks_json": {
"v": 1,
"blocks": [
{ "id": "p1", "type": "paragraph",
"text": "You can publish from any tool with one authenticated call." },
{ "id": "h1", "type": "heading", "attrs": { "level": 2 }, "text": "Why blocks" },
{ "id": "l1", "type": "list", "attrs": { "style": "unordered" },
"text": "Portable across themes\nSafe (sanitized)\nEasy to generate" },
{ "id": "c1", "type": "code", "attrs": { "language": "bash" },
"text": "curl -X POST https://api.canverly.com/v1/posts" }
]
}
}'

201 Created:

{
"id": "01K8Z9K3F7T8M2QYV5N6B4WJ8R",
"slug": "shipping-faster-with-the-canverly-api",
"status": "published",
"public_url": null
}
  • id — o ULID do post (Crockford base32). Guarde-o para correlacionar com o seu sistema de origem.
  • slug — o slug final (pode diferir do que você enviou se tiver sido normalizado).
  • status — "published" ou "draft".

Um post publicado fica acessível em https://<site-domain>/<slug>. Resolva <site-domain> uma vez por GET /v1/sites/me (primary_domain) e então:

Janela do terminal
curl -s -o /dev/null -w "%{http_code}\n" https://blog.example.com/shipping-faster-with-the-canverly-api
# 200

Para publicar em um tipo de post personalizado (CPT), defina post_type com o slug dele. Descubra os slugs válidos antes com GET /v1/post-types. post e page sempre existem.

Autopostadores repetem a requisição em caso de timeout. Para tornar as repetições seguras, envie um cabeçalho Idempotency-Key — um id opaco derivado do seu item de origem (ex.: o id na origem):

Janela do terminal
curl -X POST https://api.canverly.com/v1/posts \
-H "Authorization: Bearer ck_live_xxx" \
-H "Idempotency-Key: feed-item-2026-0042" \
-H "Content-Type: application/json" \
-d '{ "title": "…", "status": "published", "blocks_json": { "v": 1, "blocks": [] } }'

A primeira chamada cria o post; qualquer repetição com a mesma chave e o mesmo corpo devolve o 201 original (com Idempotency-Replayed: true) em vez de criar uma duplicata. A resposta fica em cache por 24 horas, com escopo por chave de API.