POST /v1/posts
Cria um post no site dono da chave de API. Com status: "published", ele é publicado na mesma chamada.
- URL:
https://api.canverly.com/v1/posts - Método:
POST - Autenticação: chave de API Bearer — escopo
posts:write - Content-Type:
application/json - Corpo máximo: 4 MiB
- Limite de requisição: 60 req/min por chave
Para exemplos completos, em várias linguagens, veja o guia de publicação.
Requisição
Seção intitulada “Requisição”Cabeçalhos
Seção intitulada “Cabeçalhos”| Cabeçalho | Obrigatório | Valor |
|---|---|---|
Authorization |
sim | Bearer ck_… |
Content-Type |
sim | application/json |
Idempotency-Key |
não | Id opaco (≤ 255 caracteres). Um replay com a mesma chave + corpo devolve o 201 original (sem duplicata). Veja Idempotência. |
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
title |
string | sim | Título do post. Não pode ser vazio. |
blocks_json |
object | sim | Documento de blocos: { "v": 1, "blocks": [...] }. Veja Blocos de conteúdo. |
status |
string | não | "draft" (padrão) ou "published". |
slug |
string | não | Derivado automaticamente de title se omitido. |
excerpt |
string | não | Armazenado como a descrição de SEO. |
language |
string | não | BCP-47; padrão "pt-BR". |
post_type |
string | não | "post" (padrão), "page" ou um slug personalizado de /v1/post-types. |
category_slugs |
string[] | não | Slugs de categoria (alimentam os arquivos de categoria). |
tag_slugs |
string[] | não | Slugs de tag. |
{ "title": "Hello from the API", "status": "published", "slug": "hello-from-the-api", "excerpt": "A short summary.", "language": "en", "category_slugs": ["news"], "tag_slugs": ["api"], "blocks_json": { "v": 1, "blocks": [ { "id": "p1", "type": "paragraph", "text": "Body text." } ] }}Resposta
Seção intitulada “Resposta”201 Created
Seção intitulada “201 Created”{ "id": "01K8Z9K3F7T8M2QYV5N6B4WJ8R", "slug": "hello-from-the-api", "status": "published", "public_url": null}| Campo | Tipo | Observações |
|---|---|---|
id |
string | ULID do post (Crockford base32). |
slug |
string | Slug final (pode ser normalizado a partir do que você enviou). |
status |
string | "published" ou "draft". |
public_url |
string | null | Atualmente null; monte a URL como https://<primary_domain>/<slug> (veja /v1/sites/me). |
Envelope: { "error": { "code", "message" } }. Tabela completa em Erros e limites de requisição.
| Status | error.code |
Quando |
|---|---|---|
400 |
bad_request |
JSON malformado, ou title vazio. |
401 |
unauthorized |
Chave ausente/inválida/revogada. |
403 |
forbidden |
A chave não tem posts:write. |
413 |
— | Corpo acima de 4 MiB. |
415 |
— | Content-Type ausente/incorreto. |
422 |
unprocessable |
blocks_json ausente, tipo de campo errado, ou uma chave criada antes de a publicação ser habilitada. |
429 |
rate_limited |
Acima de 60 req/min — respeite o Retry-After. |
5xx |
upstream |
Transitório; tente de novo com backoff (reutilize o mesmo slug). |
Idempotência
Seção intitulada “Idempotência”Envie um cabeçalho Idempotency-Key para tornar os retries seguros. A primeira
requisição roda normalmente; a resposta 201 dela fica em cache por 24 horas. Qualquer
replay com a mesma chave e o mesmo corpo devolve essa resposta original com um
cabeçalho extra Idempotency-Replayed: true — o post é criado no máximo uma vez.
curl -X POST https://api.canverly.com/v1/posts \ -H "Authorization: Bearer ck_live_xxx" \ -H "Idempotency-Key: source-item-42" \ -H "Content-Type: application/json" \ -d '{ "title": "…", "blocks_json": { "v": 1, "blocks": [] } }'- A chave tem escopo por chave de API + corpo da requisição, então não colide entre sites nem com um payload diferente.
- Uma requisição que dá erro não guarda nada em cache — tentar de novo a executa outra vez.
- Enviar a mesma chave com um corpo diferente é tratado como uma nova requisição (outro post).
Veja também
Seção intitulada “Veja também”PATCH /v1/posts/{id}— edite ou mude a data de um post existente.GET /v1/posts— leia o arquivo publicado, com filtros, paginação keyset esincepara sincronização incremental.POST /v1/import— crie muitos posts em uma única requisição NDJSON em vez de um loop.- SEO do post — título, descrição, URL canônica,
no_indexeschema_typesão definidos em uma rota própria, não no corpo de criação.
Não existe DELETE público para posts: excluir conteúdo é uma ação do admin.