Api reference

Códigos de Erro

Referência completa de códigos de erro e como resolver cada um

Códigos de Erro

Guia completo de todos os códigos de erro da API RenderHub, com exemplos e soluções.

Formato de Erro

Todos os erros seguem o mesmo formato JSON:

{
  "error": "error_code",
  "message": "Descrição legível do erro",
  "code": 400,
  "field": "campo_especifico",
  "details": "Informações adicionais"
}

Códigos HTTP

CódigoNomeSignificado
200OKRequisição bem-sucedida
400Bad RequestRequisição inválida
401UnauthorizedAutenticação falhou
403ForbiddenSem permissão ou quota excedida
404Not FoundRecurso não encontrado
413Payload Too LargeConteúdo muito grande
422Unprocessable EntityErro ao processar conteúdo
429Too Many RequestsRate limit excedido
500Internal Server ErrorErro interno do servidor
503Service UnavailableServiço temporariamente indisponível

Erros de Autenticação (401)

missing_authorization

Cabeçalho Authorization ausente na requisição.

{
  "error": "missing_authorization",
  "message": "Cabeçalho Authorization é obrigatório",
  "code": 401
}

Solução:

// ❌ Erro
fetch('/api/v1/render', {
  method: 'POST',
  body: JSON.stringify(data)
});

// ✅ Correto
fetch('/api/v1/render', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`
  },
  body: JSON.stringify(data)
});

invalid_api_key

Chave de API inválida ou mal formatada.

{
  "error": "invalid_api_key",
  "message": "Chave de API inválida",
  "code": 401
}

Causas comuns:

  • Chave copiada incorretamente (espaços extras)
  • Prefixo Bearer ausente
  • Chave de teste usada em produção (ou vice-versa)

Solução:

// ✅ Verifique o formato correto
const API_KEY = 'rh_live_abc123...'; // Deve começar com rh_live_ ou rh_test_
headers: {
  'Authorization': `Bearer ${API_KEY}` // Não esqueça do "Bearer "
}

revoked_api_key

Chave de API foi revogada.

{
  "error": "revoked_api_key",
  "message": "Esta chave de API foi revogada",
  "revoked_at": "2024-01-15T10:00:00Z",
  "code": 401
}

Solução: Crie uma nova chave de API no Dashboard.

expired_api_key

Chave de API expirou (apenas chaves temporárias).

{
  "error": "expired_api_key",
  "message": "Chave de API expirou em 2024-01-01",
  "expired_at": "2024-01-01T00:00:00Z",
  "code": 401
}

Solução: Gere uma nova chave permanente.

Erros de Permissão (403)

quota_exceeded

Quota mensal de requisições excedida.

{
  "error": "quota_exceeded",
  "message": "Quota mensal de 1.000 requisições excedida",
  "quota_limit": 1000,
  "quota_used": 1000,
  "quota_reset": "2024-02-01T00:00:00Z",
  "code": 403
}

Soluções:

  1. Aguarde o reset mensal
  2. Faça upgrade do plano
  3. Otimize uso com cache

insufficient_permissions

Chave de API não tem permissão para esta ação.

{
  "error": "insufficient_permissions",
  "message": "Esta chave não tem permissão para deletar templates",
  "required_permission": "templates:delete",
  "code": 403
}

Solução: Use uma chave com permissões adequadas ou crie uma nova no Dashboard.

account_suspended

Conta suspensa por violação de termos ou pagamento pendente.

{
  "error": "account_suspended",
  "message": "Sua conta foi suspensa. Entre em contato com o suporte.",
  "suspended_at": "2024-01-15T10:00:00Z",
  "reason": "payment_overdue",
  "code": 403
}

Solução: Entre em contato com support@renderhub.com

Erros de Validação (400)

invalid_request

Requisição mal formatada ou campos obrigatórios ausentes.

{
  "error": "invalid_request",
  "message": "O campo 'mode' é obrigatório",
  "field": "mode",
  "code": 400
}

Exemplos comuns:

// ❌ Modo ausente
{ input_type: 'html', data: '<h1>Test</h1>' }

// ✅ Correto
{ mode: 'CONVERT', input_type: 'html', data: '<h1>Test</h1>' }

// ❌ input_type inválido
{ mode: 'CONVERT', input_type: 'pdf', data: '...' }

// ✅ Correto
{ mode: 'CONVERT', input_type: 'html', data: '...' }

invalid_mode

Modo de operação inválido.

{
  "error": "invalid_mode",
  "message": "Modo deve ser 'CONVERT' ou 'RENDER'",
  "received": "TRANSFORM",
  "valid_values": ["CONVERT", "RENDER"],
  "code": 400
}

invalid_input_type

Tipo de entrada não suportado.

{
  "error": "invalid_input_type",
  "message": "Tipo de entrada inválido: 'pdf'",
  "received": "pdf",
  "valid_values": ["html", "docx", "markdown", "xml", "csv", "json"],
  "code": 400
}

invalid_page_size

Tamanho de página inválido.

{
  "error": "invalid_page_size",
  "message": "Tamanho de página inválido: 'custom'",
  "received": "custom",
  "valid_values": ["A4", "A3", "Letter", "Legal", "Tabloid"],
  "code": 400
}

invalid_orientation

Orientação inválida.

{
  "error": "invalid_orientation",
  "message": "Orientação deve ser 'portrait' ou 'landscape'",
  "received": "horizontal",
  "code": 400
}

missing_template_id

Template ID ausente no modo RENDER.

{
  "error": "missing_template_id",
  "message": "template_id é obrigatório no modo RENDER",
  "code": 400
}

Solução:

// ✅ Correto
{
  mode: 'RENDER',
  template_id: 'tpl_invoice_001',
  data: { ... }
}

missing_data

Campo data ausente no modo CONVERT.

{
  "error": "missing_data",
  "message": "Campo 'data' é obrigatório no modo CONVERT",
  "code": 400
}

Erros de Conteúdo (422)

conversion_failed

Falha ao converter conteúdo para PDF.

{
  "error": "conversion_failed",
  "message": "Falha ao converter HTML para PDF",
  "details": "CSS inválido na linha 15: unexpected token '}'",
  "line": 15,
  "code": 422
}

Causas comuns:

  • HTML malformado
  • CSS inválido
  • JavaScript com erros
  • Imagens quebradas

Solução: Valide seu HTML/CSS antes de enviar:

// Valide HTML básico
const isValid = html.includes('<html>') && html.includes('</html>');

invalid_html

HTML malformado ou inválido.

{
  "error": "invalid_html",
  "message": "HTML malformado: tag não fechada",
  "details": "Unclosed tag <div> at line 42",
  "line": 42,
  "code": 422
}

invalid_docx

Arquivo DOCX corrompido ou inválido.

{
  "error": "invalid_docx",
  "message": "Arquivo DOCX inválido ou corrompido",
  "details": "Failed to parse DOCX: invalid ZIP archive",
  "code": 422
}

Solução: Verifique se o arquivo está corrompido e se está codificado em base64 corretamente.

invalid_markdown

Markdown com sintaxe inválida.

{
  "error": "invalid_markdown",
  "message": "Markdown inválido: bloco de código não fechado",
  "line": 25,
  "code": 422
}

template_not_found

Template especificado não existe.

{
  "error": "template_not_found",
  "message": "Template 'tpl_invoice_999' não encontrado",
  "template_id": "tpl_invoice_999",
  "code": 422
}

Solução: Verifique o ID do template no Dashboard.

template_render_error

Erro ao renderizar template com dados fornecidos.

{
  "error": "template_render_error",
  "message": "Falha ao renderizar template: variável 'customer_name' não encontrada",
  "missing_variable": "customer_name",
  "code": 422
}

Solução: Certifique-se de que todos os campos do template estão no JSON:

// Template usa: {{customer_name}}, {{total}}
// ❌ Dados incompletos
{ total: '100' }

// ✅ Dados completos
{ customer_name: 'João', total: '100' }

image_load_failed

Falha ao carregar imagem externa.

{
  "error": "image_load_failed",
  "message": "Falha ao carregar imagem: https://exemplo.com/logo.png",
  "image_url": "https://exemplo.com/logo.png",
  "reason": "DNS resolution failed",
  "code": 422
}

Soluções:

  • Use imagens base64 inline
  • Verifique se a URL está acessível
  • Use HTTPS para imagens

Erros de Tamanho (413)

payload_too_large

Payload excede o tamanho máximo.

{
  "error": "payload_too_large",
  "message": "Tamanho do payload excede 10 MB",
  "max_size_mb": 10,
  "received_size_mb": 15.2,
  "code": 413
}

Soluções:

  1. Comprima imagens antes de incorporar
  2. Use referências externas para imagens grandes
  3. Divida em múltiplos PDFs
  4. Faça upgrade para plano Enterprise (50 MB)

pdf_too_large

PDF gerado excede o tamanho máximo.

{
  "error": "pdf_too_large",
  "message": "PDF gerado excede 50 MB",
  "max_size_mb": 50,
  "generated_size_mb": 67,
  "code": 413
}

Soluções:

  • Reduza qualidade de imagens
  • Remova imagens de fundo desnecessárias
  • Divida em múltiplos PDFs

Erros de Rate Limit (429)

rate_limit_exceeded

Limite de requisições por minuto excedido.

{
  "error": "rate_limit_exceeded",
  "message": "Você excedeu 20 requisições por minuto",
  "limit": 20,
  "retry_after": 45,
  "reset_at": "2024-01-15T10:31:00Z",
  "code": 429
}

Solução: Implemente retry com backoff exponencial:

async function generatePDFWithRetry(data, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await axios.post('/api/v1/render', data);
    } catch (error) {
      if (error.response?.status === 429) {
        const retryAfter = error.response.data.retry_after || (2 ** i);
        console.log(`Rate limited. Aguardando ${retryAfter}s...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Máximo de tentativas atingido');
}

Erros de Servidor (500)

internal_error

Erro interno do servidor.

{
  "error": "internal_error",
  "message": "Erro interno ao processar requisição",
  "request_id": "req_abc123",
  "code": 500
}

Solução:

  1. Tente novamente em alguns segundos
  2. Se persistir, entre em contato com o suporte informando o request_id

service_unavailable

Serviço temporariamente indisponível.

{
  "error": "service_unavailable",
  "message": "Serviço temporariamente indisponível para manutenção",
  "retry_after": 300,
  "code": 503
}

Solução: Aguarde o tempo indicado em retry_after (segundos).

Erros de Timeout

processing_timeout

Processamento excedeu o tempo limite.

{
  "error": "processing_timeout",
  "message": "Processamento excedeu 30 segundos",
  "timeout_seconds": 30,
  "code": 422
}

Soluções:

  • Simplifique o HTML (menos JavaScript)
  • Reduza número de imagens
  • Use modo assíncrono com webhook
  • Upgrade para Enterprise (60s timeout)

javascript_timeout

JavaScript excedeu tempo de execução.

{
  "error": "javascript_timeout",
  "message": "Execução de JavaScript excedeu 5 segundos",
  "timeout_seconds": 5,
  "code": 422
}

Solução: Otimize scripts ou remova JavaScript desnecessário.

Erros de Webhook

webhook_failed

Falha ao enviar callback para webhook.

{
  "error": "webhook_failed",
  "message": "Falha ao enviar callback: Connection refused",
  "webhook_url": "https://meuapp.com/webhook",
  "attempts": 3,
  "last_error": "ECONNREFUSED",
  "code": 500
}

Solução: Verifique se a URL do webhook está acessível e aceitando POST.

Tratamento de Erros

Estratégia Recomendada

async function generatePDF(data) {
  try {
    const response = await axios.post('/api/v1/render', data, {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    });
    return response.data;
  } catch (error) {
    if (error.response) {
      const { status, data } = error.response;

      switch (status) {
        case 400:
          console.error('Requisição inválida:', data.message);
          // Corrigir dados e tentar novamente
          break;

        case 401:
          console.error('Erro de autenticação:', data.message);
          // Verificar chave de API
          break;

        case 403:
          if (data.error === 'quota_exceeded') {
            console.error('Quota excedida. Reset em:', data.quota_reset);
            // Notificar usuário ou fazer upgrade
          }
          break;

        case 413:
          console.error('Payload muito grande:', data.message);
          // Reduzir tamanho ou dividir em partes
          break;

        case 422:
          console.error('Erro ao processar:', data.message);
          console.error('Detalhes:', data.details);
          // Corrigir conteúdo
          break;

        case 429:
          console.log('Rate limit. Aguardando', data.retry_after, 'segundos');
          // Implementar retry
          await sleep(data.retry_after * 1000);
          return generatePDF(data); // Tentar novamente
          break;

        case 500:
        case 503:
          console.error('Erro do servidor:', data.message);
          console.error('Request ID:', data.request_id);
          // Tentar novamente ou contatar suporte
          break;

        default:
          console.error('Erro desconhecido:', data);
      }
    } else {
      console.error('Erro de rede:', error.message);
    }
    throw error;
  }
}

Logging de Erros

function logError(error) {
  const errorData = {
    timestamp: new Date().toISOString(),
    error_code: error.response?.data?.error,
    message: error.response?.data?.message,
    request_id: error.response?.data?.request_id,
    status: error.response?.status,
    stack: error.stack
  };

  // Enviar para serviço de logging (Sentry, LogRocket, etc.)
  console.error('PDF Generation Error:', JSON.stringify(errorData, null, 2));
}

Monitoramento

Use os cabeçalhos de resposta para monitorar limites:

function checkRateLimits(response) {
  const remaining = response.headers['x-ratelimit-remaining'];
  const quotaRemaining = response.headers['x-quota-remaining'];

  if (remaining < 5) {
    console.warn('⚠️ Próximo do rate limit! Restam', remaining, 'requisições');
  }

  if (quotaRemaining < 100) {
    console.warn('⚠️ Próximo da quota mensal! Restam', quotaRemaining);
  }
}

Próximos Passos

On this page