@natyapp/meta 1.6.6 → 1.7.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.
Files changed (95) hide show
  1. package/.github/copilot-instructions.md +1540 -0
  2. package/README.md +513 -40
  3. package/dist/elements/index.d.ts +1 -0
  4. package/dist/elements/index.js +1 -0
  5. package/dist/elements/mediaTemplate.d.ts +45 -0
  6. package/dist/elements/mediaTemplate.js +47 -0
  7. package/dist/elements/textTemplate.d.ts +12 -1
  8. package/dist/elements/textTemplate.js +13 -6
  9. package/dist/index.d.ts +7 -2
  10. package/dist/index.js +11 -2
  11. package/dist/interfaces/IConnection.d.ts +2 -2
  12. package/dist/interfaces/ILog.d.ts +2 -2
  13. package/dist/interfaces/ILogger.d.ts +62 -0
  14. package/dist/interfaces/ILogger.js +2 -0
  15. package/dist/interfaces/ISdk.d.ts +4 -2
  16. package/dist/interfaces/IWebhook.d.ts +2 -2
  17. package/dist/interfaces/index.d.ts +1 -0
  18. package/dist/interfaces/index.js +1 -0
  19. package/dist/queue/messageQueue.d.ts +1 -1
  20. package/dist/queue/messageQueue.js +45 -0
  21. package/dist/routes/webhooks/methods/connection.js +78 -11
  22. package/dist/routes/webhooks/methods/messages.js +18 -3
  23. package/dist/services/axiosInstances.d.ts +14 -5
  24. package/dist/services/axiosInstances.js +111 -23
  25. package/dist/services/middlewares/validations.d.ts +2 -2
  26. package/dist/services/middlewares/validations.js +1 -2
  27. package/dist/services/mutations/connection.js +1 -1
  28. package/dist/services/mutations/logs.js +1 -1
  29. package/dist/services/mutations/messages.js +1 -1
  30. package/dist/services/mutations/validation.d.ts +1 -1
  31. package/dist/services/mutations/validation.js +1 -1
  32. package/dist/services/mutations/webhooks.js +1 -1
  33. package/dist/types/logs.d.ts +1 -1
  34. package/dist/types/requestTypes.d.ts +2 -0
  35. package/dist/useCases/connection/index.d.ts +9 -9
  36. package/dist/useCases/connection/index.js +156 -7
  37. package/dist/useCases/events/NatyEvents.d.ts +4 -2
  38. package/dist/useCases/events/NatyEvents.js +13 -1
  39. package/dist/useCases/log/index.d.ts +5 -5
  40. package/dist/useCases/log/index.js +65 -3
  41. package/dist/useCases/message/whatsappResponse.d.ts +48 -22
  42. package/dist/useCases/message/whatsappResponse.js +672 -105
  43. package/dist/useCases/messages/index.d.ts +5 -5
  44. package/dist/useCases/messages/index.js +66 -3
  45. package/dist/useCases/sdk/index.d.ts +8 -4
  46. package/dist/useCases/sdk/index.js +38 -6
  47. package/dist/useCases/webhook/index.d.ts +9 -9
  48. package/dist/useCases/webhook/index.js +154 -7
  49. package/dist/utils/consoleLogger.d.ts +20 -0
  50. package/dist/utils/consoleLogger.js +51 -0
  51. package/dist/utils/index.d.ts +6 -0
  52. package/dist/utils/index.js +6 -0
  53. package/dist/utils/loggerContext.d.ts +57 -0
  54. package/dist/utils/loggerContext.js +90 -0
  55. package/dist/utils/methodContext.d.ts +34 -0
  56. package/dist/utils/methodContext.js +48 -0
  57. package/dist/utils/parseError.d.ts +12 -0
  58. package/dist/utils/parseError.js +27 -3
  59. package/dist/utils/pinoAdapter.d.ts +30 -0
  60. package/dist/utils/pinoAdapter.js +68 -0
  61. package/dist/utils/sanitize.d.ts +42 -0
  62. package/dist/utils/sanitize.js +120 -0
  63. package/dist/utils/tryCatch.d.ts +10 -1
  64. package/dist/utils/tryCatch.js +40 -5
  65. package/docs/01-visao-geral.md +355 -0
  66. package/docs/02-contexto-negocio.md +596 -0
  67. package/docs/03-arquitetura.md +925 -0
  68. package/docs/04-fluxos-funcionais.md +887 -0
  69. package/docs/05-integracoes.md +960 -0
  70. package/docs/06-entidades.md +849 -0
  71. package/docs/07-guia-pratico.md +1133 -0
  72. package/docs/08-troubleshooting.md +816 -0
  73. package/docs/README.md +125 -0
  74. package/examples/logger-example.ts +279 -0
  75. package/package.json +2 -2
  76. /package/dist/{Entities → entities}/Logs.d.ts +0 -0
  77. /package/dist/{Entities → entities}/Logs.js +0 -0
  78. /package/dist/{Entities → entities}/connection.d.ts +0 -0
  79. /package/dist/{Entities → entities}/connection.js +0 -0
  80. /package/dist/{Entities → entities}/errorLogs.d.ts +0 -0
  81. /package/dist/{Entities → entities}/errorLogs.js +0 -0
  82. /package/dist/{Entities → entities}/index.d.ts +0 -0
  83. /package/dist/{Entities → entities}/index.js +0 -0
  84. /package/dist/{Entities → entities}/messages.d.ts +0 -0
  85. /package/dist/{Entities → entities}/messages.js +0 -0
  86. /package/dist/{Entities → entities}/webhooks.d.ts +0 -0
  87. /package/dist/{Entities → entities}/webhooks.js +0 -0
  88. /package/dist/{Entities → entities}/whatsappMessage.d.ts +0 -0
  89. /package/dist/{Entities → entities}/whatsappMessage.js +0 -0
  90. /package/dist/{Errors → errors}/Either.d.ts +0 -0
  91. /package/dist/{Errors → errors}/Either.js +0 -0
  92. /package/dist/{Errors → errors}/ErrorHandling.d.ts +0 -0
  93. /package/dist/{Errors → errors}/ErrorHandling.js +0 -0
  94. /package/dist/{Errors → errors}/index.d.ts +0 -0
  95. /package/dist/{Errors → errors}/index.js +0 -0
@@ -0,0 +1,960 @@
1
+ # 05 - Integrações com Sistemas Externos
2
+
3
+ [⬅️ Voltar ao Índice](README.md)
4
+
5
+ ---
6
+
7
+ ## 📋 Sumário
8
+ - [Visão Geral das Integrações](#-visão-geral-das-integrações)
9
+ - [Meta WhatsApp Business API (Graph API)](#-meta-whatsapp-business-api-graph-api)
10
+ - [Naty Meta API (Backend Proprietário)](#-naty-meta-api-backend-proprietário)
11
+ - [Express.js (Integração Opcional)](#-expressjs-integração-opcional)
12
+ - [Diagramas de Integração](#-diagramas-de-integração)
13
+ - [Rate Limits e Throttling](#-rate-limits-e-throttling)
14
+ - [Segurança e Autenticação](#-segurança-e-autenticação)
15
+
16
+ ---
17
+
18
+ ## 🌐 Visão Geral das Integrações
19
+
20
+ O SDK Naty Meta integra-se com três sistemas principais:
21
+
22
+ ```mermaid
23
+ graph TB
24
+ subgraph "SDK Naty Meta"
25
+ SDK[NatyMeta Core]
26
+ end
27
+
28
+ subgraph "API Proprietária"
29
+ NATY[Naty Meta API<br/>Gestão de Conexões]
30
+ end
31
+
32
+ subgraph "API Meta/Facebook"
33
+ GRAPH[Meta Graph API v18.0<br/>WhatsApp Business]
34
+ OAUTH[Meta OAuth API<br/>Token Management]
35
+ end
36
+
37
+ subgraph "Framework Web (Opcional)"
38
+ EXPRESS[Express.js<br/>Webhook Server]
39
+ end
40
+
41
+ SDK -->|CRUD Conexões<br/>CRUD Webhooks<br/>CRUD Logs| NATY
42
+ SDK -->|Envio Mensagens<br/>Upload/Download Mídia| GRAPH
43
+ SDK -->|Refresh Tokens| OAUTH
44
+ SDK -->|Registra Rotas<br/>Webhook Routes| EXPRESS
45
+
46
+ EXPRESS -->|Recebe Webhooks| GRAPH
47
+
48
+ style SDK fill:#4CAF50,color:#fff
49
+ style NATY fill:#2196F3,color:#fff
50
+ style GRAPH fill:#FF9800,color:#fff
51
+ style OAUTH fill:#FFC107
52
+ style EXPRESS fill:#9C27B0,color:#fff
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 📱 Meta WhatsApp Business API (Graph API)
58
+
59
+ ### Informações Gerais
60
+
61
+ | Propriedade | Valor |
62
+ |-------------|-------|
63
+ | **Base URL** | `https://graph.facebook.com/v18.0` |
64
+ | **Protocolo** | HTTPS (REST API) |
65
+ | **Autenticação** | Bearer Token (OAuth 2.0) |
66
+ | **Formato** | JSON |
67
+ | **Documentação Oficial** | [developers.facebook.com/docs/whatsapp](https://developers.facebook.com/docs/whatsapp/cloud-api) |
68
+
69
+ ### Endpoints Utilizados
70
+
71
+ #### 1. Envio de Mensagens
72
+
73
+ ```
74
+ POST /{phone-number-id}/messages
75
+ ```
76
+
77
+ **Headers:**
78
+ ```http
79
+ Authorization: Bearer {access_token}
80
+ Content-Type: application/json
81
+ ```
82
+
83
+ **Body (Texto simples):**
84
+ ```json
85
+ {
86
+ "messaging_product": "whatsapp",
87
+ "recipient_type": "individual",
88
+ "to": "5511999999999",
89
+ "type": "text",
90
+ "text": {
91
+ "preview_url": false,
92
+ "body": "Olá! Esta é uma mensagem de teste."
93
+ }
94
+ }
95
+ ```
96
+
97
+ **Body (Botões):**
98
+ ```json
99
+ {
100
+ "messaging_product": "whatsapp",
101
+ "to": "5511999999999",
102
+ "type": "interactive",
103
+ "interactive": {
104
+ "type": "button",
105
+ "body": {
106
+ "text": "Escolha uma opção:"
107
+ },
108
+ "action": {
109
+ "buttons": [
110
+ {
111
+ "type": "reply",
112
+ "reply": {
113
+ "id": "opt_1",
114
+ "title": "Opção 1"
115
+ }
116
+ },
117
+ {
118
+ "type": "reply",
119
+ "reply": {
120
+ "id": "opt_2",
121
+ "title": "Opção 2"
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ **Response (Sucesso):**
131
+ ```json
132
+ {
133
+ "messaging_product": "whatsapp",
134
+ "contacts": [
135
+ {
136
+ "input": "5511999999999",
137
+ "wa_id": "5511999999999"
138
+ }
139
+ ],
140
+ "messages": [
141
+ {
142
+ "id": "wamid.HBgNNTUxMTk4ODg4ODg4OBUCABIYIDNBNjdGMzQ5QzE5MEFCMTY1MjU0"
143
+ }
144
+ ]
145
+ }
146
+ ```
147
+
148
+ **Códigos de Erro Comuns:**
149
+
150
+ | Código | Erro | Significado |
151
+ |--------|------|-------------|
152
+ | 400 | `invalid_parameter` | Parâmetro inválido no payload |
153
+ | 401 | `invalid_token` | Access token inválido ou expirado |
154
+ | 403 | `rate_limit_issues` | Limite de mensagens atingido |
155
+ | 404 | `resource_not_found` | Phone number ID não encontrado |
156
+ | 429 | `too_many_requests` | Rate limit excedido |
157
+ | 500 | `internal_error` | Erro interno da Meta |
158
+
159
+ ---
160
+
161
+ #### 2. Upload de Mídia
162
+
163
+ ```
164
+ POST /{phone-number-id}/media
165
+ ```
166
+
167
+ **Headers:**
168
+ ```http
169
+ Authorization: Bearer {access_token}
170
+ Content-Type: multipart/form-data
171
+ ```
172
+
173
+ **Body:**
174
+ ```
175
+ --boundary
176
+ Content-Disposition: form-data; name="file"; filename="image.jpg"
177
+ Content-Type: image/jpeg
178
+
179
+ [binary data]
180
+ --boundary
181
+ Content-Disposition: form-data; name="messaging_product"
182
+
183
+ whatsapp
184
+ --boundary--
185
+ ```
186
+
187
+ **Response:**
188
+ ```json
189
+ {
190
+ "id": "1234567890"
191
+ }
192
+ ```
193
+
194
+ ---
195
+
196
+ #### 3. Download de Mídia (Obter URL)
197
+
198
+ ```
199
+ GET /{media-id}
200
+ ```
201
+
202
+ **Headers:**
203
+ ```http
204
+ Authorization: Bearer {access_token}
205
+ ```
206
+
207
+ **Response:**
208
+ ```json
209
+ {
210
+ "url": "https://mmg.whatsapp.net/d/f/AqFmkQ...",
211
+ "mime_type": "image/jpeg",
212
+ "sha256": "e7b6c8f9a2d3...",
213
+ "file_size": 52431,
214
+ "id": "1234567890"
215
+ }
216
+ ```
217
+
218
+ ⚠️ **Nota:** A URL tem validade de ~5 minutos.
219
+
220
+ ---
221
+
222
+ #### 4. Download de Mídia (Binário)
223
+
224
+ ```
225
+ GET {media-url}
226
+ ```
227
+
228
+ **Headers:**
229
+ ```http
230
+ Authorization: Bearer {access_token}
231
+ ```
232
+
233
+ **Response:** Binary data (arquivo)
234
+
235
+ ---
236
+
237
+ #### 5. Informações da Conta
238
+
239
+ ```
240
+ GET /{phone-number-id}
241
+ ```
242
+
243
+ **Headers:**
244
+ ```http
245
+ Authorization: Bearer {access_token}
246
+ ```
247
+
248
+ **Response:**
249
+ ```json
250
+ {
251
+ "verified_name": "Minha Empresa LTDA",
252
+ "display_phone_number": "+55 11 99999-9999",
253
+ "quality_rating": "GREEN",
254
+ "id": "123456789012345",
255
+ "name_status": "APPROVED",
256
+ "status": "CONNECTED"
257
+ }
258
+ ```
259
+
260
+ ---
261
+
262
+ #### 6. Exchange Token (Refresh)
263
+
264
+ ```
265
+ POST /oauth/access_token
266
+ ```
267
+
268
+ **Query Parameters:**
269
+ ```
270
+ grant_type=fb_exchange_token
271
+ &client_id={app-id}
272
+ &client_secret={app-secret}
273
+ &fb_exchange_token={short-lived-token}
274
+ ```
275
+
276
+ **Response:**
277
+ ```json
278
+ {
279
+ "access_token": "EAAxxxxxxxxxxxx",
280
+ "token_type": "bearer",
281
+ "expires_in": 5184000
282
+ }
283
+ ```
284
+
285
+ ---
286
+
287
+ ### Rate Limits
288
+
289
+ | Tier | Limite Diário | Requisitos |
290
+ |------|---------------|------------|
291
+ | **Tier 1** | 1.000 mensagens/dia | Número recém-registrado |
292
+ | **Tier 2** | 10.000 mensagens/dia | Envio de 1.000 msgs em 7 dias |
293
+ | **Tier 3** | 100.000 mensagens/dia | Envio de 10.000 msgs em 7 dias |
294
+ | **Unlimited** | Sem limite | Aprovação manual Meta (enterprise) |
295
+
296
+ **Recomendação:** Implementar throttling na aplicação para evitar atingir limites.
297
+
298
+ ---
299
+
300
+ ### Webhooks da Meta
301
+
302
+ A Meta envia webhooks para os eventos:
303
+
304
+ **Eventos Suportados:**
305
+ - `messages` - Mensagem recebida
306
+ - `message_status` - Status de entrega (sent, delivered, read, failed)
307
+ - `account_update` - Atualização na conta (quality rating, limites)
308
+ - `phone_number_quality_update` - Mudança no quality rating
309
+
310
+ **Payload de Webhook (Mensagem Recebida):**
311
+
312
+ <details>
313
+ <summary>Ver payload completo (clique para expandir)</summary>
314
+
315
+ ```json
316
+ {
317
+ "object": "whatsapp_business_account",
318
+ "entry": [
319
+ {
320
+ "id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
321
+ "changes": [
322
+ {
323
+ "value": {
324
+ "messaging_product": "whatsapp",
325
+ "metadata": {
326
+ "display_phone_number": "5511999999999",
327
+ "phone_number_id": "123456789012345"
328
+ },
329
+ "contacts": [
330
+ {
331
+ "profile": {
332
+ "name": "João Silva"
333
+ },
334
+ "wa_id": "5511888888888"
335
+ }
336
+ ],
337
+ "messages": [
338
+ {
339
+ "from": "5511888888888",
340
+ "id": "wamid.HBgNNTUxMTk4ODg4ODg4OBUCABIYIDNBNjdGMzQ5QzE5MEFCMTY1MjU0",
341
+ "timestamp": "1709740800",
342
+ "type": "text",
343
+ "text": {
344
+ "body": "Olá, preciso de ajuda!"
345
+ }
346
+ }
347
+ ]
348
+ },
349
+ "field": "messages"
350
+ }
351
+ ]
352
+ }
353
+ ]
354
+ }
355
+ ```
356
+ </details>
357
+
358
+ **Webhook Verification (GET Request):**
359
+
360
+ ```http
361
+ GET /webhooks?hub.mode=subscribe&hub.challenge=CHALLENGE_TOKEN&hub.verify_token=YOUR_VERIFY_TOKEN
362
+ ```
363
+
364
+ **Resposta esperada:**
365
+ ```
366
+ CHALLENGE_TOKEN
367
+ ```
368
+
369
+ ---
370
+
371
+ ## 🔧 Naty Meta API (Backend Proprietário)
372
+
373
+ ### Informações Gerais
374
+
375
+ | Propriedade | Valor |
376
+ |-------------|-------|
377
+ | **Base URL** | `process.env.API_META` (ex: `https://api.meta.naty.app/v1`) |
378
+ | **Protocolo** | HTTPS (REST API) |
379
+ | **Autenticação** | Header `x-access-token: {appToken}` |
380
+ | **Formato** | JSON |
381
+
382
+ ### Endpoints Utilizados
383
+
384
+ #### 1. Validação de App Token
385
+
386
+ ```
387
+ POST /validate/validateAppToken
388
+ ```
389
+
390
+ **Headers:**
391
+ ```http
392
+ Content-Type: application/json
393
+ ```
394
+
395
+ **Body:**
396
+ ```json
397
+ {
398
+ "appToken": "naty_app_token_xyz"
399
+ }
400
+ ```
401
+
402
+ **Response (Sucesso):**
403
+ ```json
404
+ {
405
+ "valid": true,
406
+ "data": {
407
+ "appId": "app_123",
408
+ "companyId": "company_abc"
409
+ }
410
+ }
411
+ ```
412
+
413
+ **Response (Falha):**
414
+ ```json
415
+ {
416
+ "valid": false,
417
+ "error": "Invalid token"
418
+ }
419
+ ```
420
+
421
+ ---
422
+
423
+ #### 2. CRUD de Conexões
424
+
425
+ **Criar Conexão:**
426
+ ```
427
+ POST /connection
428
+ ```
429
+
430
+ **Headers:**
431
+ ```http
432
+ x-access-token: {appToken}
433
+ Content-Type: application/json
434
+ ```
435
+
436
+ **Body:**
437
+ ```json
438
+ {
439
+ "companyId": "abc123",
440
+ "phoneNumberId": "123456789012345",
441
+ "accessToken": "EAAxxxxxxxxxxxx",
442
+ "appId": "123456789",
443
+ "appSecret": "abcdef1234567890",
444
+ "accountId": "987654321",
445
+ "businessId": "456789123",
446
+ "phoneNumber": "+5511999999999"
447
+ }
448
+ ```
449
+
450
+ **Response:**
451
+ ```json
452
+ {
453
+ "id": "conn_xyz789",
454
+ "companyId": "abc123",
455
+ "phoneNumberId": "123456789012345",
456
+ "isActive": true,
457
+ "createdAt": "2026-02-06T10:00:00.000Z"
458
+ }
459
+ ```
460
+
461
+ ---
462
+
463
+ **Buscar Conexão:**
464
+ ```
465
+ GET /connection?companyId={companyId}&phoneNumberId={phoneNumberId}
466
+ ```
467
+
468
+ **Headers:**
469
+ ```http
470
+ x-access-token: {appToken}
471
+ ```
472
+
473
+ **Response:**
474
+ ```json
475
+ {
476
+ "_id": "65e1234567890abcdef",
477
+ "id": "conn_xyz789",
478
+ "companyId": "abc123",
479
+ "phoneNumberId": "123456789012345",
480
+ "accessToken": "EAAxxxxxxxxxxxx",
481
+ "appId": "123456789",
482
+ "appSecret": "abcdef1234567890",
483
+ "isActive": true,
484
+ "createdAt": "2026-02-06T10:00:00.000Z",
485
+ "updatedAt": "2026-02-06T10:30:00.000Z"
486
+ }
487
+ ```
488
+
489
+ ---
490
+
491
+ **Atualizar Conexão:**
492
+ ```
493
+ PUT /connection/{connectionId}
494
+ ```
495
+
496
+ **Headers:**
497
+ ```http
498
+ x-access-token: {appToken}
499
+ Content-Type: application/json
500
+ ```
501
+
502
+ **Body:**
503
+ ```json
504
+ {
505
+ "accessToken": "EAAyyyyyyyyyy"
506
+ }
507
+ ```
508
+
509
+ ---
510
+
511
+ **Deletar Conexão (Soft Delete):**
512
+ ```
513
+ DELETE /connection/{connectionId}
514
+ ```
515
+
516
+ **Response:**
517
+ ```json
518
+ {
519
+ "success": true,
520
+ "message": "Connection marked as inactive"
521
+ }
522
+ ```
523
+
524
+ ---
525
+
526
+ #### 3. CRUD de Webhooks
527
+
528
+ **Criar Webhook:**
529
+ ```
530
+ POST /webhook
531
+ ```
532
+
533
+ **Body:**
534
+ ```json
535
+ {
536
+ "companyId": "abc123",
537
+ "connection": {
538
+ "url": "https://myapp.com/webhooks/connections",
539
+ "active": true
540
+ },
541
+ "messages": {
542
+ "url": "https://myapp.com/webhooks/messages",
543
+ "active": true
544
+ }
545
+ }
546
+ ```
547
+
548
+ ---
549
+
550
+ **Buscar Webhook:**
551
+ ```
552
+ GET /webhook?companyId={companyId}
553
+ ```
554
+
555
+ **Response:**
556
+ ```json
557
+ {
558
+ "id": "wh_abc123",
559
+ "companyId": "abc123",
560
+ "connection": {
561
+ "url": "https://myapp.com/webhooks/connections",
562
+ "active": true
563
+ },
564
+ "messages": {
565
+ "url": "https://myapp.com/webhooks/messages",
566
+ "active": true
567
+ },
568
+ "isActive": true
569
+ }
570
+ ```
571
+
572
+ ---
573
+
574
+ #### 4. CRUD de Mensagens
575
+
576
+ **Salvar Mensagem:**
577
+ ```
578
+ POST /message
579
+ ```
580
+
581
+ **Body:**
582
+ ```json
583
+ {
584
+ "companyId": "abc123",
585
+ "phoneNumberId": "123456789012345",
586
+ "sender": "5511888888888",
587
+ "message": {
588
+ "id": "wamid.xxx",
589
+ "type": "text",
590
+ "timestamp": "1709740800",
591
+ "text": { "body": "Olá!" }
592
+ }
593
+ }
594
+ ```
595
+
596
+ ---
597
+
598
+ **Buscar Mensagens:**
599
+ ```
600
+ GET /messages?companyId={companyId}&phoneNumberId={phoneNumberId}&limit=50
601
+ ```
602
+
603
+ **Response:**
604
+ ```json
605
+ {
606
+ "messages": [
607
+ {
608
+ "id": "msg_123",
609
+ "companyId": "abc123",
610
+ "sender": "5511888888888",
611
+ "message": { "type": "text", "text": { "body": "Olá!" } },
612
+ "createdAt": "2026-02-06T10:00:00.000Z"
613
+ }
614
+ ],
615
+ "total": 150,
616
+ "page": 1
617
+ }
618
+ ```
619
+
620
+ ---
621
+
622
+ #### 5. Logs
623
+
624
+ **Criar Log:**
625
+ ```
626
+ POST /logs
627
+ ```
628
+
629
+ **Body:**
630
+ ```json
631
+ {
632
+ "type": "Access",
633
+ "owner": "app_123",
634
+ "url": "/messages",
635
+ "method": "POST",
636
+ "remoteIP": "192.168.1.100",
637
+ "objectData": { "messageId": "wamid.xxx" }
638
+ }
639
+ ```
640
+
641
+ ---
642
+
643
+ **Criar Log de Erro:**
644
+ ```
645
+ POST /logs/error
646
+ ```
647
+
648
+ **Body:**
649
+ ```json
650
+ {
651
+ "connectionId": "conn_xyz789",
652
+ "errorFrom": "send_message",
653
+ "statusCode": 401,
654
+ "error": {
655
+ "message": "Invalid token",
656
+ "stack": "Error: Invalid token\n at ..."
657
+ }
658
+ }
659
+ ```
660
+
661
+ ---
662
+
663
+ ### Códigos de Status
664
+
665
+ | Código | Significado |
666
+ |--------|-------------|
667
+ | 200 | Sucesso |
668
+ | 201 | Recurso criado |
669
+ | 400 | Bad request (payload inválido) |
670
+ | 401 | Unauthorized (appToken inválido) |
671
+ | 404 | Recurso não encontrado |
672
+ | 500 | Erro interno do servidor |
673
+
674
+ ---
675
+
676
+ ## ⚙️ Express.js (Integração Opcional)
677
+
678
+ ### Propósito
679
+
680
+ O SDK pode integrar-se a uma aplicação Express existente para:
681
+ - Registrar rotas de webhook automaticamente
682
+ - Receber webhooks da Meta
683
+ - Processar eventos e emitir para a aplicação
684
+
685
+ ### Integração
686
+
687
+ **Arquivo:** [`src/routes/webhooks/index.ts`](../src/routes/webhooks/index.ts)
688
+
689
+ ```typescript
690
+ import express from 'express';
691
+ import { NatyMeta } from '@natyapp/meta';
692
+
693
+ const app = express();
694
+ app.use(express.json());
695
+
696
+ // Integrar SDK ao Express
697
+ const sdk = new NatyMeta();
698
+ await sdk.connect({
699
+ appToken: 'seu-app-token',
700
+ app: app, // Passa instância Express
701
+ pathname: '/webhooks' // Base path
702
+ });
703
+
704
+ // Rotas registradas automaticamente:
705
+ // - GET /webhooks/messages
706
+ // - POST /webhooks/messages
707
+ // - GET /webhooks/connections
708
+ // - POST /webhooks/connections
709
+
710
+ app.listen(3000, () => {
711
+ console.log('Servidor rodando na porta 3000');
712
+ });
713
+ ```
714
+
715
+ ### Rotas Expostas
716
+
717
+ #### 1. POST /webhooks/messages
718
+
719
+ **Recebe:** Mensagens enviadas por clientes.
720
+
721
+ **Handler:** [`src/routes/webhooks/methods/messages.ts`](../src/routes/webhooks/methods/messages.ts)
722
+
723
+ **Comportamento:**
724
+ 1. Valida payload da Meta
725
+ 2. Cria `WhatsappMessage` entity
726
+ 3. Instancia `WhatsappResponse` para resposta
727
+ 4. Emite evento `'message'`
728
+ 5. Retorna 200 OK
729
+
730
+ ---
731
+
732
+ #### 2. GET /webhooks/messages
733
+
734
+ **Recebe:** Verificação inicial da Meta.
735
+
736
+ **Query Params:**
737
+ - `hub.mode=subscribe`
738
+ - `hub.challenge={token}`
739
+ - `hub.verify_token={verify_token}`
740
+
741
+ **Comportamento:**
742
+ 1. Valida `hub.verify_token`
743
+ 2. Retorna `hub.challenge`
744
+
745
+ ---
746
+
747
+ #### 3. POST /webhooks/connections
748
+
749
+ **Recebe:** Verificação de conexão WhatsApp.
750
+
751
+ **Comportamento:**
752
+ 1. Extrai `connectionId` do payload
753
+ 2. Busca conexão na Naty API
754
+ 3. Obtém info da conta na Meta API
755
+ 4. Emite evento `'connection'`
756
+ 5. Retorna 200 OK
757
+
758
+ ---
759
+
760
+ #### 4. GET /webhooks/connections
761
+
762
+ **Recebe:** Verificação inicial (similar a messages).
763
+
764
+ ---
765
+
766
+ ## 📊 Diagramas de Integração
767
+
768
+ ### Diagrama de Sequência - Envio de Mensagem
769
+
770
+ ```mermaid
771
+ sequenceDiagram
772
+ participant App as Aplicação
773
+ participant SDK as SDK Naty
774
+ participant Naty as Naty API
775
+ participant Meta as Meta Graph API
776
+ participant WA as WhatsApp
777
+ participant Client as Cliente Final
778
+
779
+ App->>SDK: send_text({ to, message })
780
+
781
+ SDK->>Naty: GET /connection<br/>(buscar credenciais)
782
+ Naty-->>SDK: { accessToken, appId, appSecret }
783
+
784
+ SDK->>Meta: POST /oauth/access_token<br/>(refresh token)
785
+ Meta-->>SDK: { access_token: newToken }
786
+
787
+ SDK->>Naty: PUT /connection<br/>(salvar novo token)
788
+
789
+ SDK->>Meta: POST /{phoneNumberId}/messages<br/>{ to, type: 'text', text }
790
+ Meta->>WA: Processa mensagem
791
+ WA->>Client: Entrega via WhatsApp
792
+ Meta-->>SDK: { messages: [{ id }] }
793
+
794
+ SDK->>Naty: POST /logs<br/>(registrar operação)
795
+
796
+ SDK-->>App: Either.right({ id })
797
+ ```
798
+
799
+ ---
800
+
801
+ ### Diagrama de Sequência - Recebimento de Mensagem
802
+
803
+ ```mermaid
804
+ sequenceDiagram
805
+ participant Client as Cliente Final
806
+ participant WA as WhatsApp
807
+ participant Meta as Meta Webhook
808
+ participant Express as Express/Webhook
809
+ participant SDK as SDK Events
810
+ participant App as Aplicação
811
+
812
+ Client->>WA: Envia mensagem
813
+ WA->>Meta: Processa
814
+
815
+ Meta->>Express: POST /webhooks/messages<br/>{ entry: [...] }
816
+
817
+ Express->>Express: Parse payload
818
+ Express->>SDK: emit('message', data)
819
+
820
+ SDK->>App: Listener recebe evento
821
+
822
+ App->>App: Processa lógica<br/>(chatbot, IA, etc.)
823
+
824
+ App->>SDK: whatsappResponse.send_text()
825
+ SDK->>Meta: POST /messages
826
+ Meta->>WA: Envia resposta
827
+ WA->>Client: Recebe resposta
828
+
829
+ Express-->>Meta: 200 OK
830
+ ```
831
+
832
+ ---
833
+
834
+ ## ⏱ Rate Limits e Throttling
835
+
836
+ ### Limites da Meta
837
+
838
+ | Recurso | Limite |
839
+ |---------|--------|
840
+ | **Mensagens** | Varia por Tier (1k - 100k/dia) |
841
+ | **API Calls** | ~200 requisições/hora por token |
842
+ | **Upload Mídia** | 100 MB/dia por número |
843
+ | **Webhook Retries** | 3 tentativas com exponential backoff |
844
+
845
+ ### Estratégias de Throttling
846
+
847
+ **1. Queue de Mensagens (Recomendado)**
848
+
849
+ ```typescript
850
+ import PQueue from 'p-queue';
851
+
852
+ // Fila com limite de 10 mensagens/segundo
853
+ const queue = new PQueue({
854
+ interval: 1000,
855
+ intervalCap: 10
856
+ });
857
+
858
+ // Adicionar envios à fila
859
+ const sendthrottled = (to: string, message: string) => {
860
+ return queue.add(() => whatsapp.send_text({ to, message }));
861
+ };
862
+
863
+ // Uso
864
+ await sendThrottled('5511999999999', 'Mensagem 1');
865
+ await sendThrottled('5511888888888', 'Mensagem 2');
866
+ // ...
867
+ ```
868
+
869
+ **2. Retry com Exponential Backoff**
870
+
871
+ ```typescript
872
+ async function sendWithRetry(to: string, message: string, maxRetries = 3) {
873
+ for (let i = 0; i < maxRetries; i++) {
874
+ const result = await whatsapp.send_text({ to, message });
875
+
876
+ if (result.isRight()) {
877
+ return result;
878
+ }
879
+
880
+ // Se erro 429 (rate limit), aguardar antes de retry
881
+ if (result.value.statusCode === 429) {
882
+ const waitTime = Math.pow(2, i) * 1000; // 1s, 2s, 4s
883
+ console.log(`Rate limit hit. Waiting ${waitTime}ms...`);
884
+ await new Promise(resolve => setTimeout(resolve, waitTime));
885
+ } else {
886
+ return result; // Outro erro, não retry
887
+ }
888
+ }
889
+
890
+ return left(new Error('Max retries exceeded'));
891
+ }
892
+ ```
893
+
894
+ ---
895
+
896
+ ## 🔒 Segurança e Autenticação
897
+
898
+ ### Hierarquia de Credenciais
899
+
900
+ ```mermaid
901
+ graph TD
902
+ A[appToken<br/>Naty Platform] --> B[companyId<br/>Tenant]
903
+ B --> C1[Connection 1<br/>accessToken Meta]
904
+ B --> C2[Connection 2<br/>accessToken Meta]
905
+
906
+ C1 --> D1[phoneNumberId 1<br/>WhatsApp Number]
907
+ C2 --> D2[phoneNumberId 2<br/>WhatsApp Number]
908
+
909
+ style A fill:#E3F2FD
910
+ style B fill:#BBDEFB
911
+ style C1 fill:#90CAF9
912
+ style C2 fill:#90CAF9
913
+ style D1 fill:#64B5F6,color:#fff
914
+ style D2 fill:#64B5F6,color:#fff
915
+ ```
916
+
917
+ ### Boas Práticas
918
+
919
+ 1. **Nunca commitar tokens:**
920
+ ```bash
921
+ # .env
922
+ NATY_APP_TOKEN=seu_token_aqui
923
+ API_META=https://api.meta.naty.app/v1
924
+ ```
925
+
926
+ 2. **Rotacionar tokens periodicamente:**
927
+ - Tokens Meta expiram em 60 dias
928
+ - Refresh automático implementado pelo SDK
929
+
930
+ 3. **Validar webhooks da Meta:**
931
+ ```typescript
932
+ // Verificar se requisição vem da Meta
933
+ const validateWebhook = (req: Request) => {
934
+ const signature = req.headers['x-hub-signature-256'];
935
+ // Validar HMAC SHA256 com app secret
936
+ // (Implementado internamente no SDK)
937
+ };
938
+ ```
939
+
940
+ 4. **HTTPS obrigatório:**
941
+ - Webhooks devem usar HTTPS
942
+ - Certificado SSL válido
943
+
944
+ 5. **Logging de acessos:**
945
+ - Todas operações são logadas automaticamente
946
+ - Logs contêm IP, timestamp, ação
947
+
948
+ ---
949
+
950
+ ## 🔗 Próximos Passos
951
+
952
+ Com as integrações compreendidas, explore:
953
+
954
+ - **[Entidades](06-entidades.md)** - Estrutura de dados detalhada
955
+ - **[Guia Prático](07-guia-pratico.md)** - Exemplos práticos de integração
956
+ - **[Troubleshooting](08-troubleshooting.md)** - Resolver problemas de integração
957
+
958
+ ---
959
+
960
+ [⬅️ Anterior: Fluxos Funcionais](04-fluxos-funcionais.md) | [⬆️ Voltar ao Índice](README.md) | [➡️ Próximo: Entidades](06-entidades.md)