Felo APIs
Chat API
Integrasikan pencarian percakapan berbasis AI dengan analisis kueri, sumber web, dan kutipan.
/v2/chatAutentikasi
Bearer API key
Tipe konten
application/json
Catatan batas laju
Per API key and per user windows. Read X-RateLimit headers.
Chat API memungkinkan Anda mengintegrasikan pencarian percakapan berbasis AI ke dalam aplikasi Anda. Kirim kueri dalam bahasa alami dan terima jawaban cerdas yang dihasilkan dari hasil pencarian web waktu nyata.
Untuk batas laju, respons error, dan perilaku percobaan ulang, lihat Error, Batas, dan Percobaan Ulang.
Ringkasan
Chat API melakukan operasi berikut:
- Menganalisis dan mengoptimalkan kueri Anda
- Mencari informasi yang relevan di web
- Memeringkat dan memfilter hasil pencarian
- Menghasilkan jawaban AI yang komprehensif berdasarkan sumber
- Mengembalikan jawaban beserta kutipan sumber
Kasus Penggunaan:
- Asisten AI percakapan
- Alat riset dan pengambilan informasi
- Chatbot dukungan pelanggan dengan pengetahuan web
- Aplikasi pendidikan
- Alat pembuatan konten
Autentikasi
Semua permintaan ke Chat API memerlukan autentikasi menggunakan kunci API. Sertakan kunci API Anda di header Authorization:
Authorization: Bearer YOUR_API_KEYLihat Panduan Autentikasi untuk detail tentang cara memperoleh dan menggunakan kunci API Anda.
Penggunaan dengan Agen AI
Instal paket felo-ai lengkap jika Anda ingin Agen menggunakan Search dan setiap Felo Skill lain yang tersedia. Penginstal secara dinamis menemukan setiap direktori paket yang berisi SKILL.md, sehingga mencakup Skill mendatang, bukan sebagian tetap. Instal semuanya di direktori asli Agen Anda: Codex menggunakan ~/.codex/skills, Claude Code menggunakan ~/.claude/skills, OpenClaw menggunakan ~/.agents/skills, dan Hermes Agent menggunakan ~/.hermes/skills. Lihat panduan penyiapan Agen AI manual untuk langkah tautan aman, kunci API, dan verifikasi bagi setiap platform.
Endpoint
POST https://openapi.felo.ai/v2/chatPermintaan
Header
| Header | Wajib | Deskripsi |
|---|---|---|
Authorization | Ya | Kunci API Anda dalam format: Bearer YOUR_API_KEY |
Content-Type | Ya | Harus application/json |
Parameter Isi Permintaan
| Parameter | Tipe | Wajib | Deskripsi | Batasan |
|---|---|---|---|---|
query | string | Ya | Pertanyaan atau kueri pencarian pengguna | 1-2000 karakter |
Contoh Permintaan
{
"query": "What are the latest developments in quantum computing?"
}Respons
Respons Berhasil (200 OK)
Saat permintaan berhasil, API mengembalikan respons JSON dengan struktur berikut:
{
"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..."
}
]
}
}Field Respons
| Field | Tipe | Deskripsi |
|---|---|---|
status | string | number | Status respons: "ok" saat berhasil; respons error menggunakan kode status HTTP sebagai angka |
message | string | null | Pesan tambahan (null untuk permintaan yang berhasil) |
data | object | Data respons (hanya ada saat status bernilai "ok") |
data.id | string | Pengenal unik untuk sesi chat ini |
data.message_id | string | Pengenal unik untuk pesan tertentu ini |
data.answer | string | Jawaban yang dihasilkan AI untuk kueri |
data.query_analysis | object | Analisis kueri pengguna |
data.query_analysis.queries | string[] | Kueri pencarian yang dioptimalkan dari masukan pengguna |
data.resources | array | Daftar sumber web yang digunakan untuk menghasilkan jawaban |
data.resources[].link | string | URL sumber |
data.resources[].title | string | Judul halaman sumber |
data.resources[].snippet | string | Kutipan relevan dari sumber |
Respons Error
Saat terjadi error, API mengembalikan envelope error bersama:
{
"status": 401,
"code": "UNAUTHORIZED",
"message": "API Key is required",
"request_id": "..."
}Field Respons Error
| Field | Tipe | Deskripsi |
|---|---|---|
status | number | Kode status HTTP; respons berhasil menggunakan "ok" |
code | string | Kode error yang mengidentifikasi jenis error |
message | string | Deskripsi error yang dapat dibaca manusia |
request_id | string | Pengenal unik untuk permintaan ini (berguna untuk dukungan) |
Kode Error
| HTTP | Kode | Arti |
|---|---|---|
| 400 | Kode validasi endpoint | Field query tidak ada, kosong, atau terlalu panjang; baca message untuk masalah spesifiknya |
| 401 | UNAUTHORIZED | Kunci API tidak ada, tidak valid, atau dicabut |
| 429 | RATE_LIMITED | Batas laju terlampaui |
| 502 | CHAT_FAILED | Error layanan internal |
| 503 | SERVICE_UNAVAILABLE | Layanan sementara tidak tersedia |
Untuk envelope bersama, kode error lain, dan aturan percobaan ulang, lihat Error, Batas, dan Percobaan Ulang.
Contoh
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?"
}'Respons:
{
"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 (Browser/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)
}
}Batas Laju
Pengguna dengan langganan Felo berbayar yang efektif (termasuk langganan perusahaan) dibebaskan dari semua batas laju /v2/chat, baik untuk autentikasi kunci API maupun OAuth. Respons yang dibebaskan tidak menyertakan header X-RateLimit-*.
Pengguna tanpa langganan berbayar tunduk pada batas laju dalam tiga dimensi. Jika status langganan tidak dapat diverifikasi, batas ini tetap berlaku:
- Per Kunci API - membatasi permintaan yang dibuat dengan satu kunci API dalam jendela 1 menit.
- Per Pengguna (menit) - membatasi total permintaan di semua kunci API milik pengguna dalam jendela 1 menit.
- Per Pengguna (jam) - membatasi total permintaan di semua kunci API milik pengguna dalam jendela 1 jam.
Terlampauinya dimensi mana pun memicu respons 429 Too Many Requests.
Batas numerik yang tepat dapat berubah seiring waktu. Selalu baca dari header respons di bawah ini, bukan dari snapshot dokumentasi.
Header respons (respons yang tunduk pada pembatasan laju, termasuk 429):
| Header | Arti |
|---|---|
X-RateLimit-Limit | Batas dari dimensi paling ketat yang sedang berlaku |
X-RateLimit-Remaining | Sisa kuota minimum di ketiga dimensi |
X-RateLimit-Reset | Stempel waktu Unix (detik) saat jendela saat ini diatur ulang |
Pada 429, tambahan:
| Header | Arti |
|---|---|
Retry-After | Penundaan percobaan ulang yang disarankan (detik) |
Contoh isi 429 (message mencerminkan batas yang dikonfigurasi saat permintaan):
{
"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": "..."
}Perilaku klien: jika ada, baca X-RateLimit-Remaining dan mundur secara proaktif. Saat 429, tunggu setidaknya Retry-After detik (atau hingga X-RateLimit-Reset) sebelum mencoba lagi. Jangan menuliskan nilai batas secara hardcode.
Untuk kebijakan percobaan ulang lengkap dan panduan backoff, lihat Error, Batas, dan Percobaan Ulang. Jika Anda memerlukan batas laju yang lebih tinggi, hubungi [email protected].
Praktik Terbaik
1. Tangani Error dengan Baik
Selalu periksa status respons dan tangani error dengan tepat:
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. Terapkan Logika Percobaan Ulang
Untuk error sementara (kode status 5xx), terapkan backoff eksponensial:
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 backoff3. Gunakan Cache untuk Respons
Pertimbangkan untuk menyimpan respons di cache untuk kueri yang identik guna mengurangi panggilan API dan meningkatkan waktu respons.
4. Validasi Masukan
Validasi masukan pengguna sebelum mengirim ke API:
- Pastikan kueri tidak kosong
- Periksa panjang kueri (1-2000 karakter)
- Sanitasi masukan untuk mencegah serangan injeksi
5. Pantau Penggunaan
Lacak penggunaan API Anda agar tetap dalam batas laju dan mengoptimalkan biaya:
- Catat jumlah permintaan dan waktu respons
- Pantau tingkat error
- Siapkan peringatan untuk pola yang tidak biasa
Dukungan
Butuh bantuan dengan Chat API?
- Tinjau Panduan Memulai
- Periksa Dokumentasi Autentikasi
- Hubungi dukungan di [email protected] dengan ID permintaan Anda
Riwayat Perubahan
v2.0.0 (Saat Ini)
- Rilis awal Chat API
- Dukungan untuk kueri bahasa alami
- Integrasi pencarian web waktu nyata
- Jawaban yang dihasilkan AI dengan kutipan sumber