Gerar SQL: POST /v1/ask
Recebe uma pergunta em linguagem natural e devolve um SELECT validado pelo SQL Guard, com os valores em params. Cada chamada faz de 1 a 2 chamadas à LLM do seu tenant (a segunda é uma correção automática quando o primeiro SQL é rejeitado).
Requisição
Headers:
Authorization: Bearer tsk_1a2b3c4d_...
Content-Type: application/json
Accept-Language: pt-BR (opcional)
Corpo:
{
"question": "Quantos pedidos foram feitos ontem?",
"end_user": "5f0c3a9e7b1d4e2f8a6c0b9d3e7f1a2c4b5d6e7f8091a2b3c4d5e6f708192a3b",
"max_rows": 100,
"locale": "pt-BR"
}
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
question | string | sim | A pergunta, com até 2.000 caracteres. |
end_user | string | sim* | Identificador opaco da pessoa que perguntou, de 16 a 128 caracteres (A-Z, a-z, 0-9, _, -). Veja Identificador do usuário final. *Obrigatório para a maioria dos clientes. |
max_rows | inteiro | não | Máximo de linhas, ≥ 1. Padrão 100, teto 1.000. A API aplica um LIMIT no SQL; agregações que retornam uma única linha ficam sem LIMIT. |
locale | string | não | Idioma de message e explanation. Precedência: este campo → header Accept-Language → idioma padrão do tenant → pt-BR. |
Campos desconhecidos são recusados com 422 invalid_request. O corpo inteiro pode ter até 96 KiB.
Resposta 200
{
"sql": "SELECT count(*) AS total FROM public.pedidos WHERE criado_em >= %(start)s AND criado_em < %(end)s",
"params": { "start": "2026-10-22", "end": "2026-10-23" },
"dialect": "postgres",
"tables": ["public.pedidos"],
"explanation": "Conta os pedidos criados ontem.",
"locale": "pt-BR",
"request_id": "req_0f3c9a7d2b6e4f1a8c5d0e9b7a6f3c21"
}
| Campo | Tipo | Descrição |
|---|---|---|
sql | string | Um único SELECT, no dialeto do seu schema, com placeholders %(nome)s. |
params | objeto | Valores dos placeholders: string, número, booleano ou null. Pode ser {}. |
dialect | string | postgres, mysql ou firebird. |
tables | lista de strings | Tabelas usadas pela consulta. |
explanation | string ou null | Explicação curta do que a consulta faz, no idioma resolvido. |
locale | string | Idioma usado na resposta. |
request_id | string | req_ + 32 caracteres hexadecimais. Use-o para enviar feedback e buscar a resposta no histórico. |
O mesmo request_id vem no header X-Request-ID de toda resposta, inclusive das de erro.
Sobre o SQL devolvido
- Os nomes de tabelas e colunas são os do seu banco, exatamente como estão no DDL cadastrado.
- Texto do usuário nunca é concatenado ao SQL: valores como nomes, datas e termos de busca chegam em
params. - Todo
%que não é placeholder sai escapado como%%(por exemploLIKE 'A%%'), no estilo dos drivers Python. Por isso passe sempreparamsao driver, mesmo vazio. Veja Executar o SQL. - Datas relativas ("ontem", "mês passado") são resolvidas no momento da pergunta, com a data de hoje enviada à LLM.
Erros comuns
| HTTP | code | O que fazer |
|---|---|---|
| 400 | end_user_required | Envie end_user. |
| 401 | invalid_api_key | Corrija a chave. |
| 409 | schema_not_configured, llm_not_configured | O administrador precisa concluir a configuração no painel. |
| 422 | no_answer | O schema não permite responder; peça para o usuário reformular. |
| 422 | sql_rejected | O SQL gerado não passou no Guard, mesmo após a correção automática. |
| 429 | rate_limited | Aguarde o tempo do header Retry-After. |
| 502 | llm_error | Falha no provedor de LLM; veja details.reason. |
A lista completa está em Erros.
Latência
Uma pergunta leva normalmente alguns segundos, e até o dobro quando a correção automática roda. Configure o timeout de leitura do cliente HTTP em pelo menos 60 segundos e não repita automaticamente um POST /v1/ask que deu timeout, porque cada tentativa gasta tokens da sua LLM.
Exemplo
curl -sS -X POST "https://app.datafala.com.br/v1/ask" \
-H "Authorization: Bearer $DATAFALA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"question": "Top 5 clientes por faturamento em 2026", "end_user": "'"$END_USER"'", "max_rows": 5}'
Mais exemplos em Exemplos de integração.