SDK oficial Ruby da plataforma APIBrasil — WhatsApp, SMS, consultas de CPF/CNPJ, veículos, CEP, correios, pagamentos PIX/boleto e muito mais.
gem install apigratis-sdk-rubyOu no Gemfile:
gem "apigratis-sdk-ruby"Requer Ruby >= 3.0. Não tem dependências de runtime — o transporte padrão usa
a stdlib (net/http) e o Faraday é usado automaticamente quando já está carregado
no processo. A camada de transporte é plugável.
Obtenha suas credenciais em https://apibrasil.com.br
require "api_brasil"
api = ApiBrasil.new(
bearer_token: ENV["APIBRASIL_BEARER_TOKEN"], # JWT do login
device_token: ENV["APIBRASIL_DEVICE_TOKEN"] # device dos serviços device-based
)
# WhatsApp
api.whatsapp.send_text("number" => "5511999999999", "text" => "Olá! 👋")
# Consulta CNPJ (por créditos)
empresa = api.consulta.cnpj("cnpj" => "00000000000000")
pp empresa["data"]As credenciais também podem vir só do ambiente — ApiBrasil.new lê automaticamente
APIBRASIL_BEARER_TOKEN, APIBRASIL_DEVICE_TOKEN, APIBRASIL_SECRET_KEY e APIBRASIL_BASE_URL.
Todas as respostas são devolvidas como Hash já decodificado (chaves em String,
exatamente como vêm da API).
Também é possível autenticar por email/senha — o token retornado fica guardado no cliente:
api = ApiBrasil.new
api.auth.login("email" => "voce@empresa.com.br", "password" => "******")
# contas com 2FA:
session = api.auth.login("email" => email, "password" => password)
if session["requires_2fa"]
api.auth.send_2fa("challenge" => session["challenge"], "method" => "email")
api.auth.verify_2fa("challenge" => session["challenge"], "code" => "000000")
endA 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) |
consulta.cpf, consulta.cnpj, consulta.veiculos, Serasa, CNH, telefone |
Para os serviços device-based, crie um device com a SecretKey da API desejada (painel APIBrasil) e use o device_token retornado:
device = api.devices.store(
{ "device_name" => "meu-bot", "type" => "server" },
secret_key: "SUA_SECRET_KEY"
)
api.set_device_token(device["device"]["device_token"])| Módulo | Descrição |
|---|---|
api.whatsapp |
WhatsApp: start, qrcode, send_text, send_file, send_audio, send_video, fila (queue) |
api.evolution |
Evolution API: request(controller, action, body) |
api.whatsmeow |
WhatsMeow: request(action, body) |
api.sms |
SMS device-based (send_message/send) e por créditos (send_with_credits) |
api.dados |
Dados cadastrais device-based (cpf, cnpj) |
api.vehicles |
Veículos por placa (dados, fipe, consulta_fipe) |
api.fipe |
Tabela FIPE (marcas, modelos, ano_modelo, valor) |
api.correios |
Correios (rastreio, request) |
api.cep |
CEP + geolocalização (cep, cidades, estados, distancia) |
api.geolocation / api.geomatrix |
Geolocalização e matriz de distâncias |
api.recognize |
OCR / Google Vision (base64, uri) |
api.ddd / api.holidays / api.translate / api.weather |
DDD, feriados, tradução, clima |
api.loterias |
Loterias (resultado, latest) |
api.database_ip |
GeoIP (ip) |
api.consulta |
Consultas por créditos: cpf, cnpj, cnh, cep, veiculos, telefone, generic(...) |
api.ura / api.chip_virtual |
URA reversa e chip virtual |
api.bulk |
Execução em lote (direct, queue) |
api.auth |
Login, 2FA, cadastro, recuperação de senha, perfil |
api.devices |
CRUD de devices |
api.catalog |
Catálogo de APIs, planos, documentações, servidores |
api.account |
Saldo, faturas, notificações, tickets |
api.payments |
Recargas e pagamentos PIX/boleto/cartão (Santander, Inter, Mercado Pago, Sicoob) |
api.ip_whitelist / api.bearer_rate_limit |
Segurança da conta |
api.reports |
Relatórios e dashboard de consumo |
# iniciar sessão e obter QR Code
api.whatsapp.start("webhook_wh_message" => "https://seu-webhook.com/mensagens")
qr = api.whatsapp.qrcode
puts qr["response"]["qrcode"] # data URI base64
# envios
api.whatsapp.send_text("number" => "5511999999999", "text" => "Olá!")
api.whatsapp.send_file("number" => "5511999999999", "path" => "https://exemplo.com/nota.pdf")
api.whatsapp.send_audio("number" => "5511999999999", "path" => "https://exemplo.com/audio.mp3")
# qualquer action da documentação, inclusive via fila
api.whatsapp.request("sendLocation", "number" => "5511999999999", "lat" => -23.5, "lng" => -46.6)
api.whatsapp.queue("sendText", "number" => "5511999999999", "text" => "assíncrono 🚀")# CPF / CNPJ
cpf = api.consulta.cpf("cpf" => "00000000000")
socios = api.consulta.cnpj("cnpj" => "00000000000000", "tipo" => "lista-socios")
# veicular
veiculo = api.consulta.veiculos("placa" => "ABC1234")
# qualquer produto do catálogo
score = api.consulta.generic("cpf", "cpf" => "00000000000", "tipo" => "serasa-score-pf")
# homologação (sandbox, sem cobrança)
teste = api.consulta.cpf("cpf" => "00000000000", "homolog" => true)dados = api.vehicles.dados("placa" => "ABC1234")
fipe = api.vehicles.fipe("placa" => "ABC1234")api.sms.send_message("number" => "5511999999999", "message" => "Seu código: 123456")
# ou debitando créditos da conta (sem device):
api.sms.send_with_credits("number" => "5511999999999", "message" => "Olá!")
api.sms.send(...)também funciona (paridade com as demais SDKs).send_messageé o nome idiomático em Ruby, já queObject#sendtem outro significado na linguagem —public_sende__send__continuam disponíveis normalmente.
pix = api.payments.pix_generate("inter", "amount" => 100)
status = api.payments.pix_status("inter", pix["txId"])
boleto = api.payments.boleto_generate("sicoob", "amount" => 150)
pdf = api.payments.boleto_pdf("sicoob", boleto["id"]) # conteúdo bináriocomercial = api.with_device("DEVICE_TOKEN_COMERCIAL")
suporte = api.with_device("DEVICE_TOKEN_SUPORTE")
comercial.whatsapp.send_text("number" => "55...", "text" => "Proposta enviada!")
suporte.whatsapp.send_text("number" => "55...", "text" => "Como posso ajudar?")Cada categoria de falha tem a sua própria classe — todas herdam de
ApiBrasil::ApiBrasilError (que por sua vez herda de StandardError):
| Classe | Quando |
|---|---|
ApiBrasil::ValidationError |
400/422 — payload inválido |
ApiBrasil::AuthenticationError |
401 — token ausente/expirado |
ApiBrasil::InsufficientBalanceError |
402 — sem saldo/créditos |
ApiBrasil::PermissionError |
403 — sem permissão (ex: exige PJ) |
ApiBrasil::NotFoundError |
404/410 — sem dados / rota desativada |
ApiBrasil::RateLimitError |
429 — limite atingido (retry_after_ms) |
ApiBrasil::ServerError |
5xx — erro do gateway/provedor |
ApiBrasil::NetworkError / TimeoutError |
falha antes da resposta |
begin
api.consulta.cpf("cpf" => "00000000000")
rescue ApiBrasil::InsufficientBalanceError
puts "Recarregue seus créditos"
rescue ApiBrasil::RateLimitError => e
puts "Aguarde #{e.retry_after_ms}ms"
endTodo erro expõe status (HTTP), error_code (código da API) e response
(corpo completo da resposta).
Por padrão a SDK refaz a chamada em HTTP 429 e em falhas de conexão (2 tentativas
extras, backoff exponencial, respeitando Retry-After). Timeouts e erros de negócio
nunca são refeitos — evita duplicar cobranças e envios.
api = ApiBrasil.new(
retry: { retries: 3, min_delay_ms: 500, retry_on_statuses: [429, 503] }, # ou retry: false
hooks: {
on_request: ->(i) { puts "→ #{i[:method]} #{i[:url]} (##{i[:attempt]})" },
on_response: ->(i) { puts "← #{i[:status]} em #{i[:duration_ms]}ms" },
on_retry: ->(i) { puts "retry em #{i[:delay_ms]}ms: #{i[:reason]}" }
}
)O HTTP é feito pela stdlib (net/http), com uso automático do Faraday quando ele já
está carregado. A classe base ApiBrasil::Core::Transport::Base permite trocar a
camada inteira (proxy corporativo, outro cliente, mocks de teste):
# net/http com opções próprias (proxy, verificação TLS, CA...)
api = ApiBrasil.new(
transport: ApiBrasil::NetHttpTransport.new(proxy_address: "proxy.local", proxy_port: 3128)
)
# ou Faraday, com middlewares e adaptador próprios
require "faraday"
api = ApiBrasil.new(transport: ApiBrasil::FaradayTransport.new(Faraday.new { |f| f.adapter :net_http }))Ou implemente o seu:
class MeuTransporte < ApiBrasil::Core::Transport::Base
def request(request)
# use o cliente HTTP que quiser e devolva status, headers e corpo
ApiBrasil::Core::Transport::Response.new(200, {}, { "ok" => true })
end
end
api = ApiBrasil.new(transport: MeuTransporte.new)As actions de WhatsApp/Evolution/WhatsMeow e os 210+ tipo de consulta estão
disponíveis em constantes geradas do catálogo real da plataforma
(rake codegen atualiza):
ApiBrasil::Catalog::WHATSAPP_ACTIONS # ["sendText", "sendFile", ...]
ApiBrasil::Catalog.service_actions("whatsmeow") # actions documentadas do serviço
ApiBrasil::Catalog.consulta_tipo("acerta-essencial")
# => { service: "cpf", fields: ["cpf"] }Todo o gateway fica acessível pela porta de saída genérica, já com seus headers de autenticação:
api.request("POST", "/consulta/cpf/credits", "cpf" => "00000000000")
api.request("GET", "/reports/quick-stats")Documentação completa dos endpoints: https://doc.apibrasil.io
api = ApiBrasil.new(
bearer_token: "...", # ou APIBRASIL_BEARER_TOKEN
device_token: "...", # ou APIBRASIL_DEVICE_TOKEN
secret_key: "...", # usada em devices.store (ou APIBRASIL_SECRET_KEY)
base_url: "https://gateway.apibrasil.io/api/v2", # padrão (ou APIBRASIL_BASE_URL)
timeout: 30_000, # milissegundos
headers: { "X-Custom" => "valor" }, # headers extras
retry: { retries: 2 }, # ou false
hooks: { on_retry: ->(i) { warn i[:reason] } },
transport: nil # transporte customizado
)As chaves em camelCase (bearerToken, baseURL, minDelayMs...) também são aceitas,
para facilitar quem já usa as SDKs Node/PHP.
Opções por requisição (último parâmetro de qualquer método): query, headers,
bearer_token, device_token, secret_key, timeout, response_type.
api.whatsapp.send_text(
{ "number" => "5511999999999", "text" => "Olá!" },
device_token: "OUTRO_DEVICE", timeout: 60_000
)Atenção:
timeouté em milissegundos (igual às SDKs Node/PHP), diferente da interface legada, que usa segundos.
MIT — veja LICENSE.