Introdução
Documentação de Implantação — API Pública do Blog
Este documento descreve como usuários do SaaS devem integrar e
          implantar chamadas ao conjunto de rotas públicas do blog (posts,
          categorias, tags). Essas rotas exigem uma chave de API (X-API-Key).
Quickstart
Passos essenciais
- Obtenha a API Key do seu blog (Configurações → API Key).
 - 
Faça uma chamada GET para 
/public/postscom o headerX-API-Key: {SUA_API_KEY}. - 
Use os endpoints de 
posts,categoriesetagsconforme necessário. 
Exemplo de requisição básica
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getPosts() {
  const url = 'https://api.draftin.io/public/posts?limit=10&offset=0';
  const response = await axios.get(url, config);
  console.log(response.data);
}
getPosts();
      Autenticação
Uso do header X-API-Key
Todas as rotas públicas exigem o header HTTP X-API-Key com
          a chave associada ao blog.
Header necessário: X-API-Key: {API_KEY_DO_BLOG} 
Como obter a chave: a chave é gerada/visualizada no painel do blog (Configurações → Blogs)
Nota de segurança: a API key identifica o blog para leituras públicas. Não a exponha em logs públicos ou em repositórios.
Endpoints
Observação: todas as rotas usam o prefixo /public
1) Lista de posts
Método: GET — Rota: /public/posts
Query params: status (opcional), limit (opcional),
offset (opcional).
Listar posts
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function listPosts() {
  const url = 'https://api.draftin.io/public/posts?limit=5&offset=0';
  const response = await axios.get(url, config);
  console.log(response.data);
}
listPosts();
      2) Buscar post por ID
GET /public/posts/{id}
Buscar post por ID
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getPostById(postId) {
  const url = 'https://api.draftin.io/public/posts/' + postId;
  const response = await axios.get(url, config);
  console.log(response.data);
}
getPostById(123);
      3) Buscar post por slug
GET /public/posts/slug/{slug}
Buscar post por slug
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getPostBySlug(slug) {
  const url = 'https://api.draftin.io/public/posts/slug/' + slug;
  const response = await axios.get(url, config);
  console.log(response.data);
}
getPostBySlug('meu-post-exemplo');
      4) Lista de categorias
GET /public/categories
Listar categorias
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getCategories() {
  const response = await axios.get('https://api.draftin.io/public/categories', config);
  console.log(response.data);
}
getCategories();
      5) Buscar categoria por ID
GET /public/categories/{id}
Buscar categoria por ID
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getCategoryById(categoryId) {
  const url = 'https://api.draftin.io/public/categories/' + categoryId;
  const response = await axios.get(url, config);
  console.log(response.data);
}
getCategoryById(123);
      6) Lista de posts por categoria
GET /public/categories/{id}/posts 
Posts por categoria
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getPostsByCategoryId(categoryId) {
  const url = 'https://api.draftin.io/public/categories/' + categoryId + '/posts';
  const response = await axios.get(url, config);
  console.log(response.data);
}
getPostsByCategoryId(123);
      7) Lista de tags
GET /public/tags
Listar tags
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getTags() {
  const response = await axios.get('https://api.draftin.io/public/tags', config);
  console.log(response.data);
}
getTags();
      8) Buscar tag por ID
GET /public/tags/{id}
Buscar tag por ID
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getTagById(tagId) {
  const url = 'https://api.draftin.io/public/tags/' + tagId;
  const response = await axios.get(url, config);
  console.log(response.data);
}
getTagById(123);
      9) Lista de posts por tag
GET /public/tags/{id}/posts
Posts por tag
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'abcd1234-exemplo' } // Substitua pela sua API Key
};
async function getPostsByTagId(tagId) {
  const url = 'https://api.draftin.io/public/tags/' + tagId + '/posts';
  const response = await axios.get(url, config);
  console.log(response.data);
}
getPostsByTagId(123);
      Formato dos objetos (resumo rápido)
Post: campos relevantes — id, title, subtitle, slug, content, coverUrl, status, publishedAt, scheduledAt, authorId, blogId, tenantId, createdAt, updatedAt.
Category: id, name, slug, description, blogId, tenantId, createdAt, updatedAt.
Tag: id, name, slug, blogId, tenantId, createdAt, updatedAt.
Tratamento de erros e códigos HTTP
Respostas de erro seguem o esquema ErrorResponse com objeto
error contendo message, code, type, statusCode, timestamp e details.
- 
401 Unauthorized: chave 
X-API-Keyausente ou inválida. - 404 Not Found: recurso não encontrado.
 - 429 Too Many Requests: limite de requisições alcançado.
 - 500 Internal Server Error: erro do servidor.
 
Exemplo de resposta de erro
        {
  "success": false,
  "error": {
    "message": "API key inválida ou ausente",
    "code": "AUTH_INVALID_API_KEY",
    "type": "authentication",
    "statusCode": 401,
    "timestamp": "2025-08-21T10:00:00.000Z",
    "retryable": false
  }
}
      Boas práticas
- Cacheie as respostas públicas (posts, categorias, tags) no CDN/edge por alguns minutos.
 - Use 
limit+offsetpara paginação. - Valide os slugs localmente antes de fazer requests.
 - Trate 429 com backoff exponencial.
 - 
Não exponha a 
X-API-Keyem repositórios públicos. 
Exemplo de integração rápida (Javascript / fetch)
Exemplo de integração com JavaScript
        import axios from 'axios';
const config = {
  headers: { 'X-API-Key': 'SUA_API_KEY_AQUI' } // Lembre-se de substituir pela sua chave
};
async function fetchPosts(limit = 10, offset = 0) {
  const response = await axios.get('https://api.draftin.io/public/posts', {
    ...config,
    params: { limit, offset }
  });
  return response.data;
}
async function main() {
  const posts = await fetchPosts(5);
  console.log('Posts recebidos:', posts);
}
main();
      Perguntas frequentes (FAQ)
 Q: Preciso de autenticação por usuário para acessar essas
          rotas?
A: Não. As rotas públicas usam X-API-Key para identificar o blog.
 Q: A API pública retorna conteúdo filtrado por permissões?
A: A chave do blog identifica o blog e o conteúdo visível
          (posts com PUBLISHED).
Suporte
Se encontrar comportamento inconsistente entre a spec e os endpoints, reporte ao time de suporte com: exemplo de request (URL + headers), payload de resposta (body) e timestamp UTC da requisição para [email protected].