---
title: "SDK Lua"
lang: pt-BR
canonical: https://doc.apibrasil.io/sdks/lua
markdown: https://doc.apibrasil.io/sdks/lua.md
source: apibrasil-documentation
---

# SDK Lua

- **Situação:** publicado
- **Instalação:** `luarocks install apibrasil`
- **Registry:** LuaRocks — https://luarocks.org/modules/jhowbhz/apibrasil
- **Repositório:** https://github.com/APIBrasil/apigratis-sdk-lua

## Não invente a assinatura

NÃO INVENTE A API DO SDK DE Lua. Cada biblioteca deste catálogo tem construtor, nomes de método e formato de retorno próprios, e nenhum deles se deduz do nome do pacote. Abra o README do repositório acima e use exatamente o que está escrito lá. Se você não conseguir abrir o repositório, NÃO CHUTE: escreva o cliente em HTTP puro, seguindo a seção abaixo, e diga na resposta que foi isso que você fez e por quê.

## Como autenticar

O Bearer vai no cabeçalho Authorization, em toda chamada. O DeviceToken só nas APIs cobradas por plano — as por crédito não pedem. É o mesmo par que o SDK põe por você.

Com homolog verdadeiro no corpo, o gateway responde de uma base fixa. O CPF 00000000000 é o dela e não é de ninguém.

## O repositório no GitHub

- **Estrelas:** 0
- **Forks:** 0
- **Issues abertas:** 0
- **Linguagem:** Lua
- **Licença:** MIT License
- **Último envio:** 28 de julho de 2026
- **git clone:** `https://github.com/APIBrasil/apigratis-sdk-lua.git`

## README do repositório

Reproduzido do repositório, no ramo padrão. É a documentação de quem mantém a biblioteca: a assinatura do SDK é o que está aqui, e não o que se deduz do nome do pacote.

# SDK LUA - APIGratis by API BRASIL 💧

SDK oficial Lua da plataforma [APIBrasil](https://apibrasil.com.br) — WhatsApp, SMS, consultas de CPF/CNPJ, veículos, CEP, correios, pagamentos PIX/boleto e muito mais.

[![LuaRocks](https://img.shields.io/luarocks/v/jhowbhz/apibrasil)](https://luarocks.org/modules/jhowbhz/apibrasil)
[![CI](https://github.com/APIBrasil/apigratis-sdk-lua/actions/workflows/ci.yml/badge.svg)](https://github.com/APIBrasil/apigratis-sdk-lua/actions/workflows/ci.yml)
<a href="https://github.com/APIBrasil/apigratis-sdk-lua/issues" target="_blank"><img alt="GitHub issues" src="https://img.shields.io/github/issues/APIBrasil/apigratis-sdk-lua"></a>
<a href="https://github.com/APIBrasil/apigratis-sdk-lua/network" target="_blank"><img alt="GitHub forks" src="https://img.shields.io/github/forks/APIBrasil/apigratis-sdk-lua"></a>
<a href="https://github.com/APIBrasil/apigratis-sdk-lua/stargazers" target="_blank"><img alt="GitHub stars" src="https://img.shields.io/github/stars/APIBrasil/apigratis-sdk-lua"></a>

## Canais de suporte (Comunidade)

[![WhatsApp Group](https://img.shields.io/badge/WhatsApp-Channel-25D366?logo=whatsapp)](https://whatsapp.com/channel/0029VaMiaT6B4hdX3hrUcz3X)
[![Telegram Group](https://img.shields.io/badge/Telegram-Group-32AFED?logo=telegram)](https://t.me/apibrasil1)

## Instalação

```bash
luarocks install apibrasil
```

Requer **Lua >= 5.1** — funciona em Lua 5.1/5.2/5.3/5.4, LuaJIT e OpenResty.

O codec JSON acompanha a SDK, sem dependência externa. Para o HTTP, o rockspec instala `luasocket` + `luasec`; a SDK também aceita `lua-http`, `resty.http` (OpenResty) e o `curl` da máquina — veja [Transporte plugável](#transporte-plugável).

Obtenha suas credenciais em https://apibrasil.com.br

## Começando

```lua
local apibrasil = require("apibrasil")

local client = apibrasil.new({
  bearer_token = "SEU_BEARER_TOKEN",
  device_token = "SEU_DEVICE_TOKEN",
})

-- WhatsApp
local envelope, err = client.whatsapp:send_text({
  number = "5511999999999",
  text = "Olá! 👋",
})

-- Consulta CNPJ (por créditos)
local empresa = client.consulta:cnpj({ cnpj = "00000000000000" })
print(empresa.balance, empresa.data)
```

O `bearer_token` é o JWT do login; o `device_token` é o device dos serviços device-based.

As credenciais também podem vir só do ambiente — `apibrasil.from_env()` lê automaticamente `APIBRASIL_BEARER_TOKEN`, `APIBRASIL_DEVICE_TOKEN`, `APIBRASIL_SECRET_KEY` e `APIBRASIL_BASE_URL`.

Também é possível autenticar por email/senha — `apibrasil.login` devolve o cliente já autenticado, junto da sessão:

```lua
local client, session = apibrasil.login({
  email = "voce@empresa.com.br",
  password = "******",
})
```

Contas com 2FA concluem o login em três passos, aplicando o token com `client.auth:authenticate`:

```lua
local client = apibrasil.from_env()
local session = client.auth:login({ email = email, password = senha })

if client.auth.requires_2fa(session) then
  client.auth:send_2fa({ challenge = session.challenge, method = "email" })
  session = client.auth:verify_2fa({ challenge = session.challenge, code = "000000" })
end

client = client.auth:authenticate(session)
```

## Como a plataforma funciona

A API Brasil tem duas famílias de serviços:

| Família          | Autenticação                                   | Exemplos                                                                     |
| ---------------- | ---------------------------------------------- | ---------------------------------------------------------------------------- |
| **Device-based** | `Authorization: Bearer` + header `DeviceToken` | WhatsApp, SMS, veículos, CEP, correios, DDD, feriados, tradução, clima, OCR  |
| **Por créditos** | apenas `Authorization: Bearer` (debita saldo)  | `client.consulta`: `cpf`, `cnpj`, `veiculos`, Serasa, CNH                    |

Para os serviços device-based, crie um device com a `SecretKey` da API desejada (painel APIBrasil) e use o `device_token` retornado:

```lua
local device = client
  :with_options({ secret_key = "SUA_SECRET_KEY" })
  .devices:store({ device_name = "meu-bot", type = "server" })

client = client:with_device(device.device_token)
```

O cliente é um valor imutável: `with_device`, `with_bearer_token`, `with_secret_key`, `with_options` e `with_strict` devolvem sempre um **novo** cliente.

## Serviços disponíveis

Cada serviço é um campo do cliente, criado sob demanda:

| Campo                                            | Descrição                                                                                              |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| `client.whatsapp`                                | WhatsApp: `start`, `qrcode`, `send_text`, `send_file`, `send_audio`, fila (`queue`)...                 |
| `client.evolution`                               | Evolution API: `request(controller, action, body)`, `call(path, body)`, `queue(...)`                   |
| `client.whatsmeow`                               | WhatsMeow: `send_text`, `instance_create`, `instance_qr`, `request(action, body)`                      |
| `client.sms`                                     | SMS device-based (`send`) e por créditos (`send_with_credits`)                                         |
| `client.dados`                                   | Dados cadastrais device-based (`cpf`, `cnpj`, `lista_socios`...)                                       |
| `client.vehicles`                                | Veículos por placa (`dados`, `fipe`, `base_dados`, `base_fipe`)                                        |
| `client.fipe`                                    | Tabela FIPE (`consultar_marcas`, `consultar_modelos`...)                                               |
| `client.correios`                                | Correios (`rastreio`, `request`)                                                                       |
| `client.cep`                                     | CEP + geolocalização (`cep`, `cidades`, `estados`, `calcular_distancia`)                               |
| `client.geolocation` / `client.geomatrix`        | Geocoding e matriz de distâncias                                                                        |
| `client.recognize`                               | OCR / Google Vision (`base64`, `uri`)                                                                  |
| `client.ddd` / `client.holidays` / `client.translate` / `client.weather` | DDD, feriados, tradução, clima                                          |
| `client.loterias`                                | Loterias (`latest`, `resultado`)                                                                       |
| `client.database_ip`                             | GeoIP (`ip`)                                                                                           |
| `client.consulta`                                | Consultas por créditos: `cpf`, `cnpj`, `cnh`, `cep`, `veiculos`, `telefone`, `generic`                 |
| `client.ura` / `client.chip_virtual`             | URA reversa e chip virtual                                                                              |
| `client.bulk`                                    | Execução em lote (`direct`, `queue`)                                                                   |
| `client.auth`                                    | Login, 2FA, cadastro, recuperação de senha, perfil                                                     |
| `client.devices`                                 | CRUD de devices                                                                                        |
| `client.catalog`                                 | Catálogo de APIs, planos, documentações, servidores                                                    |
| `client.account`                                 | Saldo, faturas, notificações, tickets                                                                  |
| `client.payments`                                | Recargas e pagamentos PIX/boleto/cartão (Santander, Inter, Mercado Pago, Sicoob)                        |
| `client.ip_whitelist` / `client.bearer_rate_limit` | Segurança da conta                                                                                    |
| `client.reports`                                 | Relatórios e dashboard de consumo                                                                       |

Todo método recebe o body como tabela (ou `nil`) e termina com uma tabela de opções.

### WhatsApp

```lua
-- iniciar sessão e obter QR Code
client.whatsapp:start({ webhook_wh_message = "https://seu-webhook.com/mensagens" })

local qr = client.whatsapp:qrcode()
print(qr.response.qrcode) -- imagem do QR Code em base64

-- envios
client.whatsapp:send_text({ number = "5511999999999", text = "Olá!" })

client.whatsapp:send_file({
  number = "5511999999999",
  path = "https://exemplo.com/boleto.pdf",
})

client.whatsapp:send_location({
  number = "5511999999999",
  lat = -23.5,
  lng = -46.6,
})

-- qualquer action do catálogo
client.whatsapp:request("getAllChats")

-- fila assíncrona
client.whatsapp:queue("sendText", { number = "5511999999999", text = "por fila" })
```

O envelope device-based **é** o próprio JSON: os campos são lidos direto, e os poucos auxiliares têm nomes que não colidem com chaves da API.

```lua
local envelope = client.whatsapp:send_text({ number = numero, text = "Olá!" })

envelope.error       -- false
envelope.message     -- mensagem do gateway
envelope.response    -- payload do provedor
envelope.api_limit   -- limite do plano

envelope:is_error()            -- false
envelope:get("response.id")    -- acesso por caminho
envelope:raw()                 -- a tabela completa
```

### Consultas por créditos

```lua
local Consulta = require("apibrasil").Consulta

local cpf = client.consulta:cpf({ cpf = "00000000000" })
print(cpf.balance, cpf.data)

-- o campo `tipo` define o produto consultado — use o builder
client.consulta:cnpj(
  Consulta.new("lista-socios"):field("cnpj", "00000000000000")
)

-- modo homologação (sandbox, sem cobrança)
client.consulta:cnpj(
  Consulta.new("serasa-score-pj")
    :homolog()
    :field("cnpj", "00000000000000")
)

-- qualquer serviço do catálogo, e os créditos disponíveis
client.consulta:generic("cnh", { cpf = "00000000000" })
client.consulta:credits("cpf")
```

O builder também aceita `:lite()`, `:agrupados({...})`, `:extra({...})` e `:fields({...})`; qualquer método de serviço recebe o builder diretamente no lugar da tabela.

### Veículos e FIPE (device-based)

```lua
client.vehicles:dados({ placa = "ABC1234" })
client.vehicles:fipe({ placa = "ABC1234" })
client.fipe:consultar_marcas({ codigoTabelaReferencia = 300 })
```

### SMS

```lua
client.sms:send({ number = "5511999999999", message = "Olá!" })
client.sms:send_with_credits({ number = "5511999999999", message = "Olá!" })
```

### Pagamentos e recargas

```lua
local Payments = require("apibrasil.platform.payments")

client.payments:recharge({ amount = 50, type = "pix" })
client.payments:pix_generate(Payments.SANTANDER, { amount = 50 })
client.payments:pix_status("santander", "TX_ID")

-- bytes crus do PDF
local pdf = client.payments:boleto_pdf(Payments.INTER, "ID")
local file = assert(io.open("boleto.pdf", "wb"))
file:write(pdf)
file:close()
```

### Múltiplos devices

```lua
local bot1 = client:with_device("device_token_1")
local bot2 = client:with_device("device_token_2")

bot1.whatsapp:send_text({ number = numero, text = "do bot 1" })
bot2.whatsapp:send_text({ number = numero, text = "do bot 2" })
```

## Tratamento de erros

Toda chamada devolve `resultado` ou `nil, erro`; a falha carrega a categoria em `kind`:

| `kind`                  | Quando                                          |
| ----------------------- | ----------------------------------------------- |
| `validation`            | 400/422 — payload inválido                      |
| `authentication`        | 401 — token ausente/expirado                    |
| `insufficient_balance`  | 402 — sem saldo/créditos                        |
| `permission`            | 403 — sem permissão (ex: exige PJ)              |
| `not_found`             | 404/410 — sem dados / rota desativada           |
| `rate_limit`            | 429 — limite atingido (`retry_after`, em ms)    |
| `server`                | 5xx — erro do gateway/provedor                  |
| `network` / `timeout`   | falha antes da resposta                         |
| `api`                   | qualquer outra falha da API                     |

```lua
local consulta, err = client.consulta:cpf({ cpf = "00000000000" })

if err then
  if err:is_insufficient_balance() then
    print("Recarregue seus créditos")
  elseif err:is_rate_limit() then
    print("Aguarde " .. err.retry_after .. "ms")
  else
    -- mensagem já formatada com status e código
    print(tostring(err), err.status, err.code)
  end
else
  print(consulta.data)
end
```

Cada categoria tem o seu predicado: `err:is_insufficient_balance()`, `err:is_rate_limit()`, `err:is_network()`... e `apibrasil.Error.is(valor)` reconhece um erro da SDK.

## Modo estrito

`client:with_strict()` devolve um cliente que **levanta** a falha em vez de devolvê-la — o par natural do `pcall` de Lua, útil em scripts e pipelines:

```lua
local client = apibrasil.from_env():with_strict()

local envelope = client.whatsapp:send_text({ number = numero, text = "Olá!" })
print(envelope.response)

local ok, err = pcall(function()
  return client.account:balance()
end)

if not ok then
  print(tostring(err), err.kind)
end
```

Para um trecho isolado, sem trocar de cliente, use `apibrasil.unwrap`:

```lua
local envelope = apibrasil.unwrap(client.whatsapp:send_text(body))
```

## Retry e observabilidade

Por padrão a SDK refaz a chamada em **HTTP 429** e em **falhas de conexão** (2 tentativas extras, backoff exponencial com jitter, respeitando `Retry-After`). Timeouts e erros de negócio nunca são refeitos — evita duplicar cobranças e envios.

```lua
local client = apibrasil.new({
  retry = {
    retries = 3,
    min_delay = 500,
    max_delay = 5000,
    retry_on_statuses = { 429, 503 },
  },
  hooks = {
    request = function(info)
      print("→ " .. info.method .. " " .. info.url .. " (#" .. info.attempt .. ")")
    end,
    response = function(info)
      print("← " .. info.status .. " em " .. info.duration .. "ms")
    end,
    retry = function(info)
      print("retry em " .. info.delay .. "ms: " .. info.reason)
    end,
  },
})

-- ou desativando o retry
apibrasil.new({ retry = require("apibrasil.core.retry").none() })
```

Os hooks também podem ser um objeto com os métodos `on_request`, `on_response` e `on_retry`. Falhas dentro de um hook nunca derrubam a requisição.

Para limitar uma chamada, use `timeout` (em ms) — no cliente ou só naquela requisição:

```lua
client.whatsapp:send_text(body, { timeout = 10000 })
```

## Opções por requisição

`client:with_options` devolve um cliente que aplica as opções em todas as chamadas, mantendo base, credenciais e transporte:

```lua
client
  :with_options({
    secret_key = "SUA_SECRET_KEY",
    headers = { ["X-Correlation-Id"] = "abc-123" },
    timeout = 5000,
  })
  .devices:store({ device_name = "meu-bot" })

-- ou só nesta chamada — a tabela de opções é sempre o último argumento
client.whatsapp:send_text(body, { device_token = "outro-device" })
```

Opções aceitas: `query`, `headers`, `bearer_token`, `device_token`, `secret_key`, `timeout` e `response_type` (`"json"` ou `"binary"`).

## Transporte plugável

Lua não tem cliente HTTP na biblioteca padrão, então a SDK detecta o que existe no ambiente, nesta ordem:

1. `resty.http` — OpenResty (espera sem bloquear o worker);
2. `http.request` — [lua-http](https://github.com/daurnimator/lua-http);
3. `socket.http` + `ssl.https` — LuaSocket/LuaSec, **quando há um bundle de CAs**;
4. `curl` — a CLI da máquina, que usa o repositório de certificados do sistema.

A verificação de certificado é sempre ligada. Como o LuaSec não traz um repositório de CAs, a SDK procura o bundle nos caminhos usuais do sistema e em `SSL_CERT_FILE`; sem ele, prefere o `curl` a abrir mão da verificação.

```lua
local curl = require("apibrasil.core.transport.curl")
local luasocket = require("apibrasil.core.transport.luasocket")

apibrasil.new({ transport = curl.new({ proxy = "http://proxy:3128" }) })
apibrasil.new({ transport = luasocket.new({ ca_file = "/etc/ssl/cert.pem" }) })

-- qual transporte foi detectado
print(require("apibrasil.core.transport").default_name())
```

Um transporte é uma **função** `f(request) -> response, err` — o atalho para testes sem rede:

```lua
local transport = require("apibrasil.core.transport")

local client = apibrasil.new({
  bearer_token = "token-de-teste",
  device_token = "device-de-teste",
  transport = function(request)
    assert(request.url:find("/whatsapp/sendText$"))
    return transport.response_json(200, { error = false, response = { id = "ABC" } })
  end,
})

local envelope = client.whatsapp:send_text({ number = "5511999999999", text = "oi" })
assert(envelope.response.id == "ABC")
```

Também aceita uma **tabela** com o campo `request` — é assim que os transportes que acompanham a SDK são implementados.

## JSON: `null`, listas e objetos

Lua não distingue "tabela vazia" de "lista vazia", e `nil` não sobrevive dentro de uma tabela. O codec da SDK resolve as três coisas:

```lua
local apibrasil = require("apibrasil")

client.whatsapp:send_text({ text = apibrasil.null })   -- {"text":null}
client.ip_whitelist:set({})                            -- {"ip_whitelist":[]}
apibrasil.json.encode(apibrasil.array({}))             -- []
apibrasil.json.encode({})                              -- {}
```

Tabelas vazias sem marcação viram `{}` — o corpo das requisições da plataforma é sempre um objeto. Para usar um codec nativo (`cjson`, `dkjson`), troque com `apibrasil.json.use({ encode = ..., decode = ... })`.

## Catálogo gerado

As actions de WhatsApp/Evolution/WhatsMeow e os `tipo` das consultas são gerados do catálogo real da plataforma (`GET /documentations`):

```bash
lua scripts/codegen.lua
```

```lua
local catalog = require("apibrasil").catalog

catalog.service_actions("whatsapp")          -- todas as actions do WhatsApp
catalog.service_actions("cep")               -- { "bairros", "cep", "cidades", ... }
catalog.has_action("cep", "estados")         -- true
catalog.evolution_paths                      -- { "call/offer", "chat/deleteMessageForEveryone", ... }
catalog.consulta_servicos                    -- serviços de /consulta/{servico}/credits
catalog.consulta_tipo("acerta-essencial")    -- { service = "cpf", fields = { "cpf" } }
```

## Endpoint sem método dedicado?

Todo o gateway fica acessível pela porta de saída genérica, já com seus headers de autenticação:

```lua
client:request("post", "/consulta/cpf/credits", { cpf = "00000000000" })
client:request("get", "/reports/quick-stats")

-- corpo decodificado sem normalizar em objeto JSON (listas, texto)
local planos = client:execute("get", "/plans")

-- bytes crus (PDF de boleto, imagens)
local pdf = client:download("/inter/boleto/ID/pdf")
```

Documentação completa dos endpoints: https://doc.apibrasil.io

## Configuração avançada

```lua
local client = apibrasil.new({
  -- ou APIBRASIL_BEARER_TOKEN
  bearer_token = "...",
  -- ou APIBRASIL_DEVICE_TOKEN
  device_token = "...",
  -- usada em client.devices:store (ou APIBRASIL_SECRET_KEY)
  secret_key = "...",
  -- padrão (ou APIBRASIL_BASE_URL)
  base_url = "https://gateway.apibrasil.io/api/v2",
  timeout = 30000,
  headers = { ["X-Correlation-Id"] = "abc-123" },
  transport = require("apibrasil.core.transport.curl"),
  retry = { retries = 3 },
  hooks = { response = function(info) print(info.status) end },
  options = { timeout = 15000 },
  strict = false,
})
```

Os mesmos campos podem virar padrão da aplicação inteira:

```lua
apibrasil.configure({
  base_url = "https://gateway.apibrasil.io/api/v2",
  timeout = 60000,
})
```

A precedência é: `apibrasil.configure` < variáveis de ambiente < `apibrasil.new`. Credenciais vazias contam como ausentes: informar `""` é a forma de desligar o que veio do ambiente.

## Interface legada

`apibrasil.legacy` mantém o contrato das primeiras SDKs da plataforma — credenciais, body e action em uma única **string JSON** (`credentials` / `body` / `action`), com os erros da API devolvidos decodificados como resultado em vez de `nil, erro`.

```lua
local legacy = require("apibrasil").legacy.new()

local dados = [[{
  "action": "sendText",
  "credentials": {
    "DeviceToken": "SEU_DEVICE_TOKEN",
    "BearerToken": "SEU_BEARER_TOKEN"
  },
  "body": {"number": "5511999999999", "text": "Hello World for Lua"}
}]]

local resposta = legacy:whatsapp(dados)
```

Além de `whatsapp`, há `sms`, `cpf`, `cnpj` e `request(servico, dados)` (qualquer serviço).

Ela existe só para quem está migrando das SDKs PHP/Node com o formato antigo. Em código novo, prefira o cliente `apibrasil`, que cobre toda a plataforma com métodos dedicados, erros com categoria, retry e hooks.

## Desenvolvimento

```bash
luarocks install busted
luarocks install luacheck

busted                                        # testes (sem rede)
luacheck src spec examples scripts            # análise estática
lua scripts/check_rockspec.lua apibrasil-0.0.1-1.rockspec
```

`scripts/smoke.lua` carrega os 52 módulos e exercita o cliente **sem nenhuma
dependência** — é como o CI cobre LuaJIT e OpenResty, onde o `busted` não é
instalável (o manifesto do luarocks.org estoura o limite de 65536 constantes do
bytecode do Lua 5.1). Serve também como teste rápido depois de instalar:

```bash
lua scripts/smoke.lua
luajit scripts/smoke.lua
```

Os exemplos de `examples/` rodam direto do repositório:

```bash
export APIBRASIL_BEARER_TOKEN=...
export APIBRASIL_DEVICE_TOKEN=...

lua examples/basico.lua
lua examples/whatsapp.lua
```

## Publicando uma versão

A publicação é automática: criar a tag dispara o workflow `Release`, que
empacota o `.src.rock`, anexa ao release do GitHub e sobe para o
[luarocks.org](https://luarocks.org/modules/jhowbhz/apibrasil).

```bash
git tag v0.0.1
git push origin v0.0.1
```

Requisitos, uma vez só:

- o secret `LUAROCKS_API_KEY` no repositório (luarocks.org → *Settings* →
  *API keys*). Sem ele o release sai com o artefato anexado, mas o passo de
  publicação é pulado;
- `version` e `source.tag` do rockspec batendo com a tag — `check_rockspec.lua`
  falha o build antes de publicar caso divirjam.

Para publicar à mão, ou conferir o pacote antes da tag:

```bash
# a partir do fonte local, sem depender da tag ainda existir
luarocks make --tree=./lua_modules
luarocks pack --tree=./lua_modules apibrasil 0.0.1-1

# depois que a tag existe: gera o .src.rock e publica
luarocks pack apibrasil-0.0.1-1.rockspec
luarocks upload apibrasil-0.0.1-1.rockspec --api-key=SUA_CHAVE
```

O `luarocks pack` a partir do rockspec busca o fonte pela `source.url`, então
só funciona depois que a tag está no GitHub.

## Licença

MIT — veja [LICENSE](https://github.com/APIBrasil/apigratis-sdk-lua/blob/main/LICENSE).

## A mesma API por HTTP

Endereço base: https://gateway.apibrasil.io/api/v2
O caminho e o método de cada endpoint estão na página daquela API nesta documentação. Não deduza rota a partir do nome do serviço.

### Autenticação, em cabeçalhos HTTP
- `Authorization: Bearer SEU_TOKEN` — em toda chamada.
- `DeviceToken: SEU_DEVICE_TOKEN` — só nas APIs cobradas por plano; as cobradas por crédito não pedem. O nome exato do cabeçalho é o que a página do endpoint declara.

```bash
curl -X POST https://gateway.apibrasil.io/api/v2/dados/cpf \
  -H "Authorization: Bearer $APIBRASIL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cpf": "00000000000", "homolog": true}'
```

Com `homolog` verdadeiro no corpo, o gateway responde de uma base fixa e não consome crédito. O CPF 00000000000 é dessa base e não é de ninguém — use-o nos testes, nunca em produção.

## As outras linguagens

- [C++](https://doc.apibrasil.io/sdks/cpp.md): `git clone https://github.com/APIBrasil/apigratis-sdk-cpp`
- [Python](https://doc.apibrasil.io/sdks/python.md): `pip install api-brasil`
- [PHP](https://doc.apibrasil.io/sdks/php.md): `composer require jhowbhz/apigratis-sdk-php`
- [Java](https://doc.apibrasil.io/sdks/java.md): `mvn dependency:get -Dartifact=br.com.apibrasil:apigratis-sdk-java:0.0.1`
- [Ruby](https://doc.apibrasil.io/sdks/ruby.md): `gem install apigratis-sdk-ruby`
- [C# / .NET](https://doc.apibrasil.io/sdks/csharp.md): `dotnet add package ApiBrasil`
- [Node.js / TypeScript](https://doc.apibrasil.io/sdks/javascript.md): `npm install apigratis-sdk-nodejs`
- [Go](https://doc.apibrasil.io/sdks/go.md): `go get github.com/APIBrasil/apigratis-sdk-go`
- [Rust](https://doc.apibrasil.io/sdks/rust.md): `cargo add apibrasil`
- [Dart / Flutter](https://doc.apibrasil.io/sdks/flutter.md): `flutter pub add apigratis_sdk_flutter`
- [Elixir](https://doc.apibrasil.io/sdks/elixir.md): `mix deps.get  # com {:apibrasil, "~> 0.0.1"} no mix.exs`

## Ver também

- SDKs oficiais: [SDKs oficiais](https://doc.apibrasil.io/sdks.md)
- Índice da documentação: https://doc.apibrasil.io/llms.txt
- Versão HTML desta página: https://doc.apibrasil.io/sdks/lua
