Felo API PlatformFelo API Platform

Felo APIs

Chat API

Integre busca conversacional com IA, com análise de consulta, recursos da web e citações.

POST/v2/chat

Autenticação

Bearer API key

Tipo de conteúdo

application/json

Notas de limite

Per API key and per user windows. Read X-RateLimit headers.

A Chat API permite integrar busca conversacional com IA às suas aplicações. Envie uma consulta em linguagem natural e receba uma resposta inteligente gerada a partir de resultados de busca na web em tempo real.

Para limites de requisições, respostas de erro e comportamento de novas tentativas, consulte Erros, limites e novas tentativas.

Visão geral

A Chat API executa as seguintes operações:

  1. Analisa e otimiza sua consulta
  2. Busca na web informações relevantes
  3. Classifica e filtra os resultados da busca
  4. Gera uma resposta completa de IA com base nas fontes
  5. Retorna a resposta junto com as citações das fontes

Casos de uso:

  • Assistentes conversacionais de IA
  • Ferramentas de pesquisa e recuperação de informações
  • Chatbots de atendimento ao cliente com conhecimento da web
  • Aplicações educacionais
  • Ferramentas de criação de conteúdo

Autenticação

Todas as requisições à Chat API exigem autenticação com uma chave de API. Inclua sua chave de API no cabeçalho Authorization:

Authorization: Bearer YOUR_API_KEY

Consulte o guia de autenticação para detalhes sobre como obter e usar sua chave de API.

Uso com agentes de IA

Instale o pacote completo felo-ai quando quiser que um agente use a Search e todos os demais Felo Skills disponíveis. O instalador descobre dinamicamente todos os diretórios de pacote que contêm SKILL.md, então inclui Skills futuros em vez de um subconjunto fixo. Instale-os no diretório nativo do seu agente: o Codex usa ~/.codex/skills, o Claude Code usa ~/.claude/skills, o OpenClaw usa ~/.agents/skills e o Hermes Agent usa ~/.hermes/skills. Consulte o guia de configuração manual de agentes de IA para ver o link seguro, a chave de API e os passos de verificação de cada plataforma.

Endpoint

POST https://openapi.felo.ai/v2/chat

Requisição

Cabeçalhos

CabeçalhoObrigatórioDescrição
AuthorizationSimSua chave de API no formato: Bearer YOUR_API_KEY
Content-TypeSimDeve ser application/json

Parâmetros do corpo

ParâmetroTipoObrigatórioDescriçãoRestrições
querystringSimA pergunta ou consulta de busca do usuário1 a 2000 caracteres

Exemplo de requisição

{
  "query": "What are the latest developments in quantum computing?"
}

Resposta

Resposta de sucesso (200 OK)

Quando a requisição é bem-sucedida, a API retorna uma resposta JSON com a seguinte estrutura:

{
  "status": "ok",
  "message": null,
  "data": {
    "id": "HabCj883yHLSXc8mWqu4Eq",
    "message_id": "18ea8517-5559-4f48-a355-1f8a79e73b71",
    "answer": "Recent developments in quantum computing include...",
    "query_analysis": {
      "queries": [
        "quantum computing latest developments 2025",
        "quantum computing breakthroughs"
      ]
    },
    "resources": [
      {
        "link": "https://example.com/quantum-news",
        "title": "Latest Quantum Computing Breakthroughs",
        "snippet": "Scientists have achieved a major milestone..."
      },
      {
        "link": "https://example.com/quantum-research",
        "title": "Quantum Computing Research 2025",
        "snippet": "New quantum algorithms show promise..."
      }
    ]
  }
}

Campos da resposta

CampoTipoDescrição
statusstring | numberStatus da resposta: "ok" em caso de sucesso; respostas de erro usam o código de status HTTP como número
messagestring | nullMensagem adicional (null para requisições bem-sucedidas)
dataobjectDados da resposta (presente apenas quando o status é "ok")
data.idstringIdentificador exclusivo desta sessão de chat
data.message_idstringIdentificador exclusivo desta mensagem específica
data.answerstringResposta gerada por IA para a consulta
data.query_analysisobjectAnálise da consulta do usuário
data.query_analysis.queriesstring[]Consultas de busca otimizadas derivadas da entrada do usuário
data.resourcesarrayLista de fontes da web usadas para gerar a resposta
data.resources[].linkstringURL da fonte
data.resources[].titlestringTítulo da página de origem
data.resources[].snippetstringTrecho relevante da fonte

Resposta de erro

Quando ocorre um erro, a API retorna o envelope de erro compartilhado:

{
  "status": 401,
  "code": "UNAUTHORIZED",
  "message": "API Key is required",
  "request_id": "..."
}

Campos da resposta de erro

CampoTipoDescrição
statusnumberCódigo de status HTTP; respostas de sucesso usam "ok"
codestringCódigo de erro que identifica o tipo de erro
messagestringDescrição do erro legível por humanos
request_idstringIdentificador exclusivo desta requisição (útil para suporte)

Códigos de erro

HTTPCódigoSignificado
400Código de validação do endpointUm campo query está faltando, vazio ou longo demais; leia message para saber o problema específico
401UNAUTHORIZEDA chave de API está faltando, é inválida ou foi revogada
429RATE_LIMITEDUm limite de requisições foi excedido
502CHAT_FAILEDErro interno do serviço
503SERVICE_UNAVAILABLEServiço temporariamente indisponível

Para ver o envelope compartilhado, outros códigos de erro e as regras de novas tentativas, consulte Erros, limites e novas tentativas.

Exemplos

cURL

curl -X POST https://openapi.felo.ai/v2/chat \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "What are the benefits of renewable energy?"
  }'

Resposta:

{
  "status": "ok",
  "message": null,
  "data": {
    "id": "HabCj883yHLSXc8mWqu4Eq",
    "message_id": "18ea8517-5559-4f48-a355-1f8a79e73b71",
    "answer": "Renewable energy offers numerous benefits including reduced greenhouse gas emissions, decreased air pollution, energy independence, job creation, and long-term cost savings. Solar, wind, and hydroelectric power are sustainable alternatives to fossil fuels that help combat climate change while providing reliable electricity.",
    "query_analysis": {
      "queries": [
        "renewable energy benefits",
        "advantages of renewable energy sources"
      ]
    },
    "resources": [
      {
        "link": "https://example.com/renewable-benefits",
        "title": "Top Benefits of Renewable Energy",
        "snippet": "Renewable energy sources provide clean, sustainable power..."
      }
    ]
  }
}

Python

import requests
import os

# Get API key from environment variable
api_key = os.environ.get('FELO_API_KEY')

url = 'https://openapi.felo.ai/v2/chat'
headers = {
    'Authorization': f'Bearer {api_key}',
    'Content-Type': 'application/json'
}
data = {
    'query': 'What are the benefits of renewable energy?'
}

try:
    response = requests.post(url, headers=headers, json=data)
    response.raise_for_status()  # Raise exception for HTTP errors

    result = response.json()

    if result['status'] == 'ok':
        print('Answer:', result['data']['answer'])
        print('\nSources:')
        for resource in result['data']['resources']:
            print(f"- {resource['title']}: {resource['link']}")
    else:
        print(f"Error: {result['code']} - {result['message']}")

except requests.exceptions.RequestException as e:
    print(f'Request failed: {e}')

JavaScript (Node.js)

const fetch = require('node-fetch');

const apiKey = process.env.FELO_API_KEY;
const url = 'https://openapi.felo.ai/v2/chat';

const headers = {
  'Authorization': `Bearer ${apiKey}`,
  'Content-Type': 'application/json'
};

const body = JSON.stringify({
  query: 'What are the benefits of renewable energy?'
});

fetch(url, { method: 'POST', headers, body })
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    if (data.status === 'ok') {
      console.log('Answer:', data.data.answer);
      console.log('\nSources:');
      data.data.resources.forEach(resource => {
        console.log(`- ${resource.title}: ${resource.link}`);
      });
    } else {
      console.error(`Error: ${data.code} - ${data.message}`);
    }
  })
  .catch(error => {
    console.error('Request failed:', error);
  });

JavaScript (navegador/Fetch API)

const apiKey = 'YOUR_API_KEY'; // In production, get this from your backend

fetch('https://openapi.felo.ai/v2/chat', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query: 'What are the benefits of renewable energy?'
  })
})
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    if (data.status === 'ok') {
      console.log('Answer:', data.data.answer);

      // Display sources
      const sourcesList = data.data.resources.map(resource =>
        `<li><a href="${resource.link}">${resource.title}</a></li>`
      ).join('');

      document.getElementById('answer').innerHTML = data.data.answer;
      document.getElementById('sources').innerHTML = sourcesList;
    } else {
      console.error(`Error: ${data.code} - ${data.message}`);
    }
  })
  .catch(error => {
    console.error('Request failed:', error);
  });

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

type ChatRequest struct {
    Query string `json:"query"`
}

type ChatResponse struct {
    Status  string `json:"status"`
    Message string `json:"message,omitempty"`
    Data    struct {
        ID            string `json:"id"`
        MessageID     string `json:"message_id"`
        Answer        string `json:"answer"`
        QueryAnalysis struct {
            Queries []string `json:"queries"`
        } `json:"query_analysis"`
        Resources []struct {
            Link    string `json:"link"`
            Title   string `json:"title"`
            Snippet string `json:"snippet"`
        } `json:"resources"`
    } `json:"data,omitempty"`
    Code      string `json:"code,omitempty"`
    RequestID string `json:"request_id,omitempty"`
}

func main() {
    apiKey := os.Getenv("FELO_API_KEY")
    url := "https://openapi.felo.ai/v2/chat"

    requestBody := ChatRequest{
        Query: "What are the benefits of renewable energy?",
    }

    jsonData, err := json.Marshal(requestBody)
    if err != nil {
        fmt.Printf("Error marshaling request: %v\n", err)
        return
    }

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Printf("Error creating request: %v\n", err)
        return
    }

    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("Error making request: %v\n", err)
        return
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Error reading response: %v\n", err)
        return
    }

    var chatResp ChatResponse
    err = json.Unmarshal(body, &chatResp)
    if err != nil {
        fmt.Printf("Error unmarshaling response: %v\n", err)
        return
    }

    if chatResp.Status == "ok" {
        fmt.Println("Answer:", chatResp.Data.Answer)
        fmt.Println("\nSources:")
        for _, resource := range chatResp.Data.Resources {
            fmt.Printf("- %s: %s\n", resource.Title, resource.Link)
        }
    } else {
        fmt.Printf("Error: %s - %s\n", chatResp.Code, chatResp.Message)
    }
}

Limites de requisições

Usuários com uma assinatura Felo paga efetiva (incluindo assinaturas empresariais) estão isentos de todos os limites de requisições de /v2/chat, tanto na autenticação por chave de API quanto por OAuth. Respostas isentas não incluem cabeçalhos X-RateLimit-*.

Usuários sem assinatura paga estão sujeitos a limites de requisições em três dimensões. Se o status da assinatura não puder ser verificado, esses limites continuam valendo:

  • Por chave de API - limita as requisições feitas com uma única chave de API em uma janela de 1 minuto.
  • Por usuário (minuto) - limita o total de requisições de todas as chaves de API de um usuário em uma janela de 1 minuto.
  • Por usuário (hora) - limita o total de requisições de todas as chaves de API de um usuário em uma janela de 1 hora.

A violação de qualquer dimensão dispara uma resposta 429 Too Many Requests.

Os limites numéricos exatos podem mudar com o tempo. Leia-os sempre nos cabeçalhos de resposta abaixo, não em capturas da documentação.

Cabeçalhos de resposta (respostas sujeitas a limite de requisições, incluindo 429):

CabeçalhoSignificado
X-RateLimit-LimitLimite da dimensão mais restritiva em vigor no momento
X-RateLimit-RemainingCota restante mínima entre as três dimensões
X-RateLimit-ResetTimestamp Unix (em segundos) de quando a janela atual é redefinida

Em um 429, adicionalmente:

CabeçalhoSignificado
Retry-AfterAtraso recomendado para nova tentativa (em segundos)

Exemplo de corpo 429 (o message reflete os limites configurados no momento da requisição):

{
  "status": 429,
  "code": "RATE_LIMITED",
  "message": "Too many requests. Limit: <N>/min per API key, <M>/min per user, <H>/hour per user.",
  "request_id": "..."
}

Comportamento do cliente: quando presente, leia X-RateLimit-Remaining e reduza o ritmo de forma proativa. Em um 429, aguarde ao menos Retry-After segundos (ou até X-RateLimit-Reset) antes de tentar novamente. Não codifique valores de limite.

Para ver a política completa de novas tentativas e orientações de backoff, consulte Erros, limites e novas tentativas. Se precisar de limites de requisições mais altos, fale com [email protected].

Práticas recomendadas

1. Trate erros com elegância

Verifique sempre o status da resposta e trate os erros adequadamente:

if result['status'] == 'ok':
    # Process successful response
    answer = result['data']['answer']
else:
    # Handle error
    error_code = result['code']
    error_message = result['message']
    # Log error, show user-friendly message, etc.

2. Implemente lógica de novas tentativas

Para erros transitórios (códigos 5xx), implemente backoff exponencial:

import time

max_retries = 3
retry_delay = 1  # seconds

for attempt in range(max_retries):
    response = requests.post(url, headers=headers, json=data)

    if response.status_code < 500:
        break  # Success or client error, don't retry

    if attempt < max_retries - 1:
        time.sleep(retry_delay * (2 ** attempt))  # Exponential backoff

3. Faça cache das respostas

Considere fazer cache das respostas para consultas idênticas, para reduzir chamadas à API e melhorar os tempos de resposta.

4. Valide a entrada

Valide a entrada do usuário antes de enviá-la à API:

  • Verifique se a consulta não está vazia
  • Verifique o tamanho da consulta (1 a 2000 caracteres)
  • Sanitize a entrada para evitar ataques de injeção

5. Monitore o uso

Acompanhe o uso da sua API para ficar dentro dos limites de requisições e otimizar custos:

  • Registre contagens de requisições e tempos de resposta
  • Monitore as taxas de erro
  • Configure alertas para padrões incomuns

Suporte

Precisa de ajuda com a Chat API?

Registro de alterações

v2.0.0 (atual)

  • Lançamento inicial da Chat API
  • Suporte a consultas em linguagem natural
  • Integração com busca na web em tempo real
  • Respostas geradas por IA com citações das fontes