Referência da API
Todos os endpoints da API usam formato JSON. A autenticação usa chave de API Bearer aqn_. Consulte Autenticação para detalhes.
URL Base: https://your-instance/api/
Autenticação
Inclua sua chave de API em todas as requisições:
Authorization: Bearer aqn_your_api_key
As chaves de API são criadas e gerenciadas na página Chaves de API (/keys/). Chaves de acesso total veem todas as coleções; chaves restritas veem apenas as coleções concedidas.
Schema OpenAPI
O schema OpenAPI completo está disponível em /api/v1/schema/ em todos os ambientes (incluindo produção). Use-o para integrar com qualquer ferramenta compatível com OpenAPI:
- Geração de SDK (openapi-generator, kiota, etc.)
- Ações de GPT Personalizado do ChatGPT
- Importação para Postman / Insomnia
- Qualquer ferramenta ou fluxo de trabalho compatível com OpenAPI
GET /api/v1/schema/
Retorna um documento OpenAPI 3.0 válido em JSON. Sem necessidade de autenticação. Swagger UI (/api/v1/docs/) e ReDoc (/api/v1/redoc/) estão disponíveis apenas em ambientes de depuração/desenvolvimento.
Coleções
Listar Coleções
GET /api/v1/collections/
Retorna coleções visíveis para o usuário autenticado (próprias + públicas assinadas).
Resposta: 200 OK
[
{
"uuid": "a1b2c3...",
"name": "Project Docs",
"slug": "project-docs",
"description": "Technical documentation",
"document_count": 15,
"total_chunks": 342,
"is_public": false,
"is_subscribed": false,
"created_at": "2026-03-01T10:00:00Z"
}
]
Criar Coleção
POST /api/v1/collections/
Cria uma nova coleção pertencente ao usuário autenticado.
Corpo da Requisição:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name |
string | Sim | Nome da coleção (não pode estar vazio) |
description |
string | Não | Descrição opcional |
Resposta: 201 Created — Objeto completo da coleção
{
"uuid": "a1b2c3...",
"name": "Project Docs",
"slug": "project-docs",
"description": "Technical documentation",
"document_count": 0,
"total_chunks": 0,
"is_public": false,
"is_subscribed": false,
"created_at": "2026-03-23T10:00:00Z"
}
Erros:
400— Nome ausente ou vazio
Exemplo:
curl -X POST https://your-instance/api/v1/collections/ \
-H "Authorization: Bearer aqn_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "Project Docs", "description": "Technical documentation"}'
Obter Coleção
GET /api/v1/collections/{uuid}/
Resposta: 200 OK — Objeto da coleção
Atualizar Coleção
PATCH /api/v1/collections/{uuid}/
Atualiza o nome e/ou descrição de uma coleção. Somente o proprietário.
Corpo da Requisição: Qualquer subconjunto dos seguintes campos:
| Campo | Tipo | Descrição |
|---|---|---|
name |
string | Novo nome da coleção |
description |
string | Nova descrição |
Resposta: 200 OK — Objeto da coleção atualizado
Erros:
400— Erro de validação (ex.: nome vazio)403— Não é o proprietário da coleção404— Coleção não encontrada
Exemplo:
curl -X PATCH https://your-instance/api/v1/collections/{uuid}/ \
-H "Authorization: Bearer aqn_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "Renamed Docs"}'
Excluir Coleção
DELETE /api/v1/collections/{uuid}/
Exclusão suave de uma coleção e todos os seus documentos. Somente o proprietário. As entradas do índice de busca são removidas imediatamente; os blobs são mantidos por um período de carência de 7 dias antes da exclusão permanente.
Resposta: 204 No Content
Erros:
403— Não é o proprietário da coleção404— Coleção não encontrada
Exemplo:
curl -X DELETE https://your-instance/api/v1/collections/{uuid}/ \
-H "Authorization: Bearer aqn_your_api_key" \
-w "\nHTTP %{http_code}\n"
Documentos
Listar Documentos
GET /api/v1/documents/
Retorna documentos de todas as coleções visíveis.
Parâmetros de Consulta:
| Parâmetro | Tipo | Descrição |
|---|---|---|
tag |
string | Filtrar por tag (sem distinção de maiúsculas/minúsculas) |
collection |
string | Filtrar por slug da coleção |
Resposta: 200 OK
[
{
"uuid": "d4e5f6...",
"title": "Annual Report 2025",
"source_type": "pdf",
"status": "indexed",
"tags": ["finance", "annual"],
"chunks_count": 24,
"original_filename": "report-2025.pdf",
"file_size": 102400,
"collection_name": "Project Docs",
"collection_slug": "project-docs",
"created_at": "2026-03-01T10:00:00Z"
}
]
Enviar Documentos
POST /api/v1/collections/{uuid}/documents/
Envie um ou mais documentos para uma coleção.
Autenticação: Requer permissão de escrita — chaves de acesso total ou chaves restritas com permissão de escrita na coleção.
Requisição: multipart/form-data
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
file |
file | Um entre file/files | Envio de arquivo único |
files |
file[] | Um entre file/files | Envio em lote (múltiplos arquivos) |
title |
string | Não | Título do documento (padrão: nome do arquivo) |
tags |
string | Não | Lista de tags separadas por vírgula |
source_type |
string | Não | Tipo de arquivo manual (detectado automaticamente pela extensão se omitido) |
Resposta para arquivo único: 201 Created
{
"uuid": "d4e5f6...",
"title": "Annual Report 2025",
"source_type": "pdf",
"status": "pending",
"original_filename": "report-2025.pdf",
"file_size": 102400,
"tags": ["finance", "annual"],
"collection_name": "Project Docs",
"created_at": "2026-03-22T10:00:00Z"
}
Resposta para envio em lote: 201 Created
{
"uploaded": [
{
"uuid": "d4e5f6...",
"title": "Annual Report 2025",
"source_type": "pdf",
"status": "pending",
"original_filename": "report-2025.pdf",
"file_size": 102400,
"tags": [],
"collection_name": "Project Docs",
"created_at": "2026-03-22T10:00:00Z"
}
],
"skipped": [
{
"filename": "image.png",
"reason": "Unsupported file type."
}
],
"total_uploaded": 1,
"total_skipped": 1
}
Erros:
400— Nenhum arquivo fornecido, tipo de arquivo não suportado ou arquivo muito grande403— Acesso de escrita necessário404— Coleção não encontrada
Exemplo — arquivo único:
curl -X POST https://your-instance/api/v1/collections/{uuid}/documents/ \
-H "Authorization: Bearer aqn_your_api_key" \
-F "file=@report-2025.pdf" \
-F "title=Annual Report 2025" \
-F "tags=finance,annual"
Exemplo — envio em lote:
curl -X POST https://your-instance/api/v1/collections/{uuid}/documents/ \
-H "Authorization: Bearer aqn_your_api_key" \
-F "files=@report-2025.pdf" \
-F "files=@summary.docx" \
-F "tags=finance"
Substituir Documento
POST /api/v1/documents/{uuid}/replace/
Substitui o arquivo de um documento e o reprocessa. O UUID do documento é preservado; as entradas de busca antigas são removidas e o novo arquivo é processado do zero.
Autenticação: Requer permissão de escrita — chaves de acesso total ou chaves restritas com permissão de escrita na coleção.
Requisição: multipart/form-data
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
file |
file | Sim | Arquivo de substituição |
title |
string | Não | Substituir título do documento (mantém o título existente se omitido) |
tags |
string | Não | Lista de tags separadas por vírgula (substitui as tags existentes se fornecidas) |
source_type |
string | Não | Tipo de arquivo manual (detectado automaticamente pela extensão se omitido) |
Resposta: 200 OK — Objeto do documento com status: "pending"
{
"uuid": "d4e5f6...",
"title": "Annual Report 2026",
"source_type": "pdf",
"status": "pending",
"original_filename": "report-2026.pdf",
"file_size": 110592,
"tags": ["finance", "annual"],
"collection_name": "Project Docs",
"created_at": "2026-03-01T10:00:00Z"
}
Erros:
400— Nenhum arquivo fornecido ou tipo de arquivo não suportado403— Acesso de escrita necessário404— Documento não encontrado
Exemplo:
curl -X POST https://your-instance/api/v1/documents/{uuid}/replace/ \
-H "Authorization: Bearer aqn_your_api_key" \
-F "file=@report-2026.pdf" \
-F "title=Annual Report 2026"
Baixar Documento
GET /api/v1/documents/{uuid}/download/
Baixa o arquivo original enviado. Retorna um redirecionamento 302 para uma URL assinada com tempo limitado (válida por 1 hora).
Autenticação: Qualquer chave de API válida ou autenticação de sessão que possa ver o documento — coleções próprias ou coleções públicas assinadas.
Resposta: 302 Found — Redirecionamento para URL SAS do Azure Blob Storage
Erros:
404— Documento não encontrado ou nenhum arquivo disponível (documentos somente texto ou URL não possuem arquivo armazenado)
Exemplo:
curl -L -H "Authorization: Bearer aqn_..." \
https://aqoon.ai/api/v1/documents/{uuid}/download/ \
-o file.pdf
Use a flag -L para seguir o redirecionamento automaticamente. A URL assinada expira após 1 hora.
Obter Detalhes do Documento
GET /api/v1/documents/{uuid}/
Resposta: 200 OK — Inclui content_text, error_message e array de chunks.
{
"uuid": "d4e5f6...",
"title": "Annual Report 2025",
"source_type": "pdf",
"status": "indexed",
"tags": ["finance", "annual"],
"chunks_count": 24,
"original_filename": "report-2025.pdf",
"file_size": 102400,
"content_text": "Full extracted text...",
"error_message": "",
"collection_name": "Project Docs",
"collection_slug": "project-docs",
"created_at": "2026-03-01T10:00:00Z",
"chunks": [
{
"id": "uuid",
"content": "Chunk text content...",
"chunk_index": 0,
"embedding_model": "text-embedding-3-small"
}
]
}
Pesquisar
Busca Híbrida
POST /api/v1/search/
Corpo da Requisição:
{
"query": "payment terms",
"collection": "project-docs",
"limit": 5
}
| Campo | Tipo | Obrigatório | Padrão |
|---|---|---|---|
query |
string | Sim | — |
collection |
slug | Não | Todas as coleções visíveis |
limit |
int | Não | 5 (max: 50) |
Resposta: 200 OK
{
"query": "payment terms",
"count": 3,
"results": [
{
"content": "Matching chunk text...",
"title": "Contract Document",
"document_id": "uuid",
"collection_name": "Legal",
"tags": ["contract"],
"score": 0.89
}
]
}
Assinaturas de Coleções
Assinar uma Coleção Pública
POST /api/v1/collections/{slug}/subscribe/
Resposta: 200 OK
{
"status": "subscribed",
"collection": "project-docs"
}
Erros:
404— Coleção não encontrada ou não pública
Cancelar Assinatura de uma Coleção
DELETE /api/v1/collections/{slug}/subscribe/
Resposta: 200 OK
{
"status": "unsubscribed",
"collection": "project-docs"
}
Erros:
404— Assinatura não encontrada
Gerenciamento de Chaves de API (KaaS)
As chaves de API KaaS permitem que desenvolvedores externos pesquisem suas coleções. Gerenciadas pela página Chaves de API na interface web ou pela API REST.
Listar / Criar Chaves de API
GET /api/v1/keys/
POST /api/v1/keys/
Corpo da Requisição de Criação:
{
"name": "Acme Corp Key"
}
Resposta de Criação: 201 Created
{
"uuid": "key-uuid",
"name": "Acme Corp Key",
"prefix": "aqn_abc123...",
"key": "aqn_full_key_here",
"is_active": true,
"created_at": "2026-03-01T10:00:00Z"
}
O campo key é retornado apenas no momento da criação.
Rotacionar Chave de API
POST /api/v1/keys/{uuid}/rotate/
Revoga a chave de API existente e cria uma nova com o mesmo nome e concessões de acesso a coleções. A chave antiga é desativada imediatamente.
Resposta: 201 Created
{
"uuid": "new-key-uuid",
"name": "Acme Corp Key",
"prefix": "aqn_abc123...",
"key": "aqn_new_full_key_here",
"is_active": true,
"is_full_access": false,
"created_at": "2026-03-13T10:00:00Z"
}
O campo key é retornado apenas no momento da rotação. Armazene-o com segurança — ele não pode ser recuperado novamente.
Erros:
404— Chave de API não encontrada ou não pertence ao usuário autenticado
Conceder / Revogar Acesso a Coleções
POST /api/v1/keys/{uuid}/collections/
DELETE /api/v1/keys/{uuid}/collections/{collection-slug}/
Corpo da Requisição de Concessão:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
collection |
slug | Sim | Slug da coleção para conceder acesso |
permission |
string | Não | "read" (padrão) ou "write" |
{
"collection": "my-collection",
"permission": "write"
}
Se já existir uma concessão para esta chave e coleção, o nível de permissão é atualizado.
Resposta da Listagem de Concessões: GET /api/v1/keys/{uuid}/collections/ — 200 OK
[
{
"collection": "my-collection",
"permission": "write"
},
{
"collection": "public-docs",
"permission": "read"
}
]
Estatísticas de Uso
GET /api/v1/keys/usage/?days=30
GET /api/v1/keys/{uuid}/usage/
Webhooks
Webhooks permitem receber notificações em tempo real quando o processamento de documentos é concluído. Configure uma URL de webhook por organização para receber eventos document.indexed e document.failed. Os payloads são assinados com HMAC-SHA256 e entregues com retentativas com backoff exponencial em caso de falha.
Obter Configuração do Webhook
GET /api/v1/webhooks/
Retorna a configuração atual do webhook para a organização.
Resposta: 200 OK
{
"configured": true,
"url": "https://your-app.example.com/hooks/aqoon",
"is_active": true
}
O segredo nunca é retornado após a criação inicial.
curl https://your-instance/api/v1/webhooks/ \
-H "Authorization: Bearer aqn_your_api_key"
Criar ou Atualizar Webhook
POST /api/v1/webhooks/
Cria um novo webhook ou atualiza a URL de um existente.
Corpo da Requisição:
{
"url": "https://your-app.example.com/hooks/aqoon"
}
Na criação: 201 Created — secret returned once, store it securely.
{
"configured": true,
"url": "https://your-app.example.com/hooks/aqoon",
"is_active": true,
"secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Na atualização (webhook já existe): 200 OK — secret is not returned.
{
"configured": true,
"url": "https://your-app.example.com/hooks/aqoon-updated",
"is_active": true
}
# Create
curl -X POST https://your-instance/api/v1/webhooks/ \
-H "Authorization: Bearer aqn_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-app.example.com/hooks/aqoon"}'
# Update URL
curl -X POST https://your-instance/api/v1/webhooks/ \
-H "Authorization: Bearer aqn_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-app.example.com/hooks/aqoon-v2"}'
Excluir Webhook
DELETE /api/v1/webhooks/
Remove a configuração do webhook. Nenhum evento será mais entregue.
Resposta: 200 OK
curl -X DELETE https://your-instance/api/v1/webhooks/ \
-H "Authorization: Bearer aqn_your_api_key"
Enviar Evento de Teste
POST /api/v1/webhooks/test/
Enfileira um evento de teste para ser entregue à URL do webhook configurada imediatamente. Retorna 404 se nenhum webhook estiver configurado.
Resposta: 200 OK
curl -X POST https://your-instance/api/v1/webhooks/test/ \
-H "Authorization: Bearer aqn_your_api_key"
Formato do Payload
Cada evento é entregue como um POST JSON para sua URL de webhook:
{
"event": "document.indexed",
"timestamp": "2026-03-23T10:00:00Z",
"data": {
"uuid": "a1b2c3...",
"status": "indexed",
"title": "Q1 Report",
"source_type": "pdf",
"collection_uuid": "d4e5f6...",
"collection_name": "Finance Docs",
"chunks_count": 42,
"tags": "finance,quarterly",
"error_message": null,
"original_filename": "q1-report.pdf",
"file_size": 204800
}
}
O campo event é document.indexed (processamento bem-sucedido) ou document.failed (processamento falhou). Em caso de falha, error_message contém uma descrição.
Verificação de Assinatura
Cada requisição de webhook inclui dois cabeçalhos de segurança:
X-Aqoon-Signature: sha256=<hex-digest>X-Aqoon-Timestamp: <unix-timestamp>
A assinatura é um HMAC-SHA256 de {timestamp}.{raw-body} usando seu segredo do webhook. Sempre verifique a assinatura antes de processar o payload.
import hashlib
import hmac
def verify_signature(secret: str, timestamp: str, body: bytes, signature: str) -> bool:
message = f"{timestamp}.".encode() + body
expected = hmac.new(secret.encode(), message, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
import { createHmac, timingSafeEqual } from 'crypto';
function verifySignature(secret: string, timestamp: string, body: Buffer, signature: string): boolean {
const message = Buffer.concat([Buffer.from(`${timestamp}.`), body]);
const expected = 'sha256=' + createHmac('sha256', secret).update(message).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
Para se proteger contra ataques de replay, rejeite eventos onde X-Aqoon-Timestamp tem mais de 5 minutos de atraso.
Endpoint MCP
O servidor MCP está acessível em /mcp usando transporte HTTP Streamable.
Autenticação: Authorization: Bearer aqn_<key>
Ferramentas Disponíveis:
| Ferramenta | Descrição |
|---|---|
search_documents |
Busca híbrida de texto + vetor com filtro de coleção e limite de resultados opcionais |
list_collections |
Listar todas as coleções com contagem de documentos e descrições |
get_document_info |
Obter detalhes completos do documento e trechos de conteúdo por UUID |
search_by_tag |
Encontrar todos os documentos com uma tag específica |
Tratamento de Erros
Códigos de Status HTTP
| Código | Significado |
|---|---|
200 |
Sucesso |
201 |
Criado |
400 |
Requisição inválida (erro de validação) |
401 |
Não autorizado (token/chave de API ausente ou inválida) |
404 |
Recurso não encontrado |
429 |
Limite de requisições excedido |
500 |
Erro do servidor |
Formato de Resposta de Erro
Todos os erros usam um envelope consistente com um campo error e um campo code legível por máquina:
{
"error": "Collection not found.",
"code": "COLLECTION_NOT_FOUND"
}
Erros de validação incluem um objeto fields com detalhes por campo:
{
"error": "Validation failed.",
"code": "VALIDATION_FAILED",
"fields": {
"name": ["This field is required."],
"collection": ["Collection not found."]
}
}
Use code para tratamento programático de erros (ex.: lógica switch / if no seu cliente). Use error para exibição ao usuário final.
Códigos de Erro
401 — Autenticação
| Código | Descrição |
|---|---|
INVALID_API_KEY |
Chave de API não encontrada ou incompatibilidade de hash |
API_KEY_EXPIRED |
A chave de API passou da data de expiração |
USER_ACCOUNT_DISABLED |
A conta do usuário da chave está inativa |
AUTHENTICATION_REQUIRED |
Nenhuma credencial válida fornecida |
403 — Autorização
| Código | Descrição |
|---|---|
WRITE_ACCESS_REQUIRED |
Chave restrita precisa de permissão de escrita para esta coleção |
NOT_COLLECTION_OWNER |
Apenas o proprietário da coleção pode atualizar ou excluir |
SCOPED_KEY_FORBIDDEN |
Chaves restritas não podem executar esta ação |
404 — Não Encontrado
| Código | Descrição |
|---|---|
COLLECTION_NOT_FOUND |
A coleção não existe ou não é visível para esta chave |
DOCUMENT_NOT_FOUND |
O documento não existe ou não está acessível |
DOCUMENT_FILE_NOT_FOUND |
O documento existe, mas o arquivo original está ausente do armazenamento |
API_KEY_NOT_FOUND |
Registro de chave de API não encontrado |
GRANT_NOT_FOUND |
Concessão de acesso à coleção não encontrada |
SUBSCRIPTION_NOT_FOUND |
Assinatura de coleção não encontrada |
WEBHOOK_NOT_CONFIGURED |
Nenhum webhook foi configurado para esta conta |
400 — Validação
| Código | Descrição |
|---|---|
VALIDATION_FAILED |
Um ou mais campos falharam na validação (veja o objeto fields) |
NO_FILES_PROVIDED |
A requisição de envio em lote não incluiu arquivos |
NO_FILE_PROVIDED |
A requisição de envio único não incluiu arquivo |
UNSUPPORTED_FILE_TYPE |
Extensão do arquivo ou tipo MIME não é suportado |
FILE_TOO_LARGE |
O arquivo excede o limite de 50 MB |
INVALID_FILE_CONTENT |
O conteúdo do arquivo não corresponde ao tipo declarado (verificação de bytes mágicos) |
URL_REQUIRED |
Um tipo de origem URL foi especificado, mas nenhuma URL foi fornecida |
NAME_REQUIRED |
Um campo de nome obrigatório estava vazio ou ausente |
429 — Limite de Requisições
| Código | Descrição |
|---|---|
RATE_LIMIT_EXCEEDED |
Cota de requisições excedida; verifique os cabeçalhos X-RateLimit-* para horários de reinício |
500 — Erros do Servidor
| Código | Descrição |
|---|---|
SEARCH_UNAVAILABLE |
O Azure AI Search está temporariamente indisponível |
UPLOAD_FAILED |
O arquivo não pôde ser gravado no armazenamento blob |
WEBHOOK_TEST_FAILED |
A entrega do evento de teste para a URL do webhook configurada falhou |