Base de conhecimento
Busca híbrida (semântica + palavras-chave) nos seus documentos, com rerank e feedback de relevância, para RAG e assistentes de IA.
BetaEm beta: a ferramenta está em fase de testes com contas selecionadas e pode mudar antes do lançamento. Se a sua conta ainda não tiver acesso, as chamadas respondem rag.disabled; fale com o suporte para entrar nos testes.
Envie textos e Markdown para uma base (collection) e faça buscas híbridas (semântica + palavras-chave) com rerank opcional, filtros por metadados e feedback de relevância. Pensada para alimentar assistentes e agentes de IA (RAG).
- Base path
/v1/tools/rag- Escopos
tools:rag:readtools:rag:querytools:rag:managetools:manage
Visão geral
Uma base (collection) guarda documentos de texto ou Markdown. Cada documento é dividido em seções (pelos títulos) e trechos (pedaços de ~96 tokens), que são indexados de duas formas: por significado (embeddings) e por palavras-chave. A busca combina as duas e devolve os trechos mais relevantes, prontos para você passar a um modelo de linguagem (RAG) ou mostrar ao usuário.
Crie uma base com o idioma dos documentos (melhora a busca por palavras-chave).
Alimente a base. Envie texto ou Markdown, importe arquivos (PDF, Office, imagens) ou conecte uma fonte que se sincroniza sozinha (site, sitemap, repositório do GitHub, pasta do Google Drive). A indexação é assíncrona: acompanhe o status até ready. Reenviar com o mesmo external_id substitui a versão anterior sem tirar a base do ar.
Busque com a pergunta do usuário e use os trechos devolvidos como contexto da resposta.
Responda com citações (opcional): answer devolve um texto em que cada afirmação aponta para o trecho de origem, ou diz que não sabe. Para o seu site, embuta o widget.
Registre feedback (opcional): trechos confirmados sobem nas próximas buscas parecidas e os rejeitados somem.
| Operação | Rota |
|---|---|
| Criar base | POST/collections |
| Listar bases | GET/collections |
| Consultar base | GET/collections/{collection_id} |
| Filtros disponíveis | GET/collections/{collection_id}/facets |
| Alterar base | PATCH/collections/{collection_id} |
| Excluir base | DELETE/collections/{collection_id} |
| Reindexar base | POST/collections/{collection_id}/reindex |
| Adicionar ou substituir documento | POST/collections/{collection_id}/documents |
| Listar documentos | GET/collections/{collection_id}/documents |
| Consultar documento | GET/collections/{collection_id}/documents/{document_id} |
| Alterar título ou metadados | PATCH/collections/{collection_id}/documents/{document_id} |
| Excluir documento | DELETE/collections/{collection_id}/documents/{document_id} |
| Reprocessar documento com falha | POST/collections/{collection_id}/documents/{document_id}/retry |
| Ver seções indexadas | GET/collections/{collection_id}/documents/{document_id}/sections |
| Buscar na base | POST/collections/{collection_id}/query |
| Registrar feedback de relevância | POST/collections/{collection_id}/feedback |
| Listar feedback | GET/collections/{collection_id}/feedback |
| Apagar um grupo de feedback | DELETE/collections/{collection_id}/feedback/{cluster_id} |
| Reordenar textos (rerank) | POST/rerank |
| Decidir entre opções (roteamento) | POST/decide |
| Consultar preços | GET/pricing |
| Consultar limites | GET/limits |
| Painel de saúde da base | GET/collections/{collection_id}/overview |
| Índice dos documentos | GET/collections/{collection_id}/index |
| Achar duplicados e contradições | POST/collections/{collection_id}/lint |
| Trocar o modelo de embeddings | POST/collections/{collection_id}/model |
| Marcar documentos como desatualizados | POST/collections/{collection_id}/changes |
| Responder com citações | POST/collections/{collection_id}/answer |
| Analytics das perguntas | GET/collections/{collection_id}/analytics |
| Criar chave pública (widget) | POST/collections/{collection_id}/public-keys |
| Listar chaves públicas | GET/collections/{collection_id}/public-keys |
| Revogar chave pública | DELETE/collections/{collection_id}/public-keys/{key_id} |
| Responder pelo widget (rota pública) | POST/v1/public/rag/answer |
| Script do widget | GET/widget/rag.js |
| Listar fontes sincronizadas | GET/collections/{collection_id}/sources |
| Criar fonte sincronizada | POST/collections/{collection_id}/sources |
| Alterar fonte | PATCH/collections/{collection_id}/sources/{source_id} |
| Excluir fonte | DELETE/collections/{collection_id}/sources/{source_id} |
| Sincronizar agora | POST/collections/{collection_id}/sources/{source_id}/sync |
| Histórico de sincronizações | GET/collections/{collection_id}/sources/{source_id}/syncs |
| Importar arquivo (PDF, Office, imagem) | POST/collections/{collection_id}/documents/file |
| Consultar importação de arquivo | GET/collections/{collection_id}/imports/{import_id} |
Custos
Por uso — Valores por unidade. Buscas e rerank têm franquia diária e são cobrados em blocos pré-pagos (tabelas seguintes). A ingestão tem desconto no documento: −20% a partir de 1.000 trechos e −40% a partir de 10.000.
| Item | Créditos | Notas |
|---|---|---|
| Ingestão, por trecho indexado | 0,02 | modelo padrão; trecho padrão ≈ 96 tokens |
| Ingestão Alta precisão, por trecho | 0,06 | bases com o modelo Alta precisão |
Busca (modo fast) | 0,25 | — |
| Busca Alta precisão | 0,4 | substitui a busca padrão nas bases Alta precisão |
| Busca respondida do cache | 0,02 | mesma consulta nos últimos 10 min |
Rerank no modo accurate | +0,08 | sem cobrança se cair para fast |
| Rerank avulso, por chamada | 0,08 | — |
Franquia diária — Chamadas grátis por conta e por dia (UTC). Depois delas, a cobrança é em blocos pré-pagos.
| Item | Grátis por dia |
|---|---|
| Buscas | 20 |
| Buscas Alta precisão | 5 |
| Buscas respondidas do cache | 50 |
Rerank no modo accurate | 5 |
| Rerank avulso | 5 |
Blocos pré-pagos — Depois da franquia, a chamada que abre um bloco cobra o bloco inteiro de uma vez; as seguintes do bloco não cobram de novo. Os blocos crescem com o uso pago do dia, igual em todos os serviços. As chamadas não usadas de um bloco expiram à meia-noite UTC, sem estorno.
| Item | Tamanho do bloco | Notas |
|---|---|---|
| Primeiro bloco pago do dia | 10 | ex.: 10 buscas = 2,5 créditos |
| Até 200 chamadas pagas no dia | 20 | — |
| A partir de 200 chamadas pagas | 50 | — |
| A partir de 1.000 chamadas pagas | 100 | com −40% (desconto por volume) |
Desconto por volume diário — Por serviço, conforme as chamadas pagas que os blocos anteriores do dia já somam. Soma-se ao desconto dos pacotes de crédito.
| Item | Desconto no bloco |
|---|---|
| A partir de 1.000 chamadas pagas no dia | −40% |
| A partir de 10.000 chamadas pagas no dia | −70% |
Armazenamento — Cobrado uma vez por dia sobre o total de trechos guardados na conta.
| Item | Créditos |
|---|---|
| Primeiros 2.000 trechos | 0,0 |
| Cada bloco iniciado de 10.000 trechos | 0,1 / dia |
Como funcionam os blocos
Buscas e rerank têm uma franquia grátis por dia. Depois dela, a chamada que abre um bloco debita o bloco inteiro de uma vez (10 chamadas no primeiro, depois 20, 50 e 100 conforme o uso pago do dia), e as próximas do mesmo bloco não cobram de novo. Os contadores zeram à meia-noite UTC, e as chamadas não usadas de um bloco expiram sem estorno. A ferramenta MCP rag_get_usage e o dry_run das buscas mostram quanto a próxima chamada cobra. Consultar bases, documentos e feedback é grátis e não entra na franquia diária de leituras.
A ingestão é cobrada quando termina, pelo número real de trechos; o estimate da resposta é uma aproximação. Conteúdo idêntico ao já indexado não é cobrado de novo. Use X-Dry-Run: true no envio de documento para ver a estimativa sem enviar nada.
Bases
Criar base
/v1/tools/rag/collections- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
name(obrigatório, até 120 caracteres) edescription(até 1.000).language:simple(padrão),portuguese,english,spanishoufrench. Define o dicionário da busca por palavras-chave.default_mode:fast(padrão) ouaccurate(rerank extra, mais preciso e um pouco mais caro).- Ajustes avançados:
chunk_size_tokens(16–480, padrão 96),chunk_overlap_tokens(padrão 16),section_max_tokens(padrão 768),max_per_document(0–20, padrão 2),dense_weightelexical_weight(0–10, padrão 1; não podem ser os dois 0) efeedback_enabled(padrãotrue).
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"language": "portuguese",
"default_mode": "fast"
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"language": "portuguese",
"default_mode": "fast"
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"language": "portuguese",
"default_mode": "fast"
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"language": "portuguese",
"default_mode": "fast"
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections", strings.NewReader(`{
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"language": "portuguese",
"default_mode": "fast"
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 201
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"embedding_model": "intfloat/multilingual-e5-small",
"language": "portuguese",
"chunk_size_tokens": 96,
"chunk_overlap_tokens": 16,
"section_max_tokens": 768,
"default_mode": "fast",
"max_per_document": 2,
"dense_weight": 1,
"lexical_weight": 1,
"feedback_enabled": true,
"document_count": 0,
"chunk_count": 0,
"created_at": "2026-09-20T12:00:00Z",
"updated_at": "2026-09-24T09:30:00Z"
}
}Listar bases
/v1/tools/rag/collections- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Devolve também o uso da conta em relação aos limites (usage).
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"collections": [
{
"id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"embedding_model": "intfloat/multilingual-e5-small",
"language": "portuguese",
"chunk_size_tokens": 96,
"chunk_overlap_tokens": 16,
"section_max_tokens": 768,
"default_mode": "fast",
"max_per_document": 2,
"dense_weight": 1,
"lexical_weight": 1,
"feedback_enabled": true,
"document_count": 128,
"chunk_count": 4210,
"created_at": "2026-09-20T12:00:00Z",
"updated_at": "2026-09-24T09:30:00Z"
}
],
"usage": {
"collections": 1,
"max_collections": 50,
"chunks": 4210,
"max_chunks": 200000,
"pending_documents": 0,
"max_pending_documents": 20
}
}
}Consultar base
/v1/tools/rag/collections/{collection_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"embedding_model": "intfloat/multilingual-e5-small",
"language": "portuguese",
"chunk_size_tokens": 96,
"chunk_overlap_tokens": 16,
"section_max_tokens": 768,
"default_mode": "fast",
"max_per_document": 2,
"dense_weight": 1,
"lexical_weight": 1,
"feedback_enabled": true,
"document_count": 128,
"chunk_count": 4210,
"created_at": "2026-09-20T12:00:00Z",
"updated_at": "2026-09-24T09:30:00Z"
}
}Filtros disponíveis
/v1/tools/rag/collections/{collection_id}/facets- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Lista as chaves de metadados dos documentos da base e os valores mais comuns de cada uma, para você saber o que pode usar em filters nas buscas. documents é quantos documentos prontos com metadados foram analisados e keys é o total de chaves filtráveis. Se sampled for true, a base tem mais de 5000 documentos e a contagem vem só dos 5000 mais recentes. Em facets, cada item traz a key, os documents que a têm, distinct (total de valores distintos) e values[] (os valores mais comuns, cada um com value e documents). array: true indica que a chave guarda uma lista; filtre com {"chave": ["valor"]}.
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/facets' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/facets', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/facets",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/facets');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/facets", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"documents": 128,
"sampled": false,
"keys": 2,
"facets": [
{
"key": "categoria",
"documents": 120,
"distinct": 3,
"values": [
{
"value": "conta",
"documents": 64
},
{
"value": "cobranca",
"documents": 41
},
{
"value": "api",
"documents": 15
}
]
},
{
"key": "tags",
"documents": 37,
"array": true,
"distinct": 2,
"values": [
{
"value": "faq",
"documents": 30
},
{
"value": "legado",
"documents": 7
}
]
}
]
}
}Alterar base
/v1/tools/rag/collections/{collection_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Envie só os campos que quer mudar. O modelo de embeddings não pode ser trocado depois da criação. Mudanças no tamanho dos trechos só valem para documentos enviados depois; para aplicar à base inteira, use a reindexação.
curl -sS -X PATCH 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "default_mode": "accurate" }'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c', {
method: 'PATCH',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "default_mode": "accurate" }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.patch(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "default_mode": "accurate" },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "default_mode": "accurate" }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("PATCH", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c", strings.NewReader(`{ "default_mode": "accurate" }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"name": "Central de ajuda",
"description": "Artigos públicos de suporte",
"embedding_model": "intfloat/multilingual-e5-small",
"language": "portuguese",
"chunk_size_tokens": 96,
"chunk_overlap_tokens": 16,
"section_max_tokens": 768,
"default_mode": "fast",
"max_per_document": 2,
"dense_weight": 1,
"lexical_weight": 1,
"feedback_enabled": true,
"document_count": 128,
"chunk_count": 4210,
"created_at": "2026-09-20T12:00:00Z",
"updated_at": "2026-09-24T09:30:00Z"
}
}Reindexar base
/v1/tools/rag/collections/{collection_id}/reindex- Custo
- Reprocessa todos os documentos; cada trecho é cobrado como na ingestão
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Reprocessa todos os documentos com as configurações atuais da base. Cada trecho é cobrado como numa ingestão nova.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/reindex' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/reindex', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/reindex",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/reindex');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/reindex", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"documents_enqueued": 128
}
}Painel de saúde da base
/v1/tools/rag/collections/{collection_id}/overview- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Resumo para manter a base em ordem, sem custo: contagem de documentos por status, quantos estão desatualizados (stale), nunca foram consultados ou não têm metadados; uma matriz de documentos por metadado (rows e cols são chaves de metadado, até 20 valores por eixo); a atividade dos últimos days dias (1 a 180, padrão 30); e attention, com até 5 exemplos de documentos com falha, desatualizados, duplicados ou contraditórios e com feedback negativo. A resposta fica em cache por 60 s.
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/overview?rows=categoria&days=30' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/overview?rows=categoria&days=30', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/overview?rows=categoria&days=30",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/overview?rows=categoria&days=30');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/overview?rows=categoria&days=30", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"counts": {
"total": 128,
"by_status": {
"pending": 0,
"processing": 0,
"ready": 126,
"failed": 2
},
"stale": 4,
"never_accessed": 31,
"without_metadata": 8,
"total_bytes": 912000,
"total_sections": 540
},
"matrix": {
"rows_key": "categoria",
"cols_key": "",
"rows": [
"conta",
"api"
],
"cols": [],
"cells": [
{
"row": "conta",
"col": "",
"count": 64
}
]
},
"activity": {
"key": "",
"days": 30,
"values": [],
"series": [
{
"date": "2026-10-20",
"total": 12,
"counts": {}
}
]
},
"attention": {
"failed": {
"count": 2,
"items": [
{
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"title": "Como trocar a senha"
}
]
},
"stale": {
"count": 4,
"items": []
},
"lint": {
"count": 1,
"items": []
},
"negative_feedback": {
"count": 0,
"items": []
}
},
"generated_at": "2026-10-20T12:00:00Z"
}
}Índice dos documentos
/v1/tools/rag/collections/{collection_id}/index- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Lista compacta dos documentos ready, sem conteúdo, para o agente escolher o que ler. filters (JSON de metadados), fields (até 20 chaves de metadado a copiar), order (updated_at_desc, padrão, ou title) e max_bytes (padrão 4096, máximo 32768). omitted conta os documentos cortados pelo limite.
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/index?fields=categoria&order=title' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/index?fields=categoria&order=title', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/index?fields=categoria&order=title",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/index?fields=categoria&order=title');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/index?fields=categoria&order=title", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"total": 126,
"omitted": 0,
"documents": [
{
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"updated_at": "2026-09-24T09:30:05Z",
"metadata": {
"categoria": "conta"
}
}
]
}
}Achar duplicados e contradições
/v1/tools/rag/collections/{collection_id}/lint- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Compara os 500 documentos mais recentes (opcionalmente filtrados por filters) com os embeddings que já existem; não chama modelo e não escreve nada. duplicate aparece com similaridade a partir de 0,75; possible_contradiction, entre 0,4 e 0,75 quando os dois têm o mesmo metadado tipo. Cada achado diz qual documento manter (keep, o mais novo) e o que fazer (action). limit vai de 1 a 100 (padrão 20) e include_content: true devolve o início de cada documento.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/lint' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "limit": 20 }'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/lint', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "limit": 20 }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/lint",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "limit": 20 },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/lint');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "limit": 20 }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/lint", strings.NewReader(`{ "limit": 20 }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"documents": 126,
"total": 1,
"truncated": false,
"found": 1,
"findings": [
{
"kind": "duplicate",
"similarity": 0.93,
"newer": {
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"updated_at": "2026-09-24T09:30:05Z"
},
"older": {
"document_id": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"external_id": "artigo-7",
"title": "Trocar senha",
"updated_at": "2026-08-02T10:00:00Z"
},
"keep": "artigo-42",
"action": "rewrite `artigo-42` merging the unique content of `artigo-7`, then delete `artigo-7`"
}
]
}
}Trocar o modelo de embeddings
/v1/tools/rag/collections/{collection_id}/model- Custo
- Reindexa a base com desconto de 50%; voltar ao modelo anterior é grátis por 24 h
- Dry-run
- Suportado (
X-Dry-Run: true) - Autenticação
- qualquer um de
tools:rag:managetools:manage
Troca entre intfloat/multilingual-e5-small (padrão) e BAAI/bge-m3 (Alta precisão) reindexando a base em segundo plano; você não precisa chamar a reindexação. A troca custa 50% do preço normal de ingestão, e voltar ao modelo anterior é grátis enquanto ela roda e por 24 h depois, uma vez. Use X-Dry-Run: true para ver a estimativa. Durante a troca a busca continua funcionando (a consulta é embutida com os dois modelos) e documentos novos são recusados com rag.model_switch_in_progress. Acompanhe pelo campo model_switch da base (running, paused ou done); se o saldo acabar, ela pausa com paused_reason: insufficient_credits e retoma quando você recarregar.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/model' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "embedding_model": "BAAI/bge-m3" }'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/model', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "embedding_model": "BAAI/bge-m3" }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/model",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "embedding_model": "BAAI/bge-m3" },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/model');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "embedding_model": "BAAI/bge-m3" }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/model", strings.NewReader(`{ "embedding_model": "BAAI/bge-m3" }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202 — 200 com só estimate em dry-run
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"embedding_model": "BAAI/bge-m3",
"documents_enqueued": 0,
"documents_remaining": 128,
"estimate": {
"documents": 128,
"chunks": 4210,
"credit_units": 421000
}
}
}Marcar documentos como desatualizados
/v1/tools/rag/collections/{collection_id}/changes- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Para bases ligadas a código ou a arquivos: informe os paths que mudaram (arquivo exato ou prefixo dir/, até 1000) e os documentos que declararam esses paths ao serem enviados ficam com stale: true. Nada é reindexado nem cobrado; reenviar o documento limpa a marca. Use exclude_stale na busca para ignorá-los. commit (até 64 caracteres) evita marcar o que já foi conferido naquele commit.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/changes' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "paths": ["docs/api/", "src/auth.ts"], "commit": "a1b2c3d" }'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/changes', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "paths": ["docs/api/", "src/auth.ts"], "commit": "a1b2c3d" }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/changes",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "paths": ["docs/api/", "src/auth.ts"], "commit": "a1b2c3d" },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/changes');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "paths": ["docs/api/", "src/auth.ts"], "commit": "a1b2c3d" }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/changes", strings.NewReader(`{ "paths": ["docs/api/", "src/auth.ts"], "commit": "a1b2c3d" }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"marked": 1,
"document_ids": [
"7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e"
]
}
}Excluir base
/v1/tools/rag/collections/{collection_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
A exclusão é assíncrona e apaga documentos, trechos e feedback.
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c', {
method: 'DELETE',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.delete(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"status": "deleting"
}
}Documentos
Adicionar ou substituir documento
/v1/tools/rag/collections/{collection_id}/documents- Custo
- Por trecho indexado, cobrado quando a ingestão termina; conteúdo idêntico não é cobrado de novo
- Dry-run
- Suportado (
X-Dry-Run: true) - Autenticação
- qualquer um de
tools:rag:managetools:manage
content(obrigatório): texto puro ou Markdown em UTF-8, até 5 MB. Para PDF, Office e imagens, use Importar arquivo.external_id(opcional, até 200 bytes): o seu identificador. Reenviar com o mesmo valor substitui o documento; a versão anterior continua respondendo às buscas (processing: true) até a nova ficar pronta.paths(até 50) ecommit: os arquivos de onde o documento vem, para marcá-lo como desatualizado quando mudarem.- Segredos reconhecidos no texto (chaves de API, tokens) são trocados por
[REDACTED:tipo]antes de indexar;redactionsconta quantos. metadata: objeto com até 50 chaves (4 KB, até 3 níveis), usado nos filtros da busca. Não é criptografado; não coloque dados sensíveis.- Acompanhe com Consultar documento até
status: ready(oufailed, comerror_code). Antes de aceitar, a API confere se o saldo cobre a estimativa.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"external_id": "artigo-42",
"title": "Como trocar a senha",
"content": "# Conta\n\n## Como trocar a senha\n\nAcesse Configurações > Segurança…",
"source_uri": "https://ajuda.example.com/artigos/42",
"metadata": { "categoria": "conta" }
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"external_id": "artigo-42",
"title": "Como trocar a senha",
"content": "# Conta\n\n## Como trocar a senha\n\nAcesse Configurações > Segurança…",
"source_uri": "https://ajuda.example.com/artigos/42",
"metadata": { "categoria": "conta" }
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"external_id": "artigo-42",
"title": "Como trocar a senha",
"content": "# Conta\n\n## Como trocar a senha\n\nAcesse Configurações > Segurança…",
"source_uri": "https://ajuda.example.com/artigos/42",
"metadata": { "categoria": "conta" }
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"external_id": "artigo-42",
"title": "Como trocar a senha",
"content": "# Conta\n\n## Como trocar a senha\n\nAcesse Configurações > Segurança…",
"source_uri": "https://ajuda.example.com/artigos/42",
"metadata": { "categoria": "conta" }
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents", strings.NewReader(`{
"external_id": "artigo-42",
"title": "Como trocar a senha",
"content": "# Conta\n\n## Como trocar a senha\n\nAcesse Configurações > Segurança…",
"source_uri": "https://ajuda.example.com/artigos/42",
"metadata": { "categoria": "conta" }
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202 — ingestão assíncrona; 200 em dry-run (só estimate) e quando o conteúdo é idêntico ao atual (duplicate: true)
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"status": "pending",
"estimate": {
"chunks": 18,
"credit_units": 1800
},
"document": {
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"status": "pending",
"processing": false,
"byte_size": 5120,
"section_count": 0,
"chunk_count": 0,
"metadata": {
"categoria": "conta"
},
"created_at": "2026-09-24T09:30:00Z",
"updated_at": "2026-09-24T09:30:05Z"
}
}
}Importar arquivo (PDF, Office, imagem)
/v1/tools/rag/collections/{collection_id}/documents/file- Custo
- A conversão não cobra; o texto resultante é cobrado por trecho, como na ingestão
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Envio multipart/form-data com file (obrigatório, até 50 MB) e, opcionalmente, title, external_id, source_uri, metadata (objeto JSON em texto) e ocr (padrão true; desligue para PDFs que já têm texto). Formatos: .pdf, .docx, .pptx, .xlsx, .html, .md, .csv, .asciidoc e imagens (.png, .jpg, .tiff, .bmp, .webp). O arquivo é convertido em Markdown (tabelas preservadas, imagens só pelo texto do OCR) e depois indexado como qualquer documento, com o mesmo limite de 5 MB para o texto resultante. A resposta é 202 com o id da importação; consulte-a até completed (traz o document_id) ou failed. Sem conversão disponível, a resposta é 503 (rag.service_unavailable).
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/file' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/file', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/file",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/file');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/file", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"import_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
"status": "queued"
}
}Consultar importação de arquivo
/v1/tools/rag/collections/{collection_id}/imports/{import_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/imports/%7Bimport_id%7D' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/imports/%7Bimport_id%7D', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/imports/%7Bimport_id%7D",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/imports/%7Bimport_id%7D');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/imports/%7Bimport_id%7D", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
"filename": "manual.pdf",
"status": "completed",
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"error": null,
"created_at": "2026-10-20T12:00:00Z",
"updated_at": "2026-10-20T12:00:40Z"
}
}Listar documentos
/v1/tools/rag/collections/{collection_id}/documents- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Filtro opcional por status (pending, processing, ready, failed, deleting). Paginação por cursor: passe o next_cursor recebido em after. limit padrão 20, máximo 100.
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents?status=ready&limit=20' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents?status=ready&limit=20', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents?status=ready&limit=20",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents?status=ready&limit=20');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents?status=ready&limit=20", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"documents": [
{
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"status": "ready",
"processing": false,
"byte_size": 5120,
"section_count": 4,
"chunk_count": 18,
"metadata": {
"categoria": "conta"
},
"created_at": "2026-09-24T09:30:00Z",
"updated_at": "2026-09-24T09:30:05Z"
}
],
"next_cursor": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e"
}
}Consultar documento
/v1/tools/rag/collections/{collection_id}/documents/{document_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"status": "ready",
"processing": false,
"byte_size": 5120,
"section_count": 4,
"chunk_count": 18,
"metadata": {
"categoria": "conta"
},
"created_at": "2026-09-24T09:30:00Z",
"updated_at": "2026-09-24T09:30:05Z"
}
}Alterar título ou metadados
/v1/tools/rag/collections/{collection_id}/documents/{document_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Não reprocessa o conteúdo e não cobra nada.
curl -sS -X PATCH 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "metadata": { "categoria": "seguranca" } }'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e', {
method: 'PATCH',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "metadata": { "categoria": "seguranca" } }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.patch(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "metadata": { "categoria": "seguranca" } },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "metadata": { "categoria": "seguranca" } }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("PATCH", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e", strings.NewReader(`{ "metadata": { "categoria": "seguranca" } }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"status": "ready",
"processing": false,
"byte_size": 5120,
"section_count": 4,
"chunk_count": 18,
"metadata": {
"categoria": "conta"
},
"created_at": "2026-09-24T09:30:00Z",
"updated_at": "2026-09-24T09:30:05Z"
}
}Ver seções indexadas
/v1/tools/rag/collections/{collection_id}/documents/{document_id}/sections- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Mostra como o documento foi dividido, útil para ajustar títulos e tamanho dos trechos.
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/sections' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/sections', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/sections",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/sections');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/sections", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"sections": [
{
"id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"index": 0,
"heading_path": [
"Conta",
"Como trocar a senha"
],
"content": "Acesse Configurações > Segurança e clique em Trocar senha…",
"token_count": 84
}
]
}
}Reprocessar documento com falha
/v1/tools/rag/collections/{collection_id}/documents/{document_id}/retry- Custo
- Por trecho indexado, como na ingestão
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Só para documentos com status: failed; os demais respondem rag.document_not_failed.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/retry' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/retry', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/retry",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/retry');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e/retry", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"external_id": "artigo-42",
"title": "Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"status": "pending",
"processing": false,
"byte_size": 5120,
"section_count": 4,
"chunk_count": 18,
"metadata": {
"categoria": "conta"
},
"created_at": "2026-09-24T09:30:00Z",
"updated_at": "2026-09-24T09:30:05Z"
}
}Excluir documento
/v1/tools/rag/collections/{collection_id}/documents/{document_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e', {
method: 'DELETE',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.delete(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/documents/7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"status": "deleting"
}
}Fontes sincronizadas
Uma fonte importa páginas de fora e as mantém em dia: a cada sincronização, páginas novas ou alteradas são reindexadas, as inalteradas (mesmo conteúdo) não são cobradas de novo, e as que sumiram da origem são removidas da base. Cada página vira um documento comum (external_id src:<id da fonte>:…, com source_id e source_url nos metadados), cobrado por trecho como numa ingestão manual; se faltar saldo ou cota, a sincronização falha e mostra o motivo.
kind | start_url | O que importa |
|---|---|---|
site | página inicial | Rastreia links do mesmo host até max_depth, respeitando o robots.txt; HTML vira Markdown e arquivos PDF/Office linkados são convertidos. |
sitemap | URL do sitemap (ou índice) | Importa as páginas listadas, até max_pages. max_depth não se aplica. |
github | https://github.com/dono/repo | Repositório público; config.ref (padrão HEAD) e config.paths (prefixos) filtram. Lê .md, .mdx, .txt, .rst e converte os formatos de arquivo suportados. |
gdrive | URL de uma pasta /folders/<id> | Pasta compartilhada como "qualquer pessoa com o link"; Docs viram Markdown. Só existe se o servidor tiver a integração ligada. |
Listar fontes sincronizadas
/v1/tools/rag/collections/{collection_id}/sources- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"sources": [
{
"id": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"config": {},
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24,
"enabled": true,
"status": "ok",
"next_sync_at": "2026-10-21T12:00:00Z",
"last_sync": {
"id": "e7f8a9b0-c1d2-4e3f-8a4b-5c6d7e8f9a0b",
"status": "completed",
"started_at": "2026-10-20T12:00:00Z",
"finished_at": "2026-10-20T12:03:10Z",
"pages_total": 42,
"pages_new": 3,
"pages_changed": 1,
"pages_removed": 0,
"error": null
},
"created_at": "2026-10-15T09:00:00Z"
}
]
}
}Criar fonte sincronizada
/v1/tools/rag/collections/{collection_id}/sources- Custo
- Cada página nova ou alterada é cobrada como uma ingestão
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
name(até 200) estart_url(http ou https) são obrigatórios;kindpadrãosite.max_pages: 1 a 1000 (padrão 100).max_depth: 1 a 10 (padrão 3).frequency_hours:0(só manual),6,24(padrão) ou168.- A primeira sincronização começa na hora. Páginas e arquivos de até 20 MB cada; um arquivo que não converte é pulado sem falhar a sincronização.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources", strings.NewReader(`{
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 201 — a primeira sincronização começa na hora (status: syncing)
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"config": {},
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24,
"enabled": true,
"status": "syncing",
"next_sync_at": "2026-10-21T12:00:00Z",
"last_sync": {
"id": "e7f8a9b0-c1d2-4e3f-8a4b-5c6d7e8f9a0b",
"status": "completed",
"started_at": "2026-10-20T12:00:00Z",
"finished_at": "2026-10-20T12:03:10Z",
"pages_total": 42,
"pages_new": 3,
"pages_changed": 1,
"pages_removed": 0,
"error": null
},
"created_at": "2026-10-15T09:00:00Z"
}
}Alterar fonte
/v1/tools/rag/collections/{collection_id}/sources/{source_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Todos os campos são opcionais. Com enabled: false ou frequency_hours: 0, next_sync_at fica nulo.
curl -sS -X PATCH 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "frequency_hours": 168, "enabled": true }'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D', {
method: 'PATCH',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ "frequency_hours": 168, "enabled": true }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.patch(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={ "frequency_hours": 168, "enabled": True },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "frequency_hours": 168, "enabled": true }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("PATCH", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D", strings.NewReader(`{ "frequency_hours": 168, "enabled": true }`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
"collection_id": "3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c",
"kind": "site",
"name": "Central de ajuda",
"start_url": "https://ajuda.example.com",
"config": {},
"max_pages": 100,
"max_depth": 3,
"frequency_hours": 24,
"enabled": true,
"status": "ok",
"next_sync_at": "2026-10-21T12:00:00Z",
"last_sync": {
"id": "e7f8a9b0-c1d2-4e3f-8a4b-5c6d7e8f9a0b",
"status": "completed",
"started_at": "2026-10-20T12:00:00Z",
"finished_at": "2026-10-20T12:03:10Z",
"pages_total": 42,
"pages_new": 3,
"pages_changed": 1,
"pages_removed": 0,
"error": null
},
"created_at": "2026-10-15T09:00:00Z"
}
}Sincronizar agora
/v1/tools/rag/collections/{collection_id}/sources/{source_id}/sync- Custo
- Cada página nova ou alterada é cobrada como uma ingestão
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
Responde 409 se a fonte já estiver sincronizando. pages_total, pages_new, pages_changed e pages_removed resumem a execução.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/sync' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/sync', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/sync",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/sync');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/sync", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 202
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "e7f8a9b0-c1d2-4e3f-8a4b-5c6d7e8f9a0b",
"status": "completed",
"started_at": "2026-10-20T12:00:00Z",
"finished_at": "2026-10-20T12:03:10Z",
"pages_total": 42,
"pages_new": 3,
"pages_changed": 1,
"pages_removed": 0,
"error": null
}
}Histórico de sincronizações
/v1/tools/rag/collections/{collection_id}/sources/{source_id}/syncs- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/syncs' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/syncs', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/syncs",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/syncs');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D/syncs", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"syncs": [
{
"id": "e7f8a9b0-c1d2-4e3f-8a4b-5c6d7e8f9a0b",
"status": "completed",
"started_at": "2026-10-20T12:00:00Z",
"finished_at": "2026-10-20T12:03:10Z",
"pages_total": 42,
"pages_new": 3,
"pages_changed": 1,
"pages_removed": 0,
"error": null
}
]
}
}Excluir fonte
/v1/tools/rag/collections/{collection_id}/sources/{source_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D', {
method: 'DELETE',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.delete(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/sources/%7Bsource_id%7D", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200 — os documentos já importados continuam na base
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"deleted": true
}
}Busca
Modos de busca e reranker
fast(padrão): combina a busca por significado e a por palavras-chave. Oscoreé uma fusão de posições (valores pequenos, perto de 0,03), bom para ordenar, não para comparar com um limiar.accurate: depois da fusão, um reranker relê os 20 melhores candidatos junto com a pergunta e devolve umscorecalibrado de 0 a 1; só nelemin_scoretem efeito. Cobra o adicional de rerank. Se o rerank estiver indisponível, a busca cai parafastsem o adicional (mode_used).- Reranker:
rerank_providerda base (eproviderno rerank avulso e nodecide) escolhe entrebge(padrão, cross-encoder) elaya, o juiz de relevância da Respawn, que pergunta se o trecho responde à consulta e devolve a probabilidade. O Laya costuma separar melhor trechos que só se parecem com a pergunta, mas é mais lento e, se estiver fora do ar, oaccuratecai parafaste o rerank avulso responde503(rag.service_unavailable). O preço é o mesmo dobge. - Se o serviço de embeddings falhar, a busca ainda responde só por palavras-chave (
mode_used: lexical), cobrada como cache.
Buscar na base
/v1/tools/rag/collections/{collection_id}/query- Custo
- Por consulta, com franquia diária e blocos pré-pagos (veja Custos)
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:querytools:rag:managetools:manage
query(obrigatório, até 1.000 caracteres).top_k: quantos trechos devolver (padrão 5, máximo 20).mode:fastouaccurate; sem ele, vale o padrão da base. Se o rerank do modoaccurateestiver indisponível, a busca cai parafastsem cobrar o adicional;mode_usedmostra o que foi usado.filters: só trechos de documentos cujos metadados contêm estes valores.min_score(só noaccurate) emax_per_document(0–20) refinam o resultado.updated_aftereupdated_before(RFC 3339) filtram pela data de atualização do documento, eexclude_stale: trueignora os marcados como desatualizados. Cada resultado trazupdated_at,stale,paths,commit,source_uriealso_in(outros documentos com o mesmo texto, colapsados num só resultado).highlightsmarca, em posições de caractere Unicode, os termos encontrados emcontent. Consultas repetidas em até 10 minutos vêm do cache (cached: true) e custam menos.
Conteúdo do usuário
Os trechos devolvidos são conteúdo dos seus documentos. Ao passá-los a um modelo de linguagem, trate-os como dados, não como instruções.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/query' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"query": "como mudo minha senha?",
"top_k": 5,
"filters": { "categoria": "conta" }
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/query', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"query": "como mudo minha senha?",
"top_k": 5,
"filters": { "categoria": "conta" }
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/query",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"query": "como mudo minha senha?",
"top_k": 5,
"filters": { "categoria": "conta" }
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/query');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"query": "como mudo minha senha?",
"top_k": 5,
"filters": { "categoria": "conta" }
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/query", strings.NewReader(`{
"query": "como mudo minha senha?",
"top_k": 5,
"filters": { "categoria": "conta" }
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"query_id": "f0e1d2c3-b4a5-4968-8776-5a4b3c2d1e0f",
"mode_used": "fast",
"cached": false,
"results": [
{
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"title": "Como trocar a senha",
"heading_path": [
"Conta",
"Como trocar a senha"
],
"section_index": 3,
"content": "Acesse Configurações > Segurança e clique em Trocar senha…",
"highlights": [
{
"start": 38,
"end": 49
}
],
"score": 0.87,
"signals": {
"dense_rank": 1,
"lexical_rank": 2
},
"metadata": {
"categoria": "conta"
}
}
]
}
}Feedback de relevância
Registrar feedback de relevância
/v1/tools/rag/collections/{collection_id}/feedback- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:querytools:rag:managetools:manage
label:positive(o trecho responde à pergunta) ounegative.end_user_ref(opcional): identifica quem avaliou, quando o voto vem do seu usuário final. É guardado só como hash.- Até 30 votos por minuto. Perguntas parecidas são agrupadas, e o voto passa a valer para todo o grupo.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"query": "como mudo minha senha?",
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"label": "positive",
"end_user_ref": "usuario-123"
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"query": "como mudo minha senha?",
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"label": "positive",
"end_user_ref": "usuario-123"
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"query": "como mudo minha senha?",
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"label": "positive",
"end_user_ref": "usuario-123"
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"query": "como mudo minha senha?",
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"label": "positive",
"end_user_ref": "usuario-123"
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback", strings.NewReader(`{
"query": "como mudo minha senha?",
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"label": "positive",
"end_user_ref": "usuario-123"
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"recorded": true
}
}Listar feedback
/v1/tools/rag/collections/{collection_id}/feedback- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"groups": [
{
"id": "a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d",
"sample_query": "como mudo minha senha",
"query_count": 12,
"updated_at": "2026-09-24T18:00:00Z",
"votes": [
{
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"section_hash": "5f2c…",
"label": "positive",
"source": "end_user",
"confirmations": 7,
"updated_at": "2026-09-24T18:00:00Z",
"answer": {
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"section_index": 3,
"document_title": "Como trocar a senha",
"heading_path": "Conta › Como trocar a senha",
"preview": "Acesse Configurações > Segurança e clique em Trocar senha…"
}
}
]
}
]
}
}Apagar um grupo de feedback
/v1/tools/rag/collections/{collection_id}/feedback/{cluster_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback/a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback/a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d', {
method: 'DELETE',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.delete(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback/a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback/a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/feedback/a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"deleted": true
}
}Rerank avulso
Reordenar textos (rerank)
/v1/tools/rag/rerank- Custo
- Por chamada, com franquia diária e blocos pré-pagos (veja Custos)
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:querytools:rag:managetools:manage
Ordena a sua lista de textos pela relevância à pergunta, sem base envolvida. Até 100 textos por chamada (cada um é cortado em 2.000 caracteres). index aponta para a posição no array enviado.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/rerank' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"query": "prazo de reembolso",
"documents": ["Entregas em até 5 dias úteis.", "Frete grátis acima de R$ 200.", "Reembolso em até 7 dias após a devolução."],
"top_k": 2
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/rerank', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"query": "prazo de reembolso",
"documents": ["Entregas em até 5 dias úteis.", "Frete grátis acima de R$ 200.", "Reembolso em até 7 dias após a devolução."],
"top_k": 2
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/rerank",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"query": "prazo de reembolso",
"documents": ["Entregas em até 5 dias úteis.", "Frete grátis acima de R$ 200.", "Reembolso em até 7 dias após a devolução."],
"top_k": 2
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/rerank');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"query": "prazo de reembolso",
"documents": ["Entregas em até 5 dias úteis.", "Frete grátis acima de R$ 200.", "Reembolso em até 7 dias após a devolução."],
"top_k": 2
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/rerank", strings.NewReader(`{
"query": "prazo de reembolso",
"documents": ["Entregas em até 5 dias úteis.", "Frete grátis acima de R$ 200.", "Reembolso em até 7 dias após a devolução."],
"top_k": 2
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"results": [
{
"index": 2,
"score": 0.93
},
{
"index": 0,
"score": 0.41
}
]
}
}Resposta com citações
Responder com citações
/v1/tools/rag/collections/{collection_id}/answer- Custo
- Como uma busca no modo `accurate` (veja Custos)
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:querytools:rag:managetools:manage
Faz uma busca accurate e responde só com trechos de score igual ou acima de min_score (0 a 1, padrão 0,35, um ponto de partida que vale calibrar na sua base).
- Com resposta,
answered: truee cada[n]do texto aponta para umacitations[](section_id,document_id,title,heading_path,source_uri,score,excerpt). Nunca há resposta sem citação. - Sem trecho acima do limiar,
answered: false,reason: no_passage_above_threshold, nenhuma citação, e o webhookrag.question.unansweredé disparado. Se o rerank não pôde conferir a relevância,reason: relevance_unverified(não afirma nada e não dispara o webhook). generate: false(padrão) monta a resposta citando os 3 melhores trechos. Comgenerate: true, o provedor de IA padrão da plataforma escreve o texto a partir dos trechos; sem marcador de citação válido ou sem provedor, volta ao modo extrativo (generated: false). Com texto gerado, os trechos da base seguem para o provedor de IA da plataforma.- Com
Accept: text/event-stream, a resposta vem em SSE:citations, váriosdelta(pedaços do texto) edone(o resultado completo). O texto é gerado inteiro antes, o SSE só o fatia. - Cobrança de uma busca
accurate; a geração não tem cobrança à parte. Use oquery_idno feedback para alimentar o CTR do analytics.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/answer' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"query": "como mudo minha senha?",
"top_k": 5,
"min_score": 0.35,
"generate": false
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/answer', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"query": "como mudo minha senha?",
"top_k": 5,
"min_score": 0.35,
"generate": false
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/answer",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"query": "como mudo minha senha?",
"top_k": 5,
"min_score": 0.35,
"generate": False
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/answer');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"query": "como mudo minha senha?",
"top_k": 5,
"min_score": 0.35,
"generate": false
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/answer", strings.NewReader(`{
"query": "como mudo minha senha?",
"top_k": 5,
"min_score": 0.35,
"generate": false
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200 — JSON, ou text/event-stream com Accept: text/event-stream (eventos citations, delta e done)
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"query_id": "f0e1d2c3-b4a5-4968-8776-5a4b3c2d1e0f",
"answered": true,
"answer": "Acesse Configurações > Segurança e clique em Trocar senha… [1]",
"generated": false,
"citations": [
{
"marker": 1,
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"title": "Como trocar a senha",
"heading_path": "Conta › Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"score": 0.91,
"excerpt": "Acesse Configurações > Segurança e clique em Trocar senha…"
}
]
}
}Widget de chat embutível
O widget é um botão de chat em JavaScript puro (sem CDN, em shadow DOM, só escreve texto) que responde com citações usando a sua base. Ele usa uma chave pública (rpk_…) que só consegue perguntar numa base: não lê outras, não escreve nada.
<script src="https://api.respawntech.dev/widget/rag.js" data-key="rpk_..." async></script>Atributos: data-key (obrigatório), data-title, data-placeholder e data-dont-know (texto quando não há resposta). As perguntas feitas pelo widget são cobradas do dono da base, como o answer.
Criar chave pública (widget)
/v1/tools/rag/collections/{collection_id}/public-keys- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
allowed_origins(obrigatório, 1 a 20):https://site.comouhttps://*.site.com, sem caminho. O servidor recusa pedidos cujoOriginnão esteja na lista.rate_per_minute: 1 a 600 (padrão 30), por chave.generateliga o texto gerado por IA nas respostas dessa chave.- Até 20 chaves por base. A
keyaparece uma única vez; guardamos só o hash.
Origin não é autenticação
Só o navegador respeita o Origin; um cliente fora dele pode forjá-lo. O que limita o abuso é o limite por minuto da chave, e o custo recai sobre você. Revogue a chave se vir uso estranho.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Site institucional",
"allowed_origins": ["https://www.example.com", "https://*.example.com"],
"rate_per_minute": 30,
"generate": false
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Site institucional",
"allowed_origins": ["https://www.example.com", "https://*.example.com"],
"rate_per_minute": 30,
"generate": false
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"name": "Site institucional",
"allowed_origins": ["https://www.example.com", "https://*.example.com"],
"rate_per_minute": 30,
"generate": False
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"name": "Site institucional",
"allowed_origins": ["https://www.example.com", "https://*.example.com"],
"rate_per_minute": 30,
"generate": false
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys", strings.NewReader(`{
"name": "Site institucional",
"allowed_origins": ["https://www.example.com", "https://*.example.com"],
"rate_per_minute": 30,
"generate": false
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 201
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
"name": "Site institucional",
"key_prefix": "rpk_Ab3dEf",
"allowed_origins": [
"https://www.example.com",
"https://*.example.com"
],
"rate_per_minute": 30,
"generate": false,
"created_at": "2026-10-20T12:00:00Z",
"key": "rpk_Ab3dEf…"
}
}Listar chaves públicas
/v1/tools/rag/collections/{collection_id}/public-keys- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"public_keys": [
{
"id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
"name": "Site institucional",
"key_prefix": "rpk_Ab3dEf",
"allowed_origins": [
"https://www.example.com",
"https://*.example.com"
],
"rate_per_minute": 30,
"generate": false,
"created_at": "2026-10-20T12:00:00Z"
}
]
}
}Revogar chave pública
/v1/tools/rag/collections/{collection_id}/public-keys/{key_id}- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:managetools:manage
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys/%7Bkey_id%7D' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys/%7Bkey_id%7D', {
method: 'DELETE',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.delete(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys/%7Bkey_id%7D",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys/%7Bkey_id%7D');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/public-keys/%7Bkey_id%7D", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"revoked": true
}
}Responder pelo widget (rota pública)
/v1/public/rag/answer- Custo
- Cobrada do dono da base, como o `answer` (veja Custos)
- Dry-run
- Não
- Autenticação
- Pública (sem token)
Sem token de API: envie a chave no header X-Respawn-Public-Key e o navegador manda o Origin. A base vem da chave, e top_k, min_score e generate não são aceitos no pedido. Responde como o answer (JSON ou SSE), com CORS liberado para a origem permitida. Erros: 401 (chave ausente, desconhecida ou revogada), 403 (origem não permitida) e 429 (limite por minuto).
curl -sS -X POST 'https://api.respawntech.dev/v1/public/rag/answer' \
-H 'Content-Type: application/json' \
-d '{ "query": "como mudo minha senha?" }'const response = await fetch('https://api.respawntech.dev/v1/public/rag/answer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ "query": "como mudo minha senha?" }),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/public/rag/answer",
headers={
},
json={ "query": "como mudo minha senha?" },
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/public/rag/answer');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{ "query": "como mudo minha senha?" }
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/public/rag/answer", strings.NewReader(`{ "query": "como mudo minha senha?" }`))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"query_id": "f0e1d2c3-b4a5-4968-8776-5a4b3c2d1e0f",
"answered": true,
"answer": "Acesse Configurações > Segurança e clique em Trocar senha… [1]",
"generated": false,
"citations": [
{
"marker": 1,
"section_id": "b2c4d6e8-0a1b-4c3d-8e5f-6a7b8c9d0e1f",
"document_id": "7a1f2e9c-5b3d-4c8a-9e0f-1d2c3b4a5f6e",
"title": "Como trocar a senha",
"heading_path": "Conta › Como trocar a senha",
"source_uri": "https://ajuda.example.com/artigos/42",
"score": 0.91,
"excerpt": "Acesse Configurações > Segurança e clique em Trocar senha…"
}
]
}
}Script do widget
/widget/rag.js- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- Pública (sem token)
curl -sS -X GET 'https://api.respawntech.dev/widget/rag.js'const response = await fetch('https://api.respawntech.dev/widget/rag.js', {
method: 'GET',
headers: {
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/widget/rag.js",
headers={
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/widget/rag.js');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/widget/rag.js", nil)
if err != nil {
panic(err)
}
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200 — application/javascript, com cache de 5 minutos
Analytics de perguntas
Analytics das perguntas
/v1/tools/rag/collections/{collection_id}/analytics- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
Mostra o que os usuários perguntam e o que a base não sabe responder, a partir das chamadas de answer e do widget. days vai de 1 a 90 (padrão 30).
answer_rate: respondidas ÷ total de perguntas.feedback_ctr: respondidas que receberam voto (peloquery_id) ÷ respondidas.positive_rate: votos positivos ÷ votos.top_questionseunanswered_questions: até 20 perguntas agrupadas cada, para você descobrir o que escrever na base.
As perguntas ficam cifradas com a chave da base. O widget não tem voto próprio: o CTR só conta votos enviados pela API.
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/analytics?days=30' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/analytics?days=30', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/analytics?days=30",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/analytics?days=30');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/collections/3c9e7a52-1b4d-4f0e-9a6c-2d8e5f7a1b3c/analytics?days=30", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"days": 30,
"questions": 340,
"unanswered": 41,
"answer_rate": 0.88,
"feedback_ctr": 0.12,
"positive_rate": 0.9,
"top_questions": [
{
"question": "como mudo minha senha",
"count": 52,
"unanswered": 0,
"last_asked": "2026-10-20T11:40:00Z"
}
],
"unanswered_questions": [
{
"question": "tem integração com zapier",
"count": 9,
"unanswered": 9,
"last_asked": "2026-10-20T10:02:00Z"
}
]
}
}Roteamento
Decidir entre opções (roteamento)
/v1/tools/rag/decide- Custo
- Por chamada, como o rerank avulso (veja Custos)
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:querytools:rag:managetools:manage
Classifica um texto entre 2 e 50 opções sem usar um LLM, pontuando cada label: description com o reranker (provider: bge ou laya). Serve para rotear pedidos. Se a melhor opção não passar de threshold (padrão 0,5) ou não ficar min_margin (padrão 0,1) à frente da segunda, decided é false: trate como "não sei". O ranking completo vem sempre. Preço e franquia do rerank avulso.
curl -sS -X POST 'https://api.respawntech.dev/v1/tools/rag/decide' \
-H "X-API-Token: $RESPAWN_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"text": "quero cancelar minha assinatura",
"options": [
{ "label": "cobranca", "description": "pagamentos, faturas e cancelamentos" },
{ "label": "suporte", "description": "problemas técnicos" }
],
"threshold": 0.5,
"min_margin": 0.1
}'const response = await fetch('https://api.respawntech.dev/v1/tools/rag/decide', {
method: 'POST',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"text": "quero cancelar minha assinatura",
"options": [
{ "label": "cobranca", "description": "pagamentos, faturas e cancelamentos" },
{ "label": "suporte", "description": "problemas técnicos" }
],
"threshold": 0.5,
"min_margin": 0.1
}),
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.post(
"https://api.respawntech.dev/v1/tools/rag/decide",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
json={
"text": "quero cancelar minha assinatura",
"options": [
{ "label": "cobranca", "description": "pagamentos, faturas e cancelamentos" },
{ "label": "suporte", "description": "problemas técnicos" }
],
"threshold": 0.5,
"min_margin": 0.1
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/decide');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"text": "quero cancelar minha assinatura",
"options": [
{ "label": "cobranca", "description": "pagamentos, faturas e cancelamentos" },
{ "label": "suporte", "description": "problemas técnicos" }
],
"threshold": 0.5,
"min_margin": 0.1
}
JSON,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
func main() {
req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/rag/decide", strings.NewReader(`{
"text": "quero cancelar minha assinatura",
"options": [
{ "label": "cobranca", "description": "pagamentos, faturas e cancelamentos" },
{ "label": "suporte", "description": "problemas técnicos" }
],
"threshold": 0.5,
"min_margin": 0.1
}`))
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"decided": true,
"label": "cobranca",
"score": 0.92,
"margin": 0.61,
"ranking": [
{
"label": "cobranca",
"score": 0.92
},
{
"label": "suporte",
"score": 0.31
}
]
}
}Preços e limites da conta
Consultar preços
/v1/tools/rag/pricing- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/pricing' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/pricing', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/pricing",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/pricing');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/pricing", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"collection_free": true,
"feedback_free": true,
"ingest": {
"unit_cost": 200,
"volume_discounts": [
{
"min_quantity": 1000,
"discount_percentage": 20
}
]
},
"calls": [
{
"service_code": "rag_query_search",
"unit_cost": 2500,
"free_per_day": 20,
"first_block_size": 10,
"block_size": 20
}
]
}
}Consultar limites
/v1/tools/rag/limits- Custo
- Grátis
- Dry-run
- Não
- Autenticação
- qualquer um de
tools:rag:readtools:rag:managetools:readtools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/rag/limits' \
-H "X-API-Token: $RESPAWN_API_TOKEN"const response = await fetch('https://api.respawntech.dev/v1/tools/rag/limits', {
method: 'GET',
headers: {
'X-API-Token': process.env.RESPAWN_API_TOKEN,
},
});
if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());import os
import requests
response = requests.get(
"https://api.respawntech.dev/v1/tools/rag/limits",
headers={
"X-API-Token": os.environ["RESPAWN_API_TOKEN"],
},
timeout=30,
)
if not response.ok:
raise RuntimeError(response.json()["error"]["code"])
print(response.json())<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/rag/limits');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status >= 400) {
throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/rag/limits", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
client := &http.Client{Timeout: 30 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
if res.StatusCode >= 400 {
panic(string(data))
}
fmt.Println(string(data))
}Resposta 200
{
"success": true,
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"max_collections": 50,
"max_chunks": 200000,
"max_pending_documents": 20,
"max_document_bytes": 5242880,
"max_query_chars": 1000,
"max_top_k": 20
}
}Valores vigentes da sua conta (já com o bônus do plano), úteis para validar um envio antes de fazê-lo.
Eventos (webhooks)
Cadastre um endpoint no dashboard para receber:
rag.document.readyerag.document.failed:collection_id,document_id,external_ideversion; o de falha traz tambémerror_code. Valem para documentos enviados, importados de arquivo e vindos de fontes.rag.question.unanswered:collection_id,question,query_idesource(apiouwidget), quando nenhum trecho passou domin_score. Bom para alimentar uma fila de "o que escrever".
O envio é de melhor esforço, como nos demais eventos. Veja a lista de eventos.
Usar pelo MCP
As mesmas operações estão disponíveis como ferramentas MCP do grupo rag (lista completa): rag_answer, rag_decide, rag_index, rag_lint, rag_mark_changed e rag_retry_document são as novas. As de leitura (rag_index, rag_lint) são gratuitas; use rag_access=query na conexão para esconder as que alteram a base.
Erros
| Código | HTTP | Quando |
|---|---|---|
rag.disabled | 403 | Base de conhecimento ainda não liberada para a conta. |
rag.document_too_large | 413 | Conteúdo acima de 5 MB. |
rag.chunk_quota_exceeded | 403 | A conta passaria de 200.000 trechos indexados. |
rag.collection_limit_reached | 403 | Limite de 50 bases por conta. |
rag.too_many_pending_documents | 429 | Já há 20 documentos em processamento; aguarde alguns terminarem. |
rag.capacity_exhausted | 429 | Serviço de busca sem capacidade no momento; tente de novo em alguns segundos. |
rag.embedding_failed | 502 | Falha no serviço de embeddings. |
rag.feedback_rate_limited | 429 | Mais de 30 votos de feedback por minuto. |
rag.document_not_failed | 409 | Só documentos com status failed podem ser reprocessados. |
rag.collection_create_restricted | 403 | A conexão MCP está limitada a bases específicas e não pode criar bases novas. |
rag.model_switch_in_progress | 409 | A base está trocando de modelo de busca; envie documentos quando a troca terminar ou cancele-a. |
rag.service_unavailable | 503 | Serviço de rerank (inclusive o Laya), conversão de arquivo, analytics ou chaves públicas indisponível no momento. |
rag.decrypt_failed | 500 | Falha ao ler o conteúdo guardado. Informe o trace_id ao suporte. |
embedding_failed | assíncrono | A indexação do documento falhou; use o reprocessamento. |
insufficient_credits | assíncrono | Saldo ou limite diário insuficiente para cobrar a ingestão ao terminar. |
empty_document | assíncrono | O documento não tem texto indexável. |
chunk_quota_exceeded | assíncrono | A ingestão passaria do limite de trechos da conta. |
persist_failed | assíncrono | Falha ao gravar o resultado; a cobrança é estornada. |
enqueue_failed | assíncrono | Falha ao enfileirar a ingestão. |
Os códigos sem status HTTP aparecem no campo error_code de um documento com status: failed.
Limites
| Limite | Valor |
|---|---|
| Tamanho de um documento | 5 MB |
| Bases por conta | 50 |
| Trechos indexados por conta | 200.000 |
| Documentos em processamento ao mesmo tempo | 20 |
| Tamanho da pergunta | 1.000 caracteres |
Trechos por busca (top_k) | 20 |
| Textos por rerank avulso | 100 |
| Votos de feedback por minuto | 30 |
| Arquivo importado | 50 MB |
| Páginas por fonte | 1.000 (padrão 100) |
| Chaves públicas por base | 20 |
As rotas da base de conhecimento ignoram o header X-Idempotency-Key: elas já são idempotentes (conteúdo repetido não é reindexado nem cobrado). Uma chave restrita a bases específicas só enxerga essas bases e não pode criar novas (forbidden).
Atualizado em