API HTTP
O servidor aceita só GET, em três rotas. Os exemplos usam o endereço padrão, http://127.0.0.1:8790; para subir o servidor, veja Subir o servidor.
| Rota | Parâmetros | Resposta |
|---|---|---|
/pessoa | semente, hoje, uf e dominioEmail, todos opcionais | o envelope de uma pessoa, em JSON |
/pessoas | n (obrigatório, de 1 a 10 000), os quatro de /pessoa, formato, dialeto, tabela, campos | o lote, no formato pedido |
/saude | nenhum | {"ok": true, "formato": 1, "motor": "0.4.1"} |
Os parâmetros têm o nome das opções da CLI em camelCase: --dominio-email vira dominioEmail. Um nome que a rota não conhece dá 400, com a lista dos aceitos (veja Erros).
/pessoa
| Parâmetro | Valor | Sem ele |
|---|---|---|
semente | um inteiro seguro (negativo vale) ou um texto de 1 a 256 caracteres, sem caractere de controle | sorteia uma de 16 dígitos hexadecimais e a devolve no envelope |
hoje | uma data AAAA-MM-DD | usa a data de hoje em São Paulo |
uf | uma das 27 siglas, em qualquer caixa | a pessoa sai de qualquer UF |
dominioEmail | um domínio, como example.com | tuamaeaquelaursa.com, uma caixa de entrada pública |
curl -fsS 'http://127.0.0.1:8790/pessoa?semente=42&hoje=2026-10-05'
{
"formato": 1,
"motor": "0.4.1",
"semente": "42",
"hoje": "2026-10-05",
"pessoa": {
"nome": {
"sexo": "M",
"prenome": "Márcio",
"sobrenomes": [
"Carvalho",
"Rodrigues"
],
"completo": "Márcio Carvalho Rodrigues",
"noCartao": "MARCIO C RODRIGUES"
},
"nascimento": {
"iso": "1970-02-26",
"br": "26/02/1970",
"idade": 56
},
"cpf": "634.132.403-07",
"rg": {
"numero": "92.957.904-5",
"orgaoEmissor": "SSP",
"uf": "SP"
},
"pis": "166.24491.26-5",
"tituloEleitor": "5022 4149 1171",
"celular": {
"ddd": "98",
"numero": "97702-9128",
"formatado": "(98) 97702-9128",
"digitos": "98977029128",
"e164": "+5598977029128"
},
"email": {
"usuario": "marcio-rodrigues-0337",
"endereco": "marcio-rodrigues-0337@tuamaeaquelaursa.com",
"caixaUrl": "https://tuamaeaquelaursa.com/marcio-rodrigues-0337"
},
"senha": "g4JXwr#&PM8r",
"endereco": {
"cep": "65071-377",
"logradouro": "Avenida Litorânea",
"bairro": "Calhau",
"cidade": "São Luís",
"uf": "MA",
"ddd": "98",
"numero": "199",
"complemento": "Apto 171"
},
"empresa": {
"razaoSocial": "Carvalho & Rodrigues Engenharia Ltda",
"nomeFantasia": "Rodrigues Store",
"cnpj": "90.849.558/0001-39"
},
"cartao": {
"bandeira": "mastercard",
"numero": "5555555555554444",
"numeroFormatado": "5555 5555 5555 4444",
"titular": "MARCIO C RODRIGUES",
"validade": "11/28",
"mes": "11",
"ano": "28",
"cvv": "388"
}
}
}
A resposta é o mesmo texto que a CLI imprime para as mesmas opções:
diff <(botai pessoa --semente 42 --hoje 2026-10-05) \
<(curl -fsS 'http://127.0.0.1:8790/pessoa?semente=42&hoje=2026-10-05') \
&& echo iguais
Com dominioEmail, o domínio vai para minúsculas e a caixaUrl vira null. O resto da pessoa não muda:
curl -fsS 'http://127.0.0.1:8790/pessoa?semente=42&hoje=2026-10-05&dominioEmail=Example.COM' \
| grep -A4 '"email"'
"email": {
"usuario": "marcio-rodrigues-0337",
"endereco": "marcio-rodrigues-0337@example.com",
"caixaUrl": null
},
O que cada opção muda na pessoa está em A pessoa. Para reproduzir uma pessoa, passe a semente e o hoje, e fixe a versão: sem hoje, a mesma semente gera outra pessoa no dia seguinte (veja Semente e hoje).
/pessoas
| Parâmetro | Valor |
|---|---|
n | obrigatório: um inteiro de 1 a 10 000 |
semente, hoje, uf, dominioEmail | como em /pessoa |
formato | json (o padrão), ndjson, csv ou sql |
dialeto | postgres, mysql ou sqlite, em minúsculas; só com formato=sql |
tabela | tabela ou esquema.tabela; só com formato=sql |
campos | as colunas, separadas por vírgula; só com formato=csv ou formato=sql |
A resposta é o mesmo texto de botai pessoas com as mesmas opções:
diff <(botai pessoas -n 3 --semente demo --hoje 2026-10-08 --formato csv --campos nome,cpf,email) \
<(curl -fsS 'http://127.0.0.1:8790/pessoas?n=3&semente=demo&hoje=2026-10-08&formato=csv&campos=nome,cpf,email') \
&& echo iguais
Os formatos, as 33 colunas e a proteção do tabela estão em Um lote de pessoas e em Colunas. Dentro de um lote, e-mail, CPF e CNPJ não se repetem; a regra do lote está em Lote e unicidade.
CSV
curl -fsS 'http://127.0.0.1:8790/pessoas?n=3&semente=demo&hoje=2026-10-08&formato=csv&campos=nome,cpf,email'
nome,cpf,email
Isabela Freitas Santos,550.160.642-96,isabela-santos-7825@tuamaeaquelaursa.com
Vitória Alves Carvalho,843.495.439-70,vitoria-carvalho-1721@tuamaeaquelaursa.com
Lucas Gabriel Pereira Oliveira,750.346.866-19,lucas-oliveira-9018@tuamaeaquelaursa.com
SQL
curl -fsS 'http://127.0.0.1:8790/pessoas?n=2&semente=demo&hoje=2026-10-08&formato=sql&dialeto=sqlite&tabela=app.clientes&campos=nome,cpf,email'
-- botai: formato 1, motor 0.4.1, semente demo, hoje 2026-10-08
INSERT INTO "app"."clientes" ("nome", "cpf", "email") VALUES ('Isabela Freitas Santos', '550.160.642-96', 'isabela-santos-7825@tuamaeaquelaursa.com');
INSERT INTO "app"."clientes" ("nome", "cpf", "email") VALUES ('Vitória Alves Carvalho', '843.495.439-70', 'vitoria-carvalho-1721@tuamaeaquelaursa.com');
A 1ª linha é um comentário com o formato, o motor, a semente e o hoje. O SQL traz só os INSERTs: crie a tabela antes (veja Receitas de banco).
ndjson
Um envelope por linha, cada um com a semente exata da pessoa:
curl -fsS 'http://127.0.0.1:8790/pessoas?n=3&semente=demo&hoje=2026-10-08&formato=ndjson' \
| grep -o '"semente":"[^"]*"'
"semente":"demo/0"
"semente":"demo/1"
"semente":"demo/2"
JSON
Sem formato, a resposta é um envelope só, com a lista em pessoas: {"formato": 1, "motor": "0.4.1", "semente": "demo", "hoje": "2026-10-08", "pessoas": [...]}.
/saude
curl -fsS http://127.0.0.1:8790/saude
{
"ok": true,
"formato": 1,
"motor": "0.4.1"
}
O /saude ignora parâmetros que não conhece. Use-o para saber se o servidor está no ar, sempre com GET.
Content-Type e cabeçalhos
| Resposta | Content-Type |
|---|---|
/pessoa, /saude e erros | application/json; charset=utf-8 |
formato=json | application/json; charset=utf-8 |
formato=ndjson | application/x-ndjson; charset=utf-8 |
formato=csv | text/csv; charset=utf-8; header=present |
formato=sql | application/sql; charset=utf-8 |
Além do Content-Type, o servidor manda só dois cabeçalhos seus: Cache-Control: no-store e X-Content-Type-Options: nosniff.
curl -fsS -D - -o /dev/null 'http://127.0.0.1:8790/pessoas?n=1&formato=csv' \
| grep -i -E '^(content-type|cache-control|x-content-type-options):'
Cache-Control: no-store
X-Content-Type-Options: nosniff
Content-Type: text/csv; charset=utf-8; header=present
Não há cabeçalho de CORS: veja Segurança e limites.
Erros
Um pedido errado não derruba o servidor. A resposta é um JSON {"erro": "..."} que diz qual parâmetro está errado:
| Status | Quando |
|---|---|
| 400 | parâmetro desconhecido, repetido ou vazio, n fora de 1 a 10 000, valor inválido |
| 404 | rota que não é /pessoa, /pessoas nem /saude |
| 405 | método que não é GET, com o cabeçalho Allow: GET |
curl -sS 'http://127.0.0.1:8790/pessoa?dominio-email=example.com'
{
"erro": "parâmetro desconhecido: dominio-email (aceitos: semente, hoje, uf, dominioEmail)"
}
Num script, curl -fsS sai com 22 em qualquer status 400 ou mais:
curl -fsS 'http://127.0.0.1:8790/pessoas?n=10001'
Todas as mensagens estão em Mensagens de erro.
Clientes
O servidor não precisa de pacote no cliente: qualquer linguagem com HTTP serve. Há receitas para Python, Go e Java. Para preencher uma página com o motor do navegador, a pessoa pode vir do GET /pessoa: o motor recebe envelope.pessoa e envelope.hoje (veja O IIFE).