bzapper 0.7.0 → 0.8.0
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.
- checksums.yaml +4 -4
- data/README.md +69 -4
- data/lib/bzapper/codec.rb +7 -1
- data/lib/bzapper/resources/accounts.rb +35 -8
- data/lib/bzapper/resources/advanced.rb +9 -9
- data/lib/bzapper/resources/advisories.rb +1 -1
- data/lib/bzapper/resources/base.rb +6 -0
- data/lib/bzapper/resources/campaigns.rb +9 -9
- data/lib/bzapper/resources/connect.rb +1 -1
- data/lib/bzapper/resources/contacts.rb +29 -2
- data/lib/bzapper/resources/contacts_export.rb +89 -0
- data/lib/bzapper/resources/partner.rb +3 -3
- data/lib/bzapper/resources/pools.rb +2 -2
- data/lib/bzapper/resources/scheduling.rb +1 -1
- data/lib/bzapper/resources/webhooks.rb +4 -4
- data/lib/bzapper/transport.rb +10 -3
- data/lib/bzapper/version.rb +1 -1
- data/lib/bzapper.rb +2 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7438b5b975605d626f5922c69496d7adef7b4e25d792018fee18755b79d4258
|
|
4
|
+
data.tar.gz: 21d526017685778f6c373f177c74815d2de996414e7653c82ed3cda77edd7430
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2606d09adbe38226e21ff480188aa23dc909c04c35fc5541c3508f27dad4b5e627f1bf7614ba34b25e95f7f5c02b0148ce853009df6e07912ace6cabeb19fe12
|
|
7
|
+
data.tar.gz: db997c1ca043ac5b3172cbd1fe9af114eb2cfc2723f3eff54e59c2581390f84dc4ba5bcc2fcc6cac81dfbfb0e544be0627b63cc9ee3b8a4495a077e0147f178e
|
data/README.md
CHANGED
|
@@ -10,13 +10,13 @@ Zero dependências de runtime (só biblioteca padrão: `net/http`, `json`, `open
|
|
|
10
10
|
## Instalação
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
gem install bzapper -v 0.
|
|
13
|
+
gem install bzapper -v 0.8.0
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
Ou no `Gemfile` — **fixe a versão exata** (cada release declara se muda a superfície pública):
|
|
17
17
|
|
|
18
18
|
```ruby
|
|
19
|
-
gem "bzapper", "0.
|
|
19
|
+
gem "bzapper", "0.8.0"
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## Hello world
|
|
@@ -53,6 +53,27 @@ client = Bzapper::Client.new(
|
|
|
53
53
|
Construir o cliente não faz nenhuma chamada de rede. Um cliente pode ser compartilhado entre
|
|
54
54
|
threads.
|
|
55
55
|
|
|
56
|
+
### Trocar a chave sem derrubar a integração (rotação)
|
|
57
|
+
|
|
58
|
+
`rotate_my_key` (admin) cria uma chave **nova** herdando papel, escopos, projeto e nome da
|
|
59
|
+
antiga, e mantém a antiga funcionando por um período de graça — dá tempo de fazer o deploy sem
|
|
60
|
+
janela de erro. A chave crua aparece **uma única vez**, no retorno. Depois do prazo a antiga
|
|
61
|
+
responde `401 key_expired`; `revoke_in_seconds: 0` revoga na hora (padrão 86400 s, máximo 30
|
|
62
|
+
dias). Chave de parceiro (bZapper Connect) roda pelo `PartnerClient#rotate_partner_connection_key`.
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
rotated = client.accounts.rotate_my_key(key_id, revoke_in_seconds: 3600) # 1 h de graça
|
|
66
|
+
|
|
67
|
+
rotated["api_key"] # a chave NOVA, crua — guarde agora, não volta
|
|
68
|
+
rotated["key"]["id"] # metadados da nova
|
|
69
|
+
rotated["previous_key"]["expires_at"] # quando a antiga para de funcionar (nil se revogada já)
|
|
70
|
+
rotated["old_key_expires_at"] # o mesmo instante, no topo do retorno
|
|
71
|
+
rotated["previous_key"]["rotated_to"] # id da chave que substituiu a antiga
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Uma chave já revogada ou já vencida responde `409` (`key_already_revoked` /
|
|
75
|
+
`key_already_expired`).
|
|
76
|
+
|
|
56
77
|
## Como os métodos funcionam
|
|
57
78
|
|
|
58
79
|
Os métodos ficam em **recursos**, um por área da API, e se chamam como o `operationId` da
|
|
@@ -66,13 +87,13 @@ spec OpenAPI em snake_case (`sendText` → `send_text`):
|
|
|
66
87
|
| `client.groups` | `list_groups`, `create_group`, `get_group`, `update_group`, `update_group_participants`, `group_invite_link`, `join_group`, `preview_group_invite`, `leave_group`, pedidos de entrada |
|
|
67
88
|
| `client.conversations` | `list_conversations`, `conversation_history` |
|
|
68
89
|
| `client.advanced` | editar/apagar/encaminhar mensagem, perfil, privacidade, arquivar/fixar/ler/silenciar chat, etiquetas, bloqueio, chamadas |
|
|
69
|
-
| `client.contacts` | CRM (`list_contacts`, `create_contact`, `update_contact`…), tags, grupos de contatos, opt-in/out, supressões, `contacts_check` |
|
|
90
|
+
| `client.contacts` | CRM (`list_contacts`, `create_contact`, `update_contact`…), `import_contacts` (lote), `export_contacts` (CSV), tags, grupos de contatos, opt-in/out, supressões, `contacts_check` |
|
|
70
91
|
| `client.campaigns` | `create_campaign`, `estimate_campaign`, destinatários, `dry_run_campaign`, `start/pause/resume/cancel_campaign` |
|
|
71
92
|
| `client.pools` | pools de números |
|
|
72
93
|
| `client.webhooks` | `create_webhook`, `update_webhook`, `test_webhook`, `list_webhook_deliveries`… |
|
|
73
94
|
| `client.advisories` | avisos "atualize sua integração" |
|
|
74
95
|
| `client.usage` / `client.billing` | consumo; plano, assinatura, add-ons, faturas, preços |
|
|
75
|
-
| `client.accounts` | perfil, chaves de API, marca, projetos, usuários |
|
|
96
|
+
| `client.accounts` | perfil, chaves de API (`rotate_my_key`), marca, projetos, usuários |
|
|
76
97
|
| `client.connect` | apps parceiros conectados à sua conta |
|
|
77
98
|
| `client.system` | `get_health` |
|
|
78
99
|
|
|
@@ -88,6 +109,8 @@ Convenções (iguais em todos os métodos):
|
|
|
88
109
|
vêm como `{"data" => [...], ...}` (a SDK não desembrulha, para não perder paginação e
|
|
89
110
|
metadados). Campos novos da API aparecem sem quebrar nada. `204` → `nil`.
|
|
90
111
|
* Parâmetro de caminho vazio, `"."` ou `".."` → `ArgumentError` antes de qualquer requisição.
|
|
112
|
+
* Uma exceção ao retorno: `client.contacts.export_contacts` devolve **`String`** (o CSV cru),
|
|
113
|
+
porque a rota responde `text/csv` e não JSON.
|
|
91
114
|
|
|
92
115
|
## Mensagens
|
|
93
116
|
|
|
@@ -162,6 +185,48 @@ client.contacts.contacts_check(instance_id: "…", phones: ["+5511999999999"]) #
|
|
|
162
185
|
|
|
163
186
|
O vínculo contato ↔ projeto/número é mantido **automaticamente** pela API.
|
|
164
187
|
|
|
188
|
+
### Importar em lote
|
|
189
|
+
|
|
190
|
+
Até **1000** contatos por chamada, upsert por telefone: o novo entra como
|
|
191
|
+
`pending_validation` (precisa de opt-in antes de campanha), o que já existe só recebe os campos
|
|
192
|
+
informados — valor em branco não apaga o que está lá. Linha ruim vai para `errors` e **não**
|
|
193
|
+
derruba o resto; contato suprimido/opt-out/bloqueado aparece em `skipped_rows` e nunca
|
|
194
|
+
ressuscita. Tags e grupos são criados na hora. `dry_run: true` valida tudo e não grava nada.
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
result = client.contacts.import_contacts(
|
|
198
|
+
contacts: [
|
|
199
|
+
{ phone: "+5511999999999", name: "Ana", email: "ana@example.com", tags: %w[vip] },
|
|
200
|
+
{ phone: "+5511888888888", name: "Bruno", document: "12345678900", document_type: "cpf",
|
|
201
|
+
address: { city: "São Paulo", state: "SP", country: "BR" }, groups: %w[clientes] }
|
|
202
|
+
],
|
|
203
|
+
dry_run: true # ensaio: nada é gravado
|
|
204
|
+
)
|
|
205
|
+
result["created"] # => 2
|
|
206
|
+
result["errors"].each { |row| warn "linha #{row['index']} (#{row['phone']}): #{row['reason']}" }
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Exportar em CSV
|
|
210
|
+
|
|
211
|
+
`export_contacts` aceita os **mesmos filtros** do `list_contacts` (menos `offset`; use `limit`
|
|
212
|
+
para limitar as linhas) e devolve o **texto do CSV** — uma `String` UTF-8, não JSON. Colunas:
|
|
213
|
+
`phone,name,email,status,source,tags,groups,created_at,last_activity_at`, com tags e grupos
|
|
214
|
+
unidos por `;` e instantes em RFC 3339 UTC.
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
require "csv"
|
|
218
|
+
|
|
219
|
+
csv = client.contacts.export_contacts(status: "active", tags: %w[vip], has_email: true,
|
|
220
|
+
created_after: Time.utc(2026, 1, 1), limit: 50_000)
|
|
221
|
+
|
|
222
|
+
File.write("contatos.csv", csv) # gravar como veio
|
|
223
|
+
CSV.parse(csv, headers: true) { |row| puts row["phone"] } # ou percorrer linha a linha
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Vírgulas e aspas dentro dos campos vêm escapadas pelo servidor — não monte o CSV de novo,
|
|
227
|
+
entregue o texto ao parser. Para bases muito grandes, exporte em fatias com os filtros
|
|
228
|
+
(`created_after`/`created_before`, `limit`) em vez de puxar tudo de uma vez.
|
|
229
|
+
|
|
165
230
|
## Campanhas
|
|
166
231
|
|
|
167
232
|
```ruby
|
data/lib/bzapper/codec.rb
CHANGED
|
@@ -99,9 +99,15 @@ module Bzapper
|
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
+
# Corpo cru → texto UTF-8 (bytes inválidos trocados). É o que as rotas de texto
|
|
103
|
+
# (`text/csv`, ex.: `exportContacts`) devolvem, sem passar por JSON.
|
|
104
|
+
def utf8(raw)
|
|
105
|
+
raw.to_s.dup.force_encoding(::Encoding::UTF_8).scrub
|
|
106
|
+
end
|
|
107
|
+
|
|
102
108
|
# Texto UTF-8 (bytes inválidos trocados) → `[json_ou_nil, texto, é_json?]`.
|
|
103
109
|
def decode_json(raw)
|
|
104
|
-
text = raw
|
|
110
|
+
text = utf8(raw)
|
|
105
111
|
return [nil, text, false] if text.strip.empty?
|
|
106
112
|
|
|
107
113
|
[JSON.parse(text), text, true]
|
|
@@ -34,7 +34,7 @@ module Bzapper
|
|
|
34
34
|
|
|
35
35
|
# Revoke a tenant API key. Admin only. `DELETE /keys/{id}`
|
|
36
36
|
#
|
|
37
|
-
# @param id [String]
|
|
37
|
+
# @param id [String] API key ID (UUID).
|
|
38
38
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
39
39
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
40
40
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -47,6 +47,33 @@ module Bzapper
|
|
|
47
47
|
timeout: timeout)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
# Rotate a tenant API key. Admin only. `POST /keys/{id}/rotate`
|
|
51
|
+
#
|
|
52
|
+
# Creates a NEW key inheriting the old one's role, scopes, project and name, and keeps the OLD
|
|
53
|
+
# key working for a grace period so a running integration does not break mid-deploy. The raw key
|
|
54
|
+
# is shown ONCE. After the deadline the old key answers `401 key_expired`. `revoke_in_seconds:
|
|
55
|
+
# 0` revokes it immediately (default 86400, max 30 days). Partner keys (bZapper Connect) rotate
|
|
56
|
+
# through `/partner/connections/{id}/rotate-key`.
|
|
57
|
+
#
|
|
58
|
+
# @param id [String] API key ID (UUID).
|
|
59
|
+
# @param revoke_in_seconds [Integer, nil] (corpo) Grace period for the OLD key. 0 revokes it
|
|
60
|
+
# immediately.
|
|
61
|
+
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
62
|
+
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
63
|
+
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
64
|
+
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
65
|
+
# @raise [ArgumentError] parâmetro de caminho vazio, "." ou "..".
|
|
66
|
+
def rotate_my_key(id, revoke_in_seconds: UNSET, idempotency_key: nil, timeout: nil)
|
|
67
|
+
payload = compact(
|
|
68
|
+
"revoke_in_seconds" => revoke_in_seconds
|
|
69
|
+
)
|
|
70
|
+
request("POST",
|
|
71
|
+
"/keys/#{segment(id, "id")}/rotate",
|
|
72
|
+
body: payload,
|
|
73
|
+
idempotency_key: idempotency_key,
|
|
74
|
+
timeout: timeout)
|
|
75
|
+
end
|
|
76
|
+
|
|
50
77
|
# Authenticated identity (+ profile when it's a user session). `GET /me`
|
|
51
78
|
#
|
|
52
79
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -198,7 +225,7 @@ module Bzapper
|
|
|
198
225
|
#
|
|
199
226
|
# `api_mode` is immutable and is ignored here.
|
|
200
227
|
#
|
|
201
|
-
# @param id [String]
|
|
228
|
+
# @param id [String] Project ID (UUID).
|
|
202
229
|
# @param name [String] (corpo)
|
|
203
230
|
# @param logo_url [String, nil] (corpo)
|
|
204
231
|
# @param color [String, nil] (corpo)
|
|
@@ -223,7 +250,7 @@ module Bzapper
|
|
|
223
250
|
|
|
224
251
|
# Delete a project (admin). `DELETE /projects/{id}`
|
|
225
252
|
#
|
|
226
|
-
# @param id [String]
|
|
253
|
+
# @param id [String] Project ID (UUID).
|
|
227
254
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
228
255
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
229
256
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -238,7 +265,7 @@ module Bzapper
|
|
|
238
265
|
|
|
239
266
|
# Identity of the numbers of a specific project. `GET /projects/{id}/brand`
|
|
240
267
|
#
|
|
241
|
-
# @param id [String]
|
|
268
|
+
# @param id [String] Project ID (UUID).
|
|
242
269
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
243
270
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
244
271
|
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
@@ -249,7 +276,7 @@ module Bzapper
|
|
|
249
276
|
|
|
250
277
|
# Save the identity of a specific project's numbers (admin). `PUT /projects/{id}/brand`
|
|
251
278
|
#
|
|
252
|
-
# @param id [String]
|
|
279
|
+
# @param id [String] Project ID (UUID).
|
|
253
280
|
# @param about [String, nil] (corpo) "About"/status — applied to all numbers.
|
|
254
281
|
# @param display_name [String, nil] (corpo) Business name (kit).
|
|
255
282
|
# @param logo_url [String, nil] (corpo) Logo URL (kit).
|
|
@@ -286,7 +313,7 @@ module Bzapper
|
|
|
286
313
|
# Upload the project logo (multipart, PNG/JPEG/WebP up to 5 MB) — admin. `POST
|
|
287
314
|
# /projects/{id}/logo`
|
|
288
315
|
#
|
|
289
|
-
# @param id [String]
|
|
316
|
+
# @param id [String] Project ID (UUID).
|
|
290
317
|
# @param file [String, IO, Pathname] conteúdo do arquivo (bytes), um IO ou o caminho no disco.
|
|
291
318
|
# @param filename [String, nil] nome do arquivo (padrão: o do caminho, senão "file").
|
|
292
319
|
# @param content_type [String, nil] tipo MIME (padrão: application/octet-stream).
|
|
@@ -337,7 +364,7 @@ module Bzapper
|
|
|
337
364
|
#
|
|
338
365
|
# Demoting the last administrator of the account is refused (409 last_admin).
|
|
339
366
|
#
|
|
340
|
-
# @param id [String]
|
|
367
|
+
# @param id [String] Account user ID (UUID).
|
|
341
368
|
# @param role [String] (corpo) agent = member (no billing)
|
|
342
369
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
343
370
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -359,7 +386,7 @@ module Bzapper
|
|
|
359
386
|
#
|
|
360
387
|
# You cannot remove yourself (409 self_remove) nor the last administrator (409 last_admin).
|
|
361
388
|
#
|
|
362
|
-
# @param id [String]
|
|
389
|
+
# @param id [String] Account user ID (UUID).
|
|
363
390
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
364
391
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
365
392
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -8,7 +8,7 @@ module Bzapper
|
|
|
8
8
|
class Advanced < Base
|
|
9
9
|
# Edit the text of a sent message. `PATCH /messages/{id}`
|
|
10
10
|
#
|
|
11
|
-
# @param id [String]
|
|
11
|
+
# @param id [String] bZapper message ID (UUID) — the `id` returned when the message was queued.
|
|
12
12
|
# @param text [String] (corpo)
|
|
13
13
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
14
14
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -28,7 +28,7 @@ module Bzapper
|
|
|
28
28
|
|
|
29
29
|
# Revoke a message (delete for everyone). `DELETE /messages/{id}`
|
|
30
30
|
#
|
|
31
|
-
# @param id [String]
|
|
31
|
+
# @param id [String] bZapper message ID (UUID) — the `id` returned when the message was queued.
|
|
32
32
|
# @param for_everyone [Boolean, nil] (query)
|
|
33
33
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
34
34
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -121,7 +121,7 @@ module Bzapper
|
|
|
121
121
|
|
|
122
122
|
# Archive/unarchive a chat. `POST /chats/{jid}/archive`
|
|
123
123
|
#
|
|
124
|
-
# @param jid [String]
|
|
124
|
+
# @param jid [String] Chat JID — contact (…@s.whatsapp.net / …@lid) or group (…@g.us).
|
|
125
125
|
# @param instance_id [String] (corpo)
|
|
126
126
|
# @param on [Boolean] (corpo)
|
|
127
127
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
@@ -143,7 +143,7 @@ module Bzapper
|
|
|
143
143
|
|
|
144
144
|
# Pin/unpin a chat. `POST /chats/{jid}/pin`
|
|
145
145
|
#
|
|
146
|
-
# @param jid [String]
|
|
146
|
+
# @param jid [String] Chat JID — contact (…@s.whatsapp.net / …@lid) or group (…@g.us).
|
|
147
147
|
# @param instance_id [String] (corpo)
|
|
148
148
|
# @param on [Boolean] (corpo)
|
|
149
149
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
@@ -165,7 +165,7 @@ module Bzapper
|
|
|
165
165
|
|
|
166
166
|
# Mark a chat read/unread. `POST /chats/{jid}/read`
|
|
167
167
|
#
|
|
168
|
-
# @param jid [String]
|
|
168
|
+
# @param jid [String] Chat JID — contact (…@s.whatsapp.net / …@lid) or group (…@g.us).
|
|
169
169
|
# @param instance_id [String] (corpo)
|
|
170
170
|
# @param on [Boolean] (corpo)
|
|
171
171
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
@@ -187,7 +187,7 @@ module Bzapper
|
|
|
187
187
|
|
|
188
188
|
# Mute/unmute a chat. `POST /chats/{jid}/mute`
|
|
189
189
|
#
|
|
190
|
-
# @param jid [String]
|
|
190
|
+
# @param jid [String] Chat JID — contact (…@s.whatsapp.net / …@lid) or group (…@g.us).
|
|
191
191
|
# @param instance_id [String] (corpo)
|
|
192
192
|
# @param on [Boolean] (corpo)
|
|
193
193
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
@@ -209,7 +209,7 @@ module Bzapper
|
|
|
209
209
|
|
|
210
210
|
# Apply/remove a label on a chat (experimental). `POST /chats/{jid}/labels`
|
|
211
211
|
#
|
|
212
|
-
# @param jid [String]
|
|
212
|
+
# @param jid [String] Chat JID — contact (…@s.whatsapp.net / …@lid) or group (…@g.us).
|
|
213
213
|
# @param instance_id [String] (corpo)
|
|
214
214
|
# @param label_id [String] (corpo)
|
|
215
215
|
# @param apply [Boolean, nil] (corpo) true = apply, false = remove.
|
|
@@ -289,7 +289,7 @@ module Bzapper
|
|
|
289
289
|
|
|
290
290
|
# Block a contact. `POST /contacts/{jid}/block`
|
|
291
291
|
#
|
|
292
|
-
# @param jid [String]
|
|
292
|
+
# @param jid [String] Contact JID (…@s.whatsapp.net) to block/unblock.
|
|
293
293
|
# @param instance_id [String] (corpo)
|
|
294
294
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
295
295
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -309,7 +309,7 @@ module Bzapper
|
|
|
309
309
|
|
|
310
310
|
# Unblock a contact. `POST /contacts/{jid}/unblock`
|
|
311
311
|
#
|
|
312
|
-
# @param jid [String]
|
|
312
|
+
# @param jid [String] Contact JID (…@s.whatsapp.net) to block/unblock.
|
|
313
313
|
# @param instance_id [String] (corpo)
|
|
314
314
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
315
315
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -22,7 +22,7 @@ module Bzapper
|
|
|
22
22
|
#
|
|
23
23
|
# Marks the advisory as handled; it stops being returned by `GET /advisories`.
|
|
24
24
|
#
|
|
25
|
-
# @param id [String]
|
|
25
|
+
# @param id [String] Advisory ID.
|
|
26
26
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
27
27
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
28
28
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -27,6 +27,12 @@ module Bzapper
|
|
|
27
27
|
idempotency_key: idempotency_key, timeout: timeout)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
# Rotas que respondem TEXTO (`text/csv`, ex.: `exportContacts`): devolve o corpo cru,
|
|
31
|
+
# sem JSON. Mesmos cabeçalhos, novas tentativas e erros do {#request}.
|
|
32
|
+
def request_text(method, path, query: nil, timeout: nil, accept: "text/csv")
|
|
33
|
+
@transport.request(method, path, query: query, timeout: timeout, accept: accept, as_text: true)
|
|
34
|
+
end
|
|
35
|
+
|
|
30
36
|
def segment(value, name)
|
|
31
37
|
Codec.path_segment(value, name)
|
|
32
38
|
end
|
|
@@ -107,7 +107,7 @@ module Bzapper
|
|
|
107
107
|
|
|
108
108
|
# Get a campaign with stats and variations. `GET /campaigns/{id}`
|
|
109
109
|
#
|
|
110
|
-
# @param id [String]
|
|
110
|
+
# @param id [String] Campaign ID (UUID).
|
|
111
111
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
112
112
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
113
113
|
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
@@ -121,7 +121,7 @@ module Bzapper
|
|
|
121
121
|
# Updates name, pacing, schedule and (if sent) replaces the variations. Only allowed while
|
|
122
122
|
# draft/scheduled — 409 once started.
|
|
123
123
|
#
|
|
124
|
-
# @param id [String]
|
|
124
|
+
# @param id [String] Campaign ID (UUID).
|
|
125
125
|
# @param name [String, nil] (corpo)
|
|
126
126
|
# @param pacing_profile [String, nil] (corpo)
|
|
127
127
|
# @param start_at [Time, String, nil] (corpo) Future start = scheduled campaign.
|
|
@@ -148,7 +148,7 @@ module Bzapper
|
|
|
148
148
|
|
|
149
149
|
# List recipients with per-contact delivery. `GET /campaigns/{id}/recipients`
|
|
150
150
|
#
|
|
151
|
-
# @param id [String]
|
|
151
|
+
# @param id [String] Campaign ID (UUID).
|
|
152
152
|
# @param limit [Integer, nil] (query)
|
|
153
153
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
154
154
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -163,7 +163,7 @@ module Bzapper
|
|
|
163
163
|
|
|
164
164
|
# Add (or replace) recipients. `POST /campaigns/{id}/recipients`
|
|
165
165
|
#
|
|
166
|
-
# @param id [String]
|
|
166
|
+
# @param id [String] Campaign ID (UUID).
|
|
167
167
|
# @param recipients [Array<Hash>, nil] (corpo)
|
|
168
168
|
# @param contacts [Hash, nil] (corpo) Map of phone → payload, e.g. {"+5551999198087": {"name":
|
|
169
169
|
# "Vinicius"}}.
|
|
@@ -196,7 +196,7 @@ module Bzapper
|
|
|
196
196
|
|
|
197
197
|
# Start (or schedule) a campaign. `POST /campaigns/{id}/start`
|
|
198
198
|
#
|
|
199
|
-
# @param id [String]
|
|
199
|
+
# @param id [String] Campaign ID (UUID).
|
|
200
200
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
201
201
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
202
202
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -211,7 +211,7 @@ module Bzapper
|
|
|
211
211
|
|
|
212
212
|
# Pause a campaign. `POST /campaigns/{id}/pause`
|
|
213
213
|
#
|
|
214
|
-
# @param id [String]
|
|
214
|
+
# @param id [String] Campaign ID (UUID).
|
|
215
215
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
216
216
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
217
217
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -226,7 +226,7 @@ module Bzapper
|
|
|
226
226
|
|
|
227
227
|
# Resume a campaign. `POST /campaigns/{id}/resume`
|
|
228
228
|
#
|
|
229
|
-
# @param id [String]
|
|
229
|
+
# @param id [String] Campaign ID (UUID).
|
|
230
230
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
231
231
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
232
232
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -241,7 +241,7 @@ module Bzapper
|
|
|
241
241
|
|
|
242
242
|
# Cancel a campaign. `POST /campaigns/{id}/cancel`
|
|
243
243
|
#
|
|
244
|
-
# @param id [String]
|
|
244
|
+
# @param id [String] Campaign ID (UUID).
|
|
245
245
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
246
246
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
247
247
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -256,7 +256,7 @@ module Bzapper
|
|
|
256
256
|
|
|
257
257
|
# Simulate a campaign without sending. `POST /campaigns/{id}/dry-run`
|
|
258
258
|
#
|
|
259
|
-
# @param id [String]
|
|
259
|
+
# @param id [String] Campaign ID (UUID).
|
|
260
260
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
261
261
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
262
262
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -18,7 +18,7 @@ module Bzapper
|
|
|
18
18
|
# Disconnect a partner app (admin). The partner's key stops working immediately. `DELETE
|
|
19
19
|
# /me/connections/{id}`
|
|
20
20
|
#
|
|
21
|
-
# @param id [String]
|
|
21
|
+
# @param id [String] Connected partner app (connection) ID (UUID).
|
|
22
22
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
23
23
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
24
24
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -105,6 +105,33 @@ module Bzapper
|
|
|
105
105
|
timeout: timeout)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# Import contacts in bulk. `POST /contacts/import`
|
|
109
|
+
#
|
|
110
|
+
# Upserts up to 1000 contacts by phone in one call. A new contact is created with `source:
|
|
111
|
+
# import` and `status: pending_validation` (it needs opt-in before a campaign). An existing one
|
|
112
|
+
# has only its informed fields updated — a blank value never erases what is there. A
|
|
113
|
+
# suppressed/opted-out/blocked contact is reported in `skipped_rows` and never resurrected. Tags
|
|
114
|
+
# and groups are created on demand. A bad row is reported in `errors` and does NOT fail the rest
|
|
115
|
+
# of the call. `dry_run` validates everything and writes nothing.
|
|
116
|
+
#
|
|
117
|
+
# @param contacts [Array<Hash>] (corpo)
|
|
118
|
+
# @param dry_run [Boolean, nil] (corpo) Validates and reports without writing anything.
|
|
119
|
+
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
120
|
+
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
121
|
+
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
122
|
+
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
123
|
+
def import_contacts(contacts:, dry_run: UNSET, idempotency_key: nil, timeout: nil)
|
|
124
|
+
payload = compact(
|
|
125
|
+
"contacts" => contacts,
|
|
126
|
+
"dry_run" => dry_run
|
|
127
|
+
)
|
|
128
|
+
request("POST",
|
|
129
|
+
"/contacts/import",
|
|
130
|
+
body: payload,
|
|
131
|
+
idempotency_key: idempotency_key,
|
|
132
|
+
timeout: timeout)
|
|
133
|
+
end
|
|
134
|
+
|
|
108
135
|
# Get a contact. `GET /contacts/{id}`
|
|
109
136
|
#
|
|
110
137
|
# @param id [String] Contact ID (UUID).
|
|
@@ -337,7 +364,7 @@ module Bzapper
|
|
|
337
364
|
#
|
|
338
365
|
# Removes the tag from the dictionary and unlinks it from every contact.
|
|
339
366
|
#
|
|
340
|
-
# @param id [String]
|
|
367
|
+
# @param id [String] Tag ID (UUID).
|
|
341
368
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
342
369
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
343
370
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -389,7 +416,7 @@ module Bzapper
|
|
|
389
416
|
#
|
|
390
417
|
# Removes the contact group from the dictionary and unlinks it from every contact.
|
|
391
418
|
#
|
|
392
|
-
# @param id [String] Contact ID (UUID).
|
|
419
|
+
# @param id [String] Contact group ID (UUID).
|
|
393
420
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
394
421
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
395
422
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ESCRITO À MÃO (não sai do script/generate.rb): `exportContacts` responde `text/csv`, e não
|
|
4
|
+
# JSON — está fora dos casos gerados (BRIEF §6, "CSV") e tem teste próprio
|
|
5
|
+
# (test/unit_test.rb, CsvExportTest). O resto do `client.contacts` é gerado
|
|
6
|
+
# (lib/bzapper/resources/contacts.rb).
|
|
7
|
+
|
|
8
|
+
module Bzapper
|
|
9
|
+
module Resources
|
|
10
|
+
class Contacts
|
|
11
|
+
# Export contacts as CSV. `GET /contacts/export`
|
|
12
|
+
#
|
|
13
|
+
# Devolve a base de contatos em **CSV** (`text/csv`, `Content-Disposition: attachment`) —
|
|
14
|
+
# não é JSON. Colunas:
|
|
15
|
+
# `phone,name,email,status,source,tags,groups,created_at,last_activity_at`; tags e grupos
|
|
16
|
+
# vêm unidos por `;` e os instantes em RFC 3339 UTC. Os filtros são os MESMOS do
|
|
17
|
+
# {#list_contacts} (só não há `offset`: use `limit` para limitar as linhas).
|
|
18
|
+
#
|
|
19
|
+
# O retorno é o texto do CSV, como veio do servidor (UTF-8) — passe-o a `CSV.parse` ou
|
|
20
|
+
# grave em disco. Para não carregar tudo na memória, exporte em fatias com os filtros
|
|
21
|
+
# (`created_after`/`created_before`, `limit`).
|
|
22
|
+
#
|
|
23
|
+
# @example Gravar em disco
|
|
24
|
+
# File.write("contatos.csv", client.contacts.export_contacts(status: "active"))
|
|
25
|
+
#
|
|
26
|
+
# @example Ler linha a linha
|
|
27
|
+
# require "csv"
|
|
28
|
+
# CSV.parse(client.contacts.export_contacts(tags: %w[vip]), headers: true) do |row|
|
|
29
|
+
# puts row["phone"]
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# @param search [String, nil] (query) Filter by name, phone, email or document.
|
|
33
|
+
# @param tags [Array<String>, nil] (query) Tag keys (repeat the param or a CSV list).
|
|
34
|
+
# @param tags_match [String, nil] (query) Match ANY (default) or ALL of `tags`.
|
|
35
|
+
# @param groups [Array<String>, nil] (query) Contact-group keys.
|
|
36
|
+
# @param project_id [String, nil] (query) Scope by project (alternative to the X-Project-Id
|
|
37
|
+
# header).
|
|
38
|
+
# @param instance_id [String, nil] (query) Filter by a number (instance) the contact
|
|
39
|
+
# interacted with.
|
|
40
|
+
# @param status [String, nil] (query)
|
|
41
|
+
# @param city [String, nil] (query)
|
|
42
|
+
# @param state [String, nil] (query)
|
|
43
|
+
# @param country [String, nil] (query)
|
|
44
|
+
# @param zip [String, nil] (query)
|
|
45
|
+
# @param document [String, nil] (query)
|
|
46
|
+
# @param has_email [Boolean, nil] (query) Only contacts that have (true) or lack (false) an
|
|
47
|
+
# email.
|
|
48
|
+
# @param last_activity_after [Time, String, nil] (query) last_message_at ≥ this instant
|
|
49
|
+
# (RFC3339).
|
|
50
|
+
# @param last_activity_before [Time, String, nil] (query) last_message_at ≤ this instant
|
|
51
|
+
# (RFC3339).
|
|
52
|
+
# @param created_after [Time, String, nil] (query) created_at ≥ this instant (RFC3339).
|
|
53
|
+
# @param created_before [Time, String, nil] (query) created_at ≤ this instant (RFC3339).
|
|
54
|
+
# @param sort [String, nil] (query)
|
|
55
|
+
# @param limit [Integer, nil] (query) Cap of exported rows.
|
|
56
|
+
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
57
|
+
# @return [String] o CSV cru (UTF-8), com o cabeçalho na primeira linha.
|
|
58
|
+
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
59
|
+
def export_contacts(search: nil, tags: nil, tags_match: nil, groups: nil, project_id: nil,
|
|
60
|
+
instance_id: nil, status: nil, city: nil, state: nil, country: nil,
|
|
61
|
+
zip: nil, document: nil, has_email: nil, last_activity_after: nil,
|
|
62
|
+
last_activity_before: nil, created_after: nil, created_before: nil,
|
|
63
|
+
sort: nil, limit: nil, timeout: nil)
|
|
64
|
+
query = {
|
|
65
|
+
"search" => search,
|
|
66
|
+
"tags" => tags,
|
|
67
|
+
"tags_match" => tags_match,
|
|
68
|
+
"groups" => groups,
|
|
69
|
+
"project_id" => project_id,
|
|
70
|
+
"instance_id" => instance_id,
|
|
71
|
+
"status" => status,
|
|
72
|
+
"city" => city,
|
|
73
|
+
"state" => state,
|
|
74
|
+
"country" => country,
|
|
75
|
+
"zip" => zip,
|
|
76
|
+
"document" => document,
|
|
77
|
+
"has_email" => has_email,
|
|
78
|
+
"last_activity_after" => last_activity_after,
|
|
79
|
+
"last_activity_before" => last_activity_before,
|
|
80
|
+
"created_after" => created_after,
|
|
81
|
+
"created_before" => created_before,
|
|
82
|
+
"sort" => sort,
|
|
83
|
+
"limit" => limit
|
|
84
|
+
}
|
|
85
|
+
request_text("GET", "/contacts/export", query: query, timeout: timeout)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -89,7 +89,7 @@ module Bzapper
|
|
|
89
89
|
|
|
90
90
|
# Get one connection (status, account, numbers). `GET /partner/connections/{id}`
|
|
91
91
|
#
|
|
92
|
-
# @param id [String]
|
|
92
|
+
# @param id [String] Partner connection ID (UUID).
|
|
93
93
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
94
94
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
95
95
|
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
@@ -101,7 +101,7 @@ module Bzapper
|
|
|
101
101
|
# End a connection (revokes the key; does NOT cancel the customer's plan). `DELETE
|
|
102
102
|
# /partner/connections/{id}`
|
|
103
103
|
#
|
|
104
|
-
# @param id [String]
|
|
104
|
+
# @param id [String] Partner connection ID (UUID).
|
|
105
105
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
106
106
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
107
107
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -117,7 +117,7 @@ module Bzapper
|
|
|
117
117
|
# Issue a new API key for a completed connection (the previous key stops working). `POST
|
|
118
118
|
# /partner/connections/{id}/rotate-key`
|
|
119
119
|
#
|
|
120
|
-
# @param id [String]
|
|
120
|
+
# @param id [String] Partner connection ID (UUID).
|
|
121
121
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
122
122
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
123
123
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -36,7 +36,7 @@ module Bzapper
|
|
|
36
36
|
|
|
37
37
|
# Get a pool (with members). `GET /pools/{id}`
|
|
38
38
|
#
|
|
39
|
-
# @param id [String]
|
|
39
|
+
# @param id [String] Pool ID (UUID).
|
|
40
40
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
41
41
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
42
42
|
# @raise [Bzapper::Error] resposta fora de 2xx ou falha de rede.
|
|
@@ -47,7 +47,7 @@ module Bzapper
|
|
|
47
47
|
|
|
48
48
|
# Add a number to the pool. `POST /pools/{id}/numbers`
|
|
49
49
|
#
|
|
50
|
-
# @param id [String]
|
|
50
|
+
# @param id [String] Pool ID (UUID).
|
|
51
51
|
# @param instance_id [String] (corpo)
|
|
52
52
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
53
53
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -21,7 +21,7 @@ module Bzapper
|
|
|
21
21
|
|
|
22
22
|
# Cancel a pending scheduled send. `DELETE /messages/scheduled/{id}`
|
|
23
23
|
#
|
|
24
|
-
# @param id [String]
|
|
24
|
+
# @param id [String] Scheduled message ID (UUID).
|
|
25
25
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
26
26
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
27
27
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -47,7 +47,7 @@ module Bzapper
|
|
|
47
47
|
# = true. With `secret: "regenerate"` a new secret is generated and returned ONCE in the
|
|
48
48
|
# response; any other non-empty `secret` replaces it.
|
|
49
49
|
#
|
|
50
|
-
# @param id [String]
|
|
50
|
+
# @param id [String] Webhook ID (UUID).
|
|
51
51
|
# @param url [String] (corpo)
|
|
52
52
|
# @param secret [String, nil] (corpo) Empty = keep. "regenerate" = rotate (returned once).
|
|
53
53
|
# @param event_types [Array<String>, nil] (corpo) Empty = all events.
|
|
@@ -76,7 +76,7 @@ module Bzapper
|
|
|
76
76
|
|
|
77
77
|
# Remove a webhook. `DELETE /webhooks/{id}`
|
|
78
78
|
#
|
|
79
|
-
# @param id [String]
|
|
79
|
+
# @param id [String] Webhook ID (UUID).
|
|
80
80
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
81
81
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
82
82
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
|
@@ -91,7 +91,7 @@ module Bzapper
|
|
|
91
91
|
|
|
92
92
|
# Send a signed sample event to this webhook and report the result. `POST /webhooks/{id}/test`
|
|
93
93
|
#
|
|
94
|
-
# @param id [String]
|
|
94
|
+
# @param id [String] Webhook ID (UUID).
|
|
95
95
|
# @param event_type [String, nil] (corpo) Event type of the sample (default a generic one).
|
|
96
96
|
# @param idempotency_key [String, nil] chave de idempotência (senão a SDK gera uma).
|
|
97
97
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
@@ -111,7 +111,7 @@ module Bzapper
|
|
|
111
111
|
|
|
112
112
|
# Latest deliveries of a webhook. `GET /webhooks/{id}/deliveries`
|
|
113
113
|
#
|
|
114
|
-
# @param id [String]
|
|
114
|
+
# @param id [String] Webhook ID (UUID).
|
|
115
115
|
# @param limit [Integer, nil] (query) 1–200 (default 50).
|
|
116
116
|
# @param timeout [Numeric, nil] segundos por tentativa (padrão: o do cliente).
|
|
117
117
|
# @return [Hash, Array, nil] o JSON da resposta, inteiro (nil em 204).
|
data/lib/bzapper/transport.rb
CHANGED
|
@@ -96,8 +96,12 @@ module Bzapper
|
|
|
96
96
|
# Executa a chamada e devolve o JSON decodificado da resposta (`nil` sem corpo).
|
|
97
97
|
#
|
|
98
98
|
# `body: nil` significa SEM corpo JSON; `multipart:` é um {Upload}.
|
|
99
|
+
#
|
|
100
|
+
# `accept:` troca o `Accept` (padrão `application/json`) e `as_text: true` devolve o corpo
|
|
101
|
+
# CRU em texto, sem passar por JSON — é o caminho das rotas `text/csv` (`exportContacts`).
|
|
99
102
|
# @raise [Bzapper::Error]
|
|
100
|
-
def request(method, path, query: nil, body: nil, multipart: nil, idempotency_key: nil, timeout: nil
|
|
103
|
+
def request(method, path, query: nil, body: nil, multipart: nil, idempotency_key: nil, timeout: nil,
|
|
104
|
+
accept: nil, as_text: false)
|
|
101
105
|
method = method.to_s.upcase
|
|
102
106
|
per_try = timeout.nil? ? @timeout : timeout
|
|
103
107
|
unless per_try.is_a?(Numeric) && per_try.positive?
|
|
@@ -108,7 +112,7 @@ module Bzapper
|
|
|
108
112
|
request_id = SecureRandom.uuid.delete("-")
|
|
109
113
|
headers = {
|
|
110
114
|
"Authorization" => "Bearer #{@api_key}",
|
|
111
|
-
"Accept" => "application/json",
|
|
115
|
+
"Accept" => accept || "application/json",
|
|
112
116
|
"X-Bzapper-Client" => CLIENT_ID,
|
|
113
117
|
"User-Agent" => CLIENT_ID,
|
|
114
118
|
# Mesmo id em todas as tentativas desta chamada: é como o suporte correlaciona.
|
|
@@ -146,7 +150,10 @@ module Bzapper
|
|
|
146
150
|
)
|
|
147
151
|
end
|
|
148
152
|
|
|
149
|
-
|
|
153
|
+
if status.between?(200, 299)
|
|
154
|
+
# Texto: o corpo volta como veio (o `INVALID_RESPONSE` do §4 não vale aqui).
|
|
155
|
+
return as_text ? Codec.utf8(raw) : decode(status, resp_headers, raw, request_id)
|
|
156
|
+
end
|
|
150
157
|
|
|
151
158
|
if RETRY_STATUSES.include?(status) && attempt < @max_retries
|
|
152
159
|
@sleeper.call(retry_delay(attempt, resp_headers["retry-after"]))
|
data/lib/bzapper/version.rb
CHANGED
data/lib/bzapper.rb
CHANGED
|
@@ -26,5 +26,7 @@ require_relative "bzapper/codec"
|
|
|
26
26
|
require_relative "bzapper/upload"
|
|
27
27
|
require_relative "bzapper/transport"
|
|
28
28
|
require_relative "bzapper/resources"
|
|
29
|
+
# Escrito à mão: `exportContacts` responde CSV, fora dos métodos gerados.
|
|
30
|
+
require_relative "bzapper/resources/contacts_export"
|
|
29
31
|
require_relative "bzapper/client"
|
|
30
32
|
require_relative "bzapper/webhook"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bzapper
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Berni Software
|
|
@@ -31,6 +31,7 @@ files:
|
|
|
31
31
|
- lib/bzapper/resources/campaigns.rb
|
|
32
32
|
- lib/bzapper/resources/connect.rb
|
|
33
33
|
- lib/bzapper/resources/contacts.rb
|
|
34
|
+
- lib/bzapper/resources/contacts_export.rb
|
|
34
35
|
- lib/bzapper/resources/conversations.rb
|
|
35
36
|
- lib/bzapper/resources/groups.rb
|
|
36
37
|
- lib/bzapper/resources/instances.rb
|