apigratis-sdk-ruby 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +27 -0
  3. data/LICENSE +21 -0
  4. data/README.md +330 -0
  5. data/SECURITY.md +32 -0
  6. data/lib/api_brasil/client.rb +252 -0
  7. data/lib/api_brasil/core/env.rb +34 -0
  8. data/lib/api_brasil/core/errors.rb +167 -0
  9. data/lib/api_brasil/core/http_client.rb +342 -0
  10. data/lib/api_brasil/core/retry.rb +69 -0
  11. data/lib/api_brasil/core/transport/faraday_transport.rb +76 -0
  12. data/lib/api_brasil/core/transport/net_http_transport.rb +126 -0
  13. data/lib/api_brasil/core/transport.rb +114 -0
  14. data/lib/api_brasil/generated/catalog.rb +526 -0
  15. data/lib/api_brasil/legacy/service.rb +155 -0
  16. data/lib/api_brasil/services/base_service.rb +49 -0
  17. data/lib/api_brasil/services/data/bulk_service.rb +26 -0
  18. data/lib/api_brasil/services/data/cep_service.rb +58 -0
  19. data/lib/api_brasil/services/data/chip_virtual_service.rb +40 -0
  20. data/lib/api_brasil/services/data/consulta_service.rb +97 -0
  21. data/lib/api_brasil/services/data/correios_service.rb +23 -0
  22. data/lib/api_brasil/services/data/dados_service.rb +30 -0
  23. data/lib/api_brasil/services/data/database_ip_service.rb +19 -0
  24. data/lib/api_brasil/services/data/fipe_service.rb +61 -0
  25. data/lib/api_brasil/services/data/proxies.rb +146 -0
  26. data/lib/api_brasil/services/data/ura_service.rb +26 -0
  27. data/lib/api_brasil/services/data/vehicles_service.rb +46 -0
  28. data/lib/api_brasil/services/device_proxy_service.rb +46 -0
  29. data/lib/api_brasil/services/messaging/evolution_service.rb +38 -0
  30. data/lib/api_brasil/services/messaging/sms_service.rb +40 -0
  31. data/lib/api_brasil/services/messaging/whats_meow_service.rb +30 -0
  32. data/lib/api_brasil/services/messaging/whatsapp_service.rb +120 -0
  33. data/lib/api_brasil/services/platform/account_service.rb +138 -0
  34. data/lib/api_brasil/services/platform/auth_service.rb +204 -0
  35. data/lib/api_brasil/services/platform/bearer_rate_limit_service.rb +29 -0
  36. data/lib/api_brasil/services/platform/catalog_service.rb +111 -0
  37. data/lib/api_brasil/services/platform/devices_service.rb +73 -0
  38. data/lib/api_brasil/services/platform/ip_whitelist_service.rb +73 -0
  39. data/lib/api_brasil/services/platform/payments_service.rb +124 -0
  40. data/lib/api_brasil/services/platform/reports_service.rb +96 -0
  41. data/lib/api_brasil/version.rb +6 -0
  42. data/lib/api_brasil.rb +72 -0
  43. data/lib/apigratis-sdk-ruby.rb +5 -0
  44. data/lib/apigratis.rb +11 -0
  45. metadata +149 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 703aa78add23af99d379d95a3250e92e42d534c10d5b03bceea39f5ee35fdbff
4
+ data.tar.gz: 79b15e74451aae75e95a10ef9113159d4afc4554812af5e342aa2246e562ab02
5
+ SHA512:
6
+ metadata.gz: c264b039bb789492b0d54a27e45b2e9d8bd1d6ff2198072a7d754b7ddb6b716844cbf221924a6277d9e6d52c939a2cc6a83c1f7dcf78ab54aa15275f24bc13ed
7
+ data.tar.gz: 4fb02cd917518f2fcec049cb520ab5b74dd8a6246eca12cede13c3744cf498244734ca891211f36dc5cebaf2ca3215dbf37f8f675a4e36f9334fc05e4dcbd726
data/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## 0.0.1 — 2026-07-24
4
+
5
+ Primeira versão do cliente `ApiBrasil` em Ruby, cobrindo toda a plataforma
6
+ APIBrasil — mesma arquitetura, mesmos endpoints e mesmas funções das SDKs
7
+ Node.js, PHP, Flutter, Go e Java.
8
+
9
+ ### Novidades
10
+
11
+ - **Cliente central `ApiBrasil::Client`** (`ApiBrasil.new`) com módulos por produto: `whatsapp`, `evolution`, `whatsmeow`, `sms`, `dados`, `vehicles`, `fipe`, `correios`, `cep`, `geolocation`, `geomatrix`, `recognize`, `ddd`, `holidays`, `translate`, `weather`, `loterias`, `database_ip`, `consulta` (créditos), `ura`, `chip_virtual`, `bulk`, `auth` (login/2FA), `devices`, `catalog`, `account`, `payments` (PIX/boleto/cartão), `ip_whitelist`, `bearer_rate_limit`, `reports`.
12
+ - **Transporte plugável** (`ApiBrasil::Core::Transport::Base`): `NetHttpTransport` (stdlib, sem dependências) por padrão, `FaradayTransport` usado automaticamente quando o Faraday já está carregado, e injeção de implementações próprias para proxies e mocks.
13
+ - **Retry com backoff exponencial** (padrão: HTTP 429 e falhas de conexão; nunca timeouts nem erros de negócio) com suporte a `Retry-After`.
14
+ - **Hooks de observabilidade**: `on_request`, `on_response`, `on_retry`.
15
+ - **Hierarquia de erros**: `ValidationError`, `AuthenticationError`, `InsufficientBalanceError`, `PermissionError`, `NotFoundError`, `RateLimitError`, `ServerError`, `NetworkError`, `TimeoutError` — todas herdando de `ApiBrasilError`.
16
+ - **Variáveis de ambiente**: `APIBRASIL_BEARER_TOKEN`, `APIBRASIL_DEVICE_TOKEN`, `APIBRASIL_SECRET_KEY`, `APIBRASIL_BASE_URL` lidas automaticamente.
17
+ - **Catálogo gerado** (`rake codegen`): `Catalog::WHATSAPP_ACTIONS`, `EVOLUTION_PATHS`, `WHATSMEOW_ACTIONS`, `CONSULTA_SERVICOS`, `CONSULTA_TIPOS` (210 tipos) e `SERVICE_ACTIONS`.
18
+ - **Múltiplos devices** com `with_device`, e `ApiBrasil.login` devolvendo um cliente já autenticado.
19
+ - **Testes** unitários com transporte fake (cobrindo todas as rotas e o catálogo) e de contrato opcionais (`APIBRASIL_CONTRACT=1 rake contract`).
20
+ - **Interface legada** `ApiBrasil::Legacy::Service` / `Apigratis::Service` com o contrato antigo das SDKs APIGratis (sempre `POST`, erros devolvidos no corpo). Deprecada — prefira `ApiBrasil.new`.
21
+
22
+ ### Notas
23
+
24
+ - `timeout` é em **milissegundos** (paridade com as SDKs Node/PHP). A interface legada continua em segundos.
25
+ - As respostas são `Hash` com chaves em `String`, exatamente como vêm da API.
26
+ - A configuração aceita `snake_case` (idiomático) e `camelCase` (`bearerToken`, `baseURL`, `minDelayMs`), facilitando a migração de quem já usa as outras SDKs.
27
+ - `api.sms.send` existe por paridade com as demais SDKs; `send_message` é o nome idiomático em Ruby.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jhon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,330 @@
1
+ # SDK Ruby - APIGratis by API BRASIL 🚀
2
+
3
+ SDK oficial Ruby da plataforma [APIBrasil](https://apibrasil.com.br) — WhatsApp, SMS, consultas de CPF/CNPJ, veículos, CEP, correios, pagamentos PIX/boleto e muito mais.
4
+
5
+ [![CI](https://github.com/jhowbhz/apigratis-sdk-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/jhowbhz/apigratis-sdk-ruby/actions/workflows/ci.yml)
6
+ [![license mit](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0-CC342D.svg?logo=ruby)](https://www.ruby-lang.org)
8
+ <a href="https://github.com/jhowbhz/apigratis-sdk-ruby/issues" target="_blank"><img alt="GitHub issues" src="https://img.shields.io/github/issues/jhowbhz/apigratis-sdk-ruby"></a>
9
+ <a href="https://github.com/jhowbhz/apigratis-sdk-ruby/stargazers" target="_blank"><img alt="GitHub stars" src="https://img.shields.io/github/stars/jhowbhz/apigratis-sdk-ruby"></a>
10
+
11
+ ## Canais de suporte (Comunidade)
12
+
13
+ [![WhatsApp Group](https://img.shields.io/badge/WhatsApp-Group-25D366?logo=whatsapp)](https://chat.whatsapp.com/EeAWALQb6Ga5oeTbG7DD2k)
14
+ [![Telegram Group](https://img.shields.io/badge/Telegram-Group-32AFED?logo=telegram)](https://t.me/apigratisoficial)
15
+
16
+ ## Instalação
17
+
18
+ ```bash
19
+ gem install apigratis-sdk-ruby
20
+ ```
21
+
22
+ Ou no `Gemfile`:
23
+
24
+ ```ruby
25
+ gem "apigratis-sdk-ruby"
26
+ ```
27
+
28
+ Requer **Ruby >= 3.0**. Não tem dependências de runtime — o transporte padrão usa
29
+ a stdlib (`net/http`) e o Faraday é usado automaticamente quando já está carregado
30
+ no processo. A camada de transporte é plugável.
31
+
32
+ Obtenha suas credenciais em https://apibrasil.com.br
33
+
34
+ ## Começando
35
+
36
+ ```ruby
37
+ require "api_brasil"
38
+
39
+ api = ApiBrasil.new(
40
+ bearer_token: ENV["APIBRASIL_BEARER_TOKEN"], # JWT do login
41
+ device_token: ENV["APIBRASIL_DEVICE_TOKEN"] # device dos serviços device-based
42
+ )
43
+
44
+ # WhatsApp
45
+ api.whatsapp.send_text("number" => "5511999999999", "text" => "Olá! 👋")
46
+
47
+ # Consulta CNPJ (por créditos)
48
+ empresa = api.consulta.cnpj("cnpj" => "00000000000000")
49
+ pp empresa["data"]
50
+ ```
51
+
52
+ As credenciais também podem vir só do ambiente — `ApiBrasil.new` lê automaticamente
53
+ `APIBRASIL_BEARER_TOKEN`, `APIBRASIL_DEVICE_TOKEN`, `APIBRASIL_SECRET_KEY` e `APIBRASIL_BASE_URL`.
54
+
55
+ Todas as respostas são devolvidas como **Hash** já decodificado (chaves em `String`,
56
+ exatamente como vêm da API).
57
+
58
+ Também é possível autenticar por email/senha — o token retornado fica guardado no cliente:
59
+
60
+ ```ruby
61
+ api = ApiBrasil.new
62
+ api.auth.login("email" => "voce@empresa.com.br", "password" => "******")
63
+
64
+ # contas com 2FA:
65
+ session = api.auth.login("email" => email, "password" => password)
66
+ if session["requires_2fa"]
67
+ api.auth.send_2fa("challenge" => session["challenge"], "method" => "email")
68
+ api.auth.verify_2fa("challenge" => session["challenge"], "code" => "000000")
69
+ end
70
+ ```
71
+
72
+ ## Como a plataforma funciona
73
+
74
+ A API Brasil tem duas famílias de serviços:
75
+
76
+ | Família | Autenticação | Exemplos |
77
+ | ---------------- | ---------------------------------------------- | --------------------------------------------------------------------------- |
78
+ | **Device-based** | `Authorization: Bearer` + header `DeviceToken` | WhatsApp, SMS, veículos, CEP, correios, DDD, feriados, tradução, clima, OCR |
79
+ | **Por créditos** | apenas `Authorization: Bearer` (debita saldo) | `consulta.cpf`, `consulta.cnpj`, `consulta.veiculos`, Serasa, CNH, telefone |
80
+
81
+ Para os serviços device-based, crie um device com a `SecretKey` da API desejada (painel APIBrasil) e use o `device_token` retornado:
82
+
83
+ ```ruby
84
+ device = api.devices.store(
85
+ { "device_name" => "meu-bot", "type" => "server" },
86
+ secret_key: "SUA_SECRET_KEY"
87
+ )
88
+
89
+ api.set_device_token(device["device"]["device_token"])
90
+ ```
91
+
92
+ ## Serviços disponíveis
93
+
94
+ | Módulo | Descrição |
95
+ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
96
+ | `api.whatsapp` | WhatsApp: `start`, `qrcode`, `send_text`, `send_file`, `send_audio`, `send_video`, fila (`queue`) |
97
+ | `api.evolution` | Evolution API: `request(controller, action, body)` |
98
+ | `api.whatsmeow` | WhatsMeow: `request(action, body)` |
99
+ | `api.sms` | SMS device-based (`send_message`/`send`) e por créditos (`send_with_credits`) |
100
+ | `api.dados` | Dados cadastrais device-based (`cpf`, `cnpj`) |
101
+ | `api.vehicles` | Veículos por placa (`dados`, `fipe`, `consulta_fipe`) |
102
+ | `api.fipe` | Tabela FIPE (`marcas`, `modelos`, `ano_modelo`, `valor`) |
103
+ | `api.correios` | Correios (`rastreio`, `request`) |
104
+ | `api.cep` | CEP + geolocalização (`cep`, `cidades`, `estados`, `distancia`) |
105
+ | `api.geolocation` / `api.geomatrix` | Geolocalização e matriz de distâncias |
106
+ | `api.recognize` | OCR / Google Vision (`base64`, `uri`) |
107
+ | `api.ddd` / `api.holidays` / `api.translate` / `api.weather` | DDD, feriados, tradução, clima |
108
+ | `api.loterias` | Loterias (`resultado`, `latest`) |
109
+ | `api.database_ip` | GeoIP (`ip`) |
110
+ | `api.consulta` | Consultas por créditos: `cpf`, `cnpj`, `cnh`, `cep`, `veiculos`, `telefone`, `generic(...)` |
111
+ | `api.ura` / `api.chip_virtual` | URA reversa e chip virtual |
112
+ | `api.bulk` | Execução em lote (`direct`, `queue`) |
113
+ | `api.auth` | Login, 2FA, cadastro, recuperação de senha, perfil |
114
+ | `api.devices` | CRUD de devices |
115
+ | `api.catalog` | Catálogo de APIs, planos, documentações, servidores |
116
+ | `api.account` | Saldo, faturas, notificações, tickets |
117
+ | `api.payments` | Recargas e pagamentos PIX/boleto/cartão (Santander, Inter, Mercado Pago, Sicoob) |
118
+ | `api.ip_whitelist` / `api.bearer_rate_limit` | Segurança da conta |
119
+ | `api.reports` | Relatórios e dashboard de consumo |
120
+
121
+ ### WhatsApp
122
+
123
+ ```ruby
124
+ # iniciar sessão e obter QR Code
125
+ api.whatsapp.start("webhook_wh_message" => "https://seu-webhook.com/mensagens")
126
+
127
+ qr = api.whatsapp.qrcode
128
+ puts qr["response"]["qrcode"] # data URI base64
129
+
130
+ # envios
131
+ api.whatsapp.send_text("number" => "5511999999999", "text" => "Olá!")
132
+ api.whatsapp.send_file("number" => "5511999999999", "path" => "https://exemplo.com/nota.pdf")
133
+ api.whatsapp.send_audio("number" => "5511999999999", "path" => "https://exemplo.com/audio.mp3")
134
+
135
+ # qualquer action da documentação, inclusive via fila
136
+ api.whatsapp.request("sendLocation", "number" => "5511999999999", "lat" => -23.5, "lng" => -46.6)
137
+ api.whatsapp.queue("sendText", "number" => "5511999999999", "text" => "assíncrono 🚀")
138
+ ```
139
+
140
+ ### Consultas por créditos
141
+
142
+ ```ruby
143
+ # CPF / CNPJ
144
+ cpf = api.consulta.cpf("cpf" => "00000000000")
145
+ socios = api.consulta.cnpj("cnpj" => "00000000000000", "tipo" => "lista-socios")
146
+
147
+ # veicular
148
+ veiculo = api.consulta.veiculos("placa" => "ABC1234")
149
+
150
+ # qualquer produto do catálogo
151
+ score = api.consulta.generic("cpf", "cpf" => "00000000000", "tipo" => "serasa-score-pf")
152
+
153
+ # homologação (sandbox, sem cobrança)
154
+ teste = api.consulta.cpf("cpf" => "00000000000", "homolog" => true)
155
+ ```
156
+
157
+ ### Veículos e FIPE (device-based)
158
+
159
+ ```ruby
160
+ dados = api.vehicles.dados("placa" => "ABC1234")
161
+ fipe = api.vehicles.fipe("placa" => "ABC1234")
162
+ ```
163
+
164
+ ### SMS
165
+
166
+ ```ruby
167
+ api.sms.send_message("number" => "5511999999999", "message" => "Seu código: 123456")
168
+ # ou debitando créditos da conta (sem device):
169
+ api.sms.send_with_credits("number" => "5511999999999", "message" => "Olá!")
170
+ ```
171
+
172
+ > `api.sms.send(...)` também funciona (paridade com as demais SDKs). `send_message`
173
+ > é o nome idiomático em Ruby, já que `Object#send` tem outro significado na
174
+ > linguagem — `public_send` e `__send__` continuam disponíveis normalmente.
175
+
176
+ ### Pagamentos e recargas
177
+
178
+ ```ruby
179
+ pix = api.payments.pix_generate("inter", "amount" => 100)
180
+ status = api.payments.pix_status("inter", pix["txId"])
181
+
182
+ boleto = api.payments.boleto_generate("sicoob", "amount" => 150)
183
+ pdf = api.payments.boleto_pdf("sicoob", boleto["id"]) # conteúdo binário
184
+ ```
185
+
186
+ ### Múltiplos devices
187
+
188
+ ```ruby
189
+ comercial = api.with_device("DEVICE_TOKEN_COMERCIAL")
190
+ suporte = api.with_device("DEVICE_TOKEN_SUPORTE")
191
+
192
+ comercial.whatsapp.send_text("number" => "55...", "text" => "Proposta enviada!")
193
+ suporte.whatsapp.send_text("number" => "55...", "text" => "Como posso ajudar?")
194
+ ```
195
+
196
+ ## Tratamento de erros
197
+
198
+ Cada categoria de falha tem a sua própria classe — todas herdam de
199
+ `ApiBrasil::ApiBrasilError` (que por sua vez herda de `StandardError`):
200
+
201
+ | Classe | Quando |
202
+ | ------------------------------------------ | ---------------------------------------- |
203
+ | `ApiBrasil::ValidationError` | 400/422 — payload inválido |
204
+ | `ApiBrasil::AuthenticationError` | 401 — token ausente/expirado |
205
+ | `ApiBrasil::InsufficientBalanceError` | 402 — sem saldo/créditos |
206
+ | `ApiBrasil::PermissionError` | 403 — sem permissão (ex: exige PJ) |
207
+ | `ApiBrasil::NotFoundError` | 404/410 — sem dados / rota desativada |
208
+ | `ApiBrasil::RateLimitError` | 429 — limite atingido (`retry_after_ms`) |
209
+ | `ApiBrasil::ServerError` | 5xx — erro do gateway/provedor |
210
+ | `ApiBrasil::NetworkError` / `TimeoutError` | falha antes da resposta |
211
+
212
+ ```ruby
213
+ begin
214
+ api.consulta.cpf("cpf" => "00000000000")
215
+ rescue ApiBrasil::InsufficientBalanceError
216
+ puts "Recarregue seus créditos"
217
+ rescue ApiBrasil::RateLimitError => e
218
+ puts "Aguarde #{e.retry_after_ms}ms"
219
+ end
220
+ ```
221
+
222
+ Todo erro expõe `status` (HTTP), `error_code` (código da API) e `response`
223
+ (corpo completo da resposta).
224
+
225
+ ## Retry e observabilidade
226
+
227
+ Por padrão a SDK refaz a chamada em **HTTP 429** e em **falhas de conexão** (2 tentativas
228
+ extras, backoff exponencial, respeitando `Retry-After`). Timeouts e erros de negócio
229
+ nunca são refeitos — evita duplicar cobranças e envios.
230
+
231
+ ```ruby
232
+ api = ApiBrasil.new(
233
+ retry: { retries: 3, min_delay_ms: 500, retry_on_statuses: [429, 503] }, # ou retry: false
234
+ hooks: {
235
+ on_request: ->(i) { puts "→ #{i[:method]} #{i[:url]} (##{i[:attempt]})" },
236
+ on_response: ->(i) { puts "← #{i[:status]} em #{i[:duration_ms]}ms" },
237
+ on_retry: ->(i) { puts "retry em #{i[:delay_ms]}ms: #{i[:reason]}" }
238
+ }
239
+ )
240
+ ```
241
+
242
+ ## Transporte plugável
243
+
244
+ O HTTP é feito pela stdlib (`net/http`), com uso automático do Faraday quando ele já
245
+ está carregado. A classe base `ApiBrasil::Core::Transport::Base` permite trocar a
246
+ camada inteira (proxy corporativo, outro cliente, mocks de teste):
247
+
248
+ ```ruby
249
+ # net/http com opções próprias (proxy, verificação TLS, CA...)
250
+ api = ApiBrasil.new(
251
+ transport: ApiBrasil::NetHttpTransport.new(proxy_address: "proxy.local", proxy_port: 3128)
252
+ )
253
+
254
+ # ou Faraday, com middlewares e adaptador próprios
255
+ require "faraday"
256
+ api = ApiBrasil.new(transport: ApiBrasil::FaradayTransport.new(Faraday.new { |f| f.adapter :net_http }))
257
+ ```
258
+
259
+ Ou implemente o seu:
260
+
261
+ ```ruby
262
+ class MeuTransporte < ApiBrasil::Core::Transport::Base
263
+ def request(request)
264
+ # use o cliente HTTP que quiser e devolva status, headers e corpo
265
+ ApiBrasil::Core::Transport::Response.new(200, {}, { "ok" => true })
266
+ end
267
+ end
268
+
269
+ api = ApiBrasil.new(transport: MeuTransporte.new)
270
+ ```
271
+
272
+ ## Catálogo gerado
273
+
274
+ As actions de WhatsApp/Evolution/WhatsMeow e os 210+ `tipo` de consulta estão
275
+ disponíveis em constantes geradas do catálogo real da plataforma
276
+ (`rake codegen` atualiza):
277
+
278
+ ```ruby
279
+ ApiBrasil::Catalog::WHATSAPP_ACTIONS # ["sendText", "sendFile", ...]
280
+ ApiBrasil::Catalog.service_actions("whatsmeow") # actions documentadas do serviço
281
+ ApiBrasil::Catalog.consulta_tipo("acerta-essencial")
282
+ # => { service: "cpf", fields: ["cpf"] }
283
+ ```
284
+
285
+ ## Endpoint sem método dedicado?
286
+
287
+ Todo o gateway fica acessível pela porta de saída genérica, já com seus headers de autenticação:
288
+
289
+ ```ruby
290
+ api.request("POST", "/consulta/cpf/credits", "cpf" => "00000000000")
291
+ api.request("GET", "/reports/quick-stats")
292
+ ```
293
+
294
+ Documentação completa dos endpoints: https://doc.apibrasil.io
295
+
296
+ ## Configuração avançada
297
+
298
+ ```ruby
299
+ api = ApiBrasil.new(
300
+ bearer_token: "...", # ou APIBRASIL_BEARER_TOKEN
301
+ device_token: "...", # ou APIBRASIL_DEVICE_TOKEN
302
+ secret_key: "...", # usada em devices.store (ou APIBRASIL_SECRET_KEY)
303
+ base_url: "https://gateway.apibrasil.io/api/v2", # padrão (ou APIBRASIL_BASE_URL)
304
+ timeout: 30_000, # milissegundos
305
+ headers: { "X-Custom" => "valor" }, # headers extras
306
+ retry: { retries: 2 }, # ou false
307
+ hooks: { on_retry: ->(i) { warn i[:reason] } },
308
+ transport: nil # transporte customizado
309
+ )
310
+ ```
311
+
312
+ As chaves em camelCase (`bearerToken`, `baseURL`, `minDelayMs`...) também são aceitas,
313
+ para facilitar quem já usa as SDKs Node/PHP.
314
+
315
+ Opções por requisição (último parâmetro de qualquer método): `query`, `headers`,
316
+ `bearer_token`, `device_token`, `secret_key`, `timeout`, `response_type`.
317
+
318
+ ```ruby
319
+ api.whatsapp.send_text(
320
+ { "number" => "5511999999999", "text" => "Olá!" },
321
+ device_token: "OUTRO_DEVICE", timeout: 60_000
322
+ )
323
+ ```
324
+
325
+ > **Atenção:** `timeout` é em **milissegundos** (igual às SDKs Node/PHP), diferente
326
+ > da interface legada, que usa segundos.
327
+
328
+ ## Licença
329
+
330
+ MIT — veja [LICENSE](LICENSE).
data/SECURITY.md ADDED
@@ -0,0 +1,32 @@
1
+ # Security Policy
2
+
3
+ ## Versões suportadas
4
+
5
+ | Versão | Suportada |
6
+ | ------- | ------------------ |
7
+ | 0.0.x | :white_check_mark: |
8
+
9
+ Ruby suportado: **3.0 ou superior**.
10
+
11
+ ## Reportando uma vulnerabilidade
12
+
13
+ Não abra issues públicas para falhas de segurança.
14
+
15
+ Envie os detalhes para **contato@apibrasil.com.br** com:
16
+
17
+ - descrição da falha e impacto;
18
+ - passos para reproduzir (ou prova de conceito);
19
+ - versão da SDK e do Ruby.
20
+
21
+ Retornamos o primeiro contato em até **72 horas** e mantemos você informado até a
22
+ correção. Correções são publicadas como uma nova versão do gem, com o crédito ao
23
+ reporter (quando autorizado).
24
+
25
+ ## Boas práticas ao usar a SDK
26
+
27
+ - Nunca versione `APIBRASIL_BEARER_TOKEN`, `APIBRASIL_DEVICE_TOKEN` ou
28
+ `APIBRASIL_SECRET_KEY` — use variáveis de ambiente ou um cofre de segredos.
29
+ - Restrinja os IPs que podem usar o seu Bearer Token com `api.ip_whitelist`.
30
+ - Configure o limite por minuto do token com `api.bearer_rate_limit`.
31
+ - Rotacione o token periodicamente (`api.auth.token_rotate`) e revogue os que
32
+ não estão mais em uso (`api.auth.token_revoke`).
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core/http_client"
4
+ require_relative "services/base_service"
5
+ require_relative "services/device_proxy_service"
6
+ require_relative "services/data/bulk_service"
7
+ require_relative "services/data/cep_service"
8
+ require_relative "services/data/chip_virtual_service"
9
+ require_relative "services/data/consulta_service"
10
+ require_relative "services/data/correios_service"
11
+ require_relative "services/data/dados_service"
12
+ require_relative "services/data/database_ip_service"
13
+ require_relative "services/data/fipe_service"
14
+ require_relative "services/data/proxies"
15
+ require_relative "services/data/ura_service"
16
+ require_relative "services/data/vehicles_service"
17
+ require_relative "services/messaging/evolution_service"
18
+ require_relative "services/messaging/sms_service"
19
+ require_relative "services/messaging/whats_meow_service"
20
+ require_relative "services/messaging/whatsapp_service"
21
+ require_relative "services/platform/account_service"
22
+ require_relative "services/platform/auth_service"
23
+ require_relative "services/platform/bearer_rate_limit_service"
24
+ require_relative "services/platform/catalog_service"
25
+ require_relative "services/platform/devices_service"
26
+ require_relative "services/platform/ip_whitelist_service"
27
+ require_relative "services/platform/payments_service"
28
+ require_relative "services/platform/reports_service"
29
+
30
+ module ApiBrasil
31
+ # Cliente oficial da plataforma APIBrasil.
32
+ #
33
+ # api = ApiBrasil.new(
34
+ # bearer_token: ENV["APIBRASIL_BEARER_TOKEN"],
35
+ # device_token: ENV["APIBRASIL_DEVICE_TOKEN"]
36
+ # )
37
+ #
38
+ # api.whatsapp.send_text("number" => "5511999999999", "text" => "Ola!")
39
+ # empresa = api.consulta.cnpj("cnpj" => "00000000000000")
40
+ #
41
+ # Credenciais nao informadas sao lidas das variaveis de ambiente
42
+ # `APIBRASIL_BEARER_TOKEN`, `APIBRASIL_DEVICE_TOKEN`,
43
+ # `APIBRASIL_SECRET_KEY` e `APIBRASIL_BASE_URL`.
44
+ class Client
45
+ # @return [Core::HttpClient] cliente HTTP interno (headers, retry, hooks, erros)
46
+ attr_reader :http
47
+
48
+ # @return [Services::Platform::AuthService] login, 2FA, cadastro, senha e perfil
49
+ attr_reader :auth
50
+
51
+ # @return [Services::Platform::DevicesService] gestao de devices
52
+ attr_reader :devices
53
+
54
+ # @return [Services::Messaging::WhatsAppService] WhatsApp device-based (`/whatsapp/{action}`)
55
+ attr_reader :whatsapp
56
+
57
+ # @return [Services::Messaging::EvolutionService] Evolution API (`/evolution/{controller}/{action}`)
58
+ attr_reader :evolution
59
+
60
+ # @return [Services::Messaging::WhatsMeowService] WhatsMeow (`/whatsmeow/{action}`)
61
+ attr_reader :whatsmeow
62
+
63
+ # @return [Services::Messaging::SmsService] SMS (`/sms/{action}` e `/sms/send/credits`)
64
+ attr_reader :sms
65
+
66
+ # @return [Services::Data::DadosService] dados cadastrais device-based
67
+ attr_reader :dados
68
+
69
+ # @return [Services::Data::VehiclesService] veiculos por placa
70
+ attr_reader :vehicles
71
+
72
+ # @return [Services::Data::FipeService] tabela FIPE
73
+ attr_reader :fipe
74
+
75
+ # @return [Services::Data::CorreiosService] Correios
76
+ attr_reader :correios
77
+
78
+ # @return [Services::Data::CepService] CEP + geolocalizacao
79
+ attr_reader :cep
80
+
81
+ # @return [Services::Data::GeolocationService] geolocalizacao
82
+ attr_reader :geolocation
83
+
84
+ # @return [Services::Data::GeomatrixService] matriz de distancias
85
+ attr_reader :geomatrix
86
+
87
+ # @return [Services::Data::RecognizeService] OCR / Google Vision
88
+ attr_reader :recognize
89
+
90
+ # @return [Services::Data::DddService] DDD
91
+ attr_reader :ddd
92
+
93
+ # @return [Services::Data::HolidaysService] feriados
94
+ attr_reader :holidays
95
+
96
+ # @return [Services::Data::TranslateService] traducao
97
+ attr_reader :translate
98
+
99
+ # @return [Services::Data::WeatherService] clima
100
+ attr_reader :weather
101
+
102
+ # @return [Services::Data::LoteriasService] loterias
103
+ attr_reader :loterias
104
+
105
+ # @return [Services::Data::DatabaseIpService] GeoIP (`/database/ip`)
106
+ attr_reader :database_ip
107
+
108
+ # @return [Services::Data::ConsultaService] consultas por credito
109
+ attr_reader :consulta
110
+
111
+ # @return [Services::Data::UraService] URA reversa / ligacoes
112
+ attr_reader :ura
113
+
114
+ # @return [Services::Data::ChipVirtualService] chip virtual
115
+ attr_reader :chip_virtual
116
+
117
+ # @return [Services::Data::BulkService] execucao em lote
118
+ attr_reader :bulk
119
+
120
+ # @return [Services::Platform::CatalogService] catalogo de APIs, planos, docs e servidores
121
+ attr_reader :catalog
122
+
123
+ # @return [Services::Platform::AccountService] saldo, faturas, notificacoes, tickets
124
+ attr_reader :account
125
+
126
+ # @return [Services::Platform::PaymentsService] recargas e pagamentos (PIX, boleto, cartao)
127
+ attr_reader :payments
128
+
129
+ # @return [Services::Platform::IpWhitelistService] IP whitelist da conta
130
+ attr_reader :ip_whitelist
131
+
132
+ # @return [Services::Platform::BearerRateLimitService] rate limit por Bearer Token
133
+ attr_reader :bearer_rate_limit
134
+
135
+ # @return [Services::Platform::ReportsService] relatorios e dashboard de consumo
136
+ attr_reader :reports
137
+
138
+ # @param config [Hash] veja `Core::HttpClient` para as chaves aceitas
139
+ def initialize(config = {})
140
+ @http = Core::HttpClient.new(config)
141
+
142
+ @auth = Services::Platform::AuthService.new(@http)
143
+ @devices = Services::Platform::DevicesService.new(@http)
144
+
145
+ @whatsapp = Services::Messaging::WhatsAppService.new(@http)
146
+ @evolution = Services::Messaging::EvolutionService.new(@http)
147
+ @whatsmeow = Services::Messaging::WhatsMeowService.new(@http)
148
+ @sms = Services::Messaging::SmsService.new(@http)
149
+
150
+ @dados = Services::Data::DadosService.new(@http)
151
+ @vehicles = Services::Data::VehiclesService.new(@http)
152
+ @fipe = Services::Data::FipeService.new(@http)
153
+ @correios = Services::Data::CorreiosService.new(@http)
154
+ @cep = Services::Data::CepService.new(@http)
155
+ @geolocation = Services::Data::GeolocationService.new(@http)
156
+ @geomatrix = Services::Data::GeomatrixService.new(@http)
157
+ @recognize = Services::Data::RecognizeService.new(@http)
158
+ @ddd = Services::Data::DddService.new(@http)
159
+ @holidays = Services::Data::HolidaysService.new(@http)
160
+ @translate = Services::Data::TranslateService.new(@http)
161
+ @weather = Services::Data::WeatherService.new(@http)
162
+ @loterias = Services::Data::LoteriasService.new(@http)
163
+ @database_ip = Services::Data::DatabaseIpService.new(@http)
164
+
165
+ @consulta = Services::Data::ConsultaService.new(@http)
166
+ @ura = Services::Data::UraService.new(@http)
167
+ @chip_virtual = Services::Data::ChipVirtualService.new(@http)
168
+ @bulk = Services::Data::BulkService.new(@http)
169
+
170
+ @catalog = Services::Platform::CatalogService.new(@http)
171
+ @account = Services::Platform::AccountService.new(@http)
172
+ @payments = Services::Platform::PaymentsService.new(@http)
173
+ @ip_whitelist = Services::Platform::IpWhitelistService.new(@http)
174
+ @bearer_rate_limit = Services::Platform::BearerRateLimitService.new(@http)
175
+ @reports = Services::Platform::ReportsService.new(@http)
176
+ end
177
+
178
+ # Faz login e retorna um cliente ja autenticado.
179
+ # Levanta `ApiBrasilError` se a conta exigir 2FA - nesse caso crie o
180
+ # cliente manualmente e use `auth.login` + `auth.verify_2fa`.
181
+ #
182
+ # @param credentials [Hash] `email` e `password`
183
+ # @param config [Hash]
184
+ # @return [Hash] `{ client: Client, session: Object }`
185
+ def self.login(credentials, config = {})
186
+ client = new(config)
187
+ session = client.auth.login(credentials)
188
+
189
+ if session.is_a?(Hash) && session["requires_2fa"]
190
+ raise Core::Errors::ApiBrasilError.new(
191
+ "Esta conta exige autenticacao em dois fatores. Use auth.login + auth.verify_2fa.",
192
+ response: session
193
+ )
194
+ end
195
+
196
+ { client: client, session: session }
197
+ end
198
+
199
+ # Define/atualiza o Bearer Token do cliente.
200
+ #
201
+ # @return [self]
202
+ def set_bearer_token(token)
203
+ http.bearer_token = token
204
+ self
205
+ end
206
+
207
+ # Define/atualiza o DeviceToken do cliente.
208
+ #
209
+ # @return [self]
210
+ def set_device_token(token)
211
+ http.device_token = token
212
+ self
213
+ end
214
+
215
+ # @return [String, nil]
216
+ def bearer_token
217
+ http.bearer_token
218
+ end
219
+
220
+ def bearer_token=(token)
221
+ http.bearer_token = token
222
+ end
223
+
224
+ # @return [String, nil]
225
+ def device_token
226
+ http.device_token
227
+ end
228
+
229
+ def device_token=(token)
230
+ http.device_token = token
231
+ end
232
+
233
+ # Retorna um novo cliente com as mesmas credenciais, mas apontando
234
+ # para outro device - util para gerenciar varios numeros/instancias.
235
+ #
236
+ # @return [Client]
237
+ def with_device(device_token)
238
+ self.class.new(http.to_config.merge(device_token: device_token))
239
+ end
240
+
241
+ # Porta de saida generica: chama qualquer endpoint do gateway com os
242
+ # headers de autenticacao ja configurados. Use para rotas que ainda
243
+ # nao tem metodo dedicado na SDK.
244
+ #
245
+ # api.request("POST", "/consulta/cpf/credits", "cpf" => "...")
246
+ #
247
+ # @return [Object]
248
+ def request(method, path, body = nil, options = {})
249
+ http.request(method, path, body, options)
250
+ end
251
+ end
252
+ end