atendeaqui 1.0.0__tar.gz

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.
@@ -0,0 +1,82 @@
1
+ # AtendeAqui Python SDK — Copilot Instructions
2
+
3
+ ## Build & Test
4
+
5
+ ```bash
6
+ # Install (with dev deps)
7
+ pip install -e ".[dev]"
8
+
9
+ # Run all tests
10
+ pytest
11
+
12
+ # Run a single test file
13
+ pytest tests/test_client.py
14
+
15
+ # Run a single test
16
+ pytest tests/test_client.py::TestOnboarding::test_get_structure
17
+ ```
18
+
19
+ No linter is configured in the project yet.
20
+
21
+ ## Architecture
22
+
23
+ The SDK is a thin HTTP wrapper around the AtendeAqui REST API.
24
+
25
+ ```
26
+ AtendeAquiClient (src/atendeaqui/client.py)
27
+ ├── HttpClient (_http.py) — shared requests.Session, error handling
28
+ ├── ClientsModule (clients/) — client.clients.*
29
+ └── OnboardingModule (onboarding/) — client.onboarding.*
30
+ ```
31
+
32
+ `AtendeAquiClient` requires at least one of `api_token` (Bearer token for admin endpoints) or `flow_key` (public UUID for onboarding endpoints). Both can be provided together.
33
+
34
+ `HttpClient` is the only transport layer. All modules receive it in their `__init__` and call `self._http.get/post/patch/put/delete(path, ...)`. It handles error parsing and maps API error codes to SDK exceptions via `ERROR_CODE_MAP` in `exceptions.py`.
35
+
36
+ ## Key Conventions
37
+
38
+ ### Models
39
+ All response models are plain `@dataclass` classes with a single `from_dict(cls, data: dict)` classmethod. They never raise — missing fields fall back to safe defaults (empty strings, `[]`, `{}`).
40
+
41
+ ```python
42
+ @dataclass
43
+ class MyModel:
44
+ field: str
45
+
46
+ @classmethod
47
+ def from_dict(cls, data: dict) -> MyModel:
48
+ return cls(field=data.get('field', ''))
49
+ ```
50
+
51
+ All model and module files use `from __future__ import annotations`.
52
+
53
+ ### Adding a New Module
54
+ 1. Create `src/atendeaqui/<module>/` with `__init__.py` (the module class) and `models.py`.
55
+ 2. The module class takes `http: HttpClient` as its only required constructor arg. Add optional default params (e.g., `default_flow_key`) as keyword-only args.
56
+ 3. Expose the module as a `@property` on `AtendeAquiClient` in `client.py`.
57
+ 4. Export all public symbols from `src/atendeaqui/__init__.py`.
58
+
59
+ ### Exception Hierarchy
60
+ All exceptions inherit from `AtendeAquiError(message, code, status_code, response)`. Specific codes are mapped in `exceptions.ERROR_CODE_MAP`. When adding new API error codes, add them to the map and create a new exception class if semantically distinct.
61
+
62
+ ### Testing Pattern
63
+ Tests use the `responses` library to mock HTTP calls. Fixtures are in `tests/conftest.py`:
64
+
65
+ - `client` — `flow_key` only (public onboarding API)
66
+ - `admin_client` — `api_token` + `flow_key`
67
+ - `admin_only_client` — `api_token` only
68
+
69
+ All fixtures use `_base_url='https://test.atendeaqui.com.br/api'` (private param, for tests only). Mock the exact URL the module would call:
70
+
71
+ ```python
72
+ @responses.activate
73
+ def test_something(self, client, mocked_responses):
74
+ mocked_responses.add(responses.GET, f'{BASE_URL}/api/resource/', json={...})
75
+ result = client.module.method()
76
+ assert result.field == 'expected'
77
+ ```
78
+
79
+ ### API URL Structure
80
+ - Production: `https://api.atendeaqui.com.br/v1`
81
+ - Sandbox: `https://api.homolog.atendeaqui.com.br/v1`
82
+ - Paths use trailing slashes: `clients/`, `clients/{id}/`, `clients/{id}/team/`
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Distribution / packaging
8
+ dist/
9
+ build/
10
+ *.egg-info/
11
+ *.egg
12
+ src/*.egg-info/
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+
19
+ # IDE
20
+ .idea/
21
+ .vscode/
22
+ *.sublime-project
23
+ *.sublime-workspace
24
+
25
+ # Testing
26
+ .pytest_cache/
27
+ .coverage
28
+ htmlcov/
29
+
30
+ # OS
31
+ .DS_Store
32
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 AtendeAqui
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.
@@ -0,0 +1,550 @@
1
+ Metadata-Version: 2.4
2
+ Name: atendeaqui
3
+ Version: 1.0.0
4
+ Summary: SDK Python para a plataforma AtendeAqui
5
+ Author: AtendeAqui
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: requests>=2.28
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest>=7.0; extra == 'dev'
19
+ Requires-Dist: responses>=0.23; extra == 'dev'
20
+ Description-Content-Type: text/markdown
21
+
22
+ # AtendeAqui SDK Python
23
+
24
+ SDK Python unificado para a plataforma AtendeAqui.
25
+
26
+ ## Instalação
27
+
28
+ ```bash
29
+ pip install atendeaqui
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ```python
35
+ from atendeaqui import AtendeAquiClient
36
+
37
+ client = AtendeAquiClient(api_token="seu-bearer-token")
38
+
39
+ # Onboarding
40
+ flow = client.onboarding.get_structure(flow_key="uuid-do-flow", language="pt-BR")
41
+ progress = client.onboarding.start_flow(flow_key="uuid-do-flow", user_id="user-123", name="João Silva", email="u@example.com")
42
+ progress = client.onboarding.complete_step(flow_key="uuid-do-flow", user_id="user-123", step_key="welcome")
43
+ print(f"Progresso: {progress.completion_percentage}%")
44
+ ```
45
+
46
+ ## Autenticação
47
+
48
+ ### Com api_token (recomendado)
49
+
50
+ O `api_token` é um Bearer token gerado no dashboard. Dá acesso a todos os módulos: clientes, onboarding (admin e progresso) e futuros módulos.
51
+
52
+ ```python
53
+ client = AtendeAquiClient(api_token="seu-bearer-token")
54
+
55
+ # Clientes
56
+ client.clients.list()
57
+
58
+ # Onboarding — passa flow_key por operação
59
+ client.onboarding.start_flow(flow_key="uuid-do-flow", user_id="user-123")
60
+ client.onboarding.list_flows()
61
+ client.onboarding.get_analytics(slug="meu-flow")
62
+ ```
63
+
64
+ ### Com flow_key default (atalho para um único flow)
65
+
66
+ Se o seu sistema interage com um único flow, passe `flow_key` na inicialização. Ele será usado como default em todos os métodos de onboarding (pode ser sobrescrito por chamada).
67
+
68
+ ```python
69
+ client = AtendeAquiClient(flow_key="f47ac10b-58cc-4372-a567-0e02b2c3d479")
70
+
71
+ # Usa o flow_key default — não precisa repetir
72
+ client.onboarding.get_structure()
73
+ client.onboarding.start_flow(user_id="user-123")
74
+
75
+ # Pode sobrescrever por chamada
76
+ client.onboarding.get_structure(flow_key="outro-flow-uuid")
77
+ ```
78
+
79
+ ### Com ambos (API admin + flow default)
80
+
81
+ ```python
82
+ client = AtendeAquiClient(
83
+ api_token="seu-bearer-token",
84
+ flow_key="f47ac10b-58cc-4372-a567-0e02b2c3d479",
85
+ )
86
+ # Operações de progresso (usa flow_key default)
87
+ client.onboarding.start_flow(user_id="user-123")
88
+ # Operações admin (usa api_token)
89
+ client.onboarding.list_flows()
90
+ client.onboarding.get_analytics(slug="meu-flow")
91
+ ```
92
+
93
+ ## Módulos
94
+
95
+ ### Clientes (requer api_token)
96
+
97
+ ```python
98
+ admin = AtendeAquiClient(api_token="seu-bearer-token")
99
+
100
+ # Listar clientes
101
+ clientes = admin.clients.list(page=1, page_size=50)
102
+
103
+ # Criar cliente (client_id é gerado automaticamente se não fornecido)
104
+ novo = admin.clients.create(
105
+ full_name="Acme Corp",
106
+ email="contato@acme.com",
107
+ phone="1133334444",
108
+ identification_number="12.345.678/0001-90",
109
+ type_identification="CNPJ",
110
+ )
111
+ print(novo.client_id) # UUID gerado automaticamente
112
+
113
+ # Ou criar com ID do seu sistema (evita manter mapeamento de IDs)
114
+ novo = admin.clients.create(
115
+ full_name="Acme Corp",
116
+ email="contato@acme.com",
117
+ client_id="meu-sistema-123", # opcional: usa o ID do seu sistema local
118
+ )
119
+
120
+ # Detalhes do cliente
121
+ cliente = admin.clients.get(client_id=novo.client_id)
122
+
123
+ # Atualizar cliente
124
+ admin.clients.update(novo.client_id, full_name="Acme Corp Ltda", phone="1199998888")
125
+
126
+ # Equipe do cliente
127
+ team = admin.clients.get_team(novo.client_id)
128
+ for member in team:
129
+ print(f"{member.full_name} (primary={member.is_primary})")
130
+
131
+ # Adicionar membro (cria usuário se não existir)
132
+ member = admin.clients.add_team_member(
133
+ client_id=novo.client_id,
134
+ user_email="joao@acme.com",
135
+ is_primary=True,
136
+ can_create_tickets=True,
137
+ )
138
+
139
+ # Atualizar permissões
140
+ admin.clients.update_team_member(novo.client_id, member.id, can_edit_client=True)
141
+
142
+ # Remover membro
143
+ admin.clients.remove_team_member(novo.client_id, member.id)
144
+ ```
145
+
146
+ ### Onboarding
147
+
148
+ ```python
149
+ FLOW = "uuid-do-flow"
150
+
151
+ # Estrutura do flow
152
+ flow = client.onboarding.get_structure(flow_key=FLOW, language="pt-BR")
153
+
154
+ # Iniciar onboarding
155
+ progress = client.onboarding.start_flow(
156
+ flow_key=FLOW,
157
+ user_id="user-123",
158
+ name="João Silva",
159
+ email="user@example.com",
160
+ metadata={"company": "Acme", "preferred_language": "pt-BR"},
161
+ )
162
+
163
+ # Registrar início de um step (rastreamento, sem marcar como completo)
164
+ progress = client.onboarding.start_step(
165
+ user_id="user-123",
166
+ flow_key=FLOW,
167
+ step_key="welcome",
168
+ metadata={"source": "sidebar", "device": "desktop"}, # opcional
169
+ )
170
+
171
+ # Completar steps
172
+ progress = client.onboarding.complete_step(
173
+ user_id="user-123",
174
+ flow_key=FLOW,
175
+ step_key="welcome",
176
+ step_data={"accepted_terms": True},
177
+ )
178
+
179
+ # Completar múltiplos steps (batch)
180
+ progress = client.onboarding.complete_steps(
181
+ user_id="user-123",
182
+ flow_key=FLOW,
183
+ steps=[
184
+ {"step_key": "config", "step_data": {"api_key": "xxx"}},
185
+ {"step_key": "test"},
186
+ ],
187
+ )
188
+
189
+ # Pular step opcional
190
+ progress = client.onboarding.skip_step(user_id="user-123", flow_key=FLOW, step_key="tour")
191
+
192
+ # Atualizar metadata (merge)
193
+ progress = client.onboarding.update_metadata(
194
+ user_id="user-123",
195
+ flow_key=FLOW,
196
+ metadata={"plan": "pro"},
197
+ )
198
+
199
+ # Consultar progresso
200
+ progress = client.onboarding.get_progress(user_id="user-123", flow_key=FLOW)
201
+ print(progress.status) # IN_PROGRESS
202
+ print(progress.steps_completed) # ['welcome', 'config']
203
+ print(progress.step_data) # {'welcome': {'accepted_terms': True}, ...}
204
+ print(progress.completion_percentage) # 75
205
+ print(progress.flow_slug) # 'onboarding-clientes'
206
+
207
+ # Ações no flow
208
+ client.onboarding.complete_flow(user_id="user-123", flow_key=FLOW)
209
+ client.onboarding.restart_flow(user_id="user-123", flow_key=FLOW)
210
+ client.onboarding.abandon_flow(user_id="user-123", flow_key=FLOW)
211
+
212
+ # Token para widget frontend
213
+ token = client.onboarding.get_widget_token(flow_key=FLOW, user_id="user-123", ttl=600)
214
+
215
+ # Admin: listar flows e analytics (requer api_token)
216
+ flows = client.onboarding.list_flows()
217
+ analytics = client.onboarding.get_analytics(slug="meu-flow")
218
+ progress_list = client.onboarding.list_progress(slug="meu-flow")
219
+ ```
220
+
221
+ ## Exemplos de Uso
222
+
223
+ ### Fluxo completo com dados de perfil
224
+
225
+ Quanto mais dados você enviar no `metadata` e `step_data`, mais personalizados serão os e-mails automáticos enviados pelo sistema. O sistema de e-mails usa IA para gerar conteúdo baseado no perfil e caso de uso do cliente.
226
+
227
+ ```python
228
+ from atendeaqui import AtendeAquiClient
229
+
230
+ client = AtendeAquiClient(flow_key="uuid-do-flow")
231
+
232
+ # 1. Iniciar o flow com metadata do usuário
233
+ # Esses dados são usados pela IA para personalizar e-mails de boas-vindas
234
+ progress = client.onboarding.start_flow(
235
+ user_id="empresa-456",
236
+ name="João Silva",
237
+ email="joao@agendapro.com.br",
238
+ metadata={
239
+ "company": "AgendaPro",
240
+ "sector": "tecnologia",
241
+ "role": "CTO",
242
+ "plan": "professional",
243
+ "preferred_language": "pt-BR",
244
+ },
245
+ )
246
+ # >>> E-mail de boas-vindas é enviado automaticamente (se configurado)
247
+ # >>> A IA usa nome, empresa e cargo para personalizar a saudação
248
+
249
+ # 2. Completar etapa de perfil com caso de uso
250
+ # step_data é JSON livre — envie tudo que descreve o cenário do cliente
251
+ progress = client.onboarding.complete_step(
252
+ user_id="empresa-456",
253
+ step_key="perfil",
254
+ step_data={
255
+ "uso_pretendido": "reuniões de vendas",
256
+ "tamanho_equipe": "até 10 pessoas",
257
+ "frequencia_uso": "diário",
258
+ "integracao_desejada": "Google Calendar",
259
+ },
260
+ )
261
+
262
+ # 3. Completar configuração técnica
263
+ progress = client.onboarding.complete_step(
264
+ user_id="empresa-456",
265
+ step_key="configuracao-api",
266
+ step_data={
267
+ "api_token": "EAAG...configurado",
268
+ "provider": "google",
269
+ "webhook_url": "https://agendapro.com.br/webhook",
270
+ },
271
+ )
272
+
273
+ # 4. Completar múltiplos steps de uma vez
274
+ progress = client.onboarding.complete_steps(
275
+ user_id="empresa-456",
276
+ steps=[
277
+ {
278
+ "step_key": "convidar-equipe",
279
+ "step_data": {
280
+ "membros_convidados": 5,
281
+ "emails": ["ana@agendapro.com.br", "pedro@agendapro.com.br"],
282
+ },
283
+ },
284
+ {
285
+ "step_key": "personalizar-agenda",
286
+ "step_data": {
287
+ "horario_inicio": "08:00",
288
+ "horario_fim": "18:00",
289
+ "duracao_padrao": "30min",
290
+ "fuso_horario": "America/Sao_Paulo",
291
+ },
292
+ },
293
+ ],
294
+ )
295
+
296
+ # 5. Completar o flow
297
+ client.onboarding.complete_flow(user_id="empresa-456")
298
+ ```
299
+
300
+ ### Integração com sistema existente (SaaS)
301
+
302
+ Exemplo de integração server-side: criar cliente + iniciar onboarding vinculado.
303
+
304
+ ```python
305
+ from atendeaqui import AtendeAquiClient, NotFoundError
306
+
307
+ FLOW_KEY = "uuid-do-flow"
308
+
309
+ # api_token necessário para criar clientes
310
+ client = AtendeAquiClient(api_token="seu-bearer-token")
311
+
312
+
313
+ def on_client_signup(client_data: dict):
314
+ """Chamado após o cadastro de um novo cliente no seu sistema."""
315
+
316
+ # 1. Criar cliente no AtendeAqui usando o ID do seu sistema
317
+ # Isso evita manter um mapeamento separado de IDs
318
+ novo_cliente = client.clients.create(
319
+ full_name=client_data["company_name"],
320
+ email=client_data["email"],
321
+ client_id=client_data["id"], # usa o ID do seu sistema local
322
+ )
323
+
324
+ # 2. Iniciar onboarding vinculado ao cliente
325
+ progress = client.onboarding.start_flow(
326
+ flow_key=FLOW_KEY,
327
+ user_id=client_data["id"],
328
+ name=client_data["name"],
329
+ email=client_data["email"],
330
+ metadata={
331
+ "company": client_data.get("company_name", ""),
332
+ "sector": client_data.get("industry", ""),
333
+ "plan": client_data.get("plan", "free"),
334
+ },
335
+ client_id=novo_cliente.client_id, # vincula onboarding ao cliente
336
+ )
337
+
338
+ return progress
339
+
340
+
341
+ def on_feature_configured(user_id: str, feature: str, config: dict):
342
+ """Chamado quando o cliente configura uma feature no seu sistema."""
343
+
344
+ step_map = {
345
+ "api_setup": "configuracao-api",
346
+ "team_invite": "convidar-equipe",
347
+ "branding": "personalizar-marca",
348
+ }
349
+
350
+ step_key = step_map.get(feature)
351
+ if not step_key:
352
+ return
353
+
354
+ try:
355
+ progress = client.onboarding.complete_step(
356
+ flow_key=FLOW_KEY,
357
+ user_id=user_id,
358
+ step_key=step_key,
359
+ step_data=config,
360
+ )
361
+ return progress
362
+ except NotFoundError:
363
+ return None
364
+
365
+
366
+ def check_onboarding_status(user_id: str) -> dict:
367
+ """Verifica o status do onboarding para exibir no dashboard."""
368
+
369
+ try:
370
+ progress = client.onboarding.get_progress(flow_key=FLOW_KEY, user_id=user_id)
371
+ return {
372
+ "status": progress.status,
373
+ "percentage": progress.completion_percentage,
374
+ "is_completed": progress.is_completed,
375
+ "current_step": progress.current_step_title,
376
+ "steps_done": progress.steps_completed,
377
+ }
378
+ except NotFoundError:
379
+ return {"status": "NOT_STARTED", "percentage": 0}
380
+ ```
381
+
382
+ ### Widget frontend com token JWT
383
+
384
+ ```python
385
+ from atendeaqui import AtendeAquiClient
386
+
387
+ FLOW_KEY = "uuid-do-flow"
388
+
389
+ # Server-side: gerar token seguro para o frontend
390
+ server_client = AtendeAquiClient(flow_key=FLOW_KEY)
391
+
392
+ # Em uma view/endpoint do seu backend:
393
+ def get_onboarding_token(request):
394
+ token = server_client.onboarding.get_widget_token(
395
+ user_id=request.user.external_id,
396
+ client_id=request.user.client_id,
397
+ ttl=600, # 10 minutos
398
+ )
399
+ return {"token": token.token, "expires_in": token.expires_in}
400
+ ```
401
+
402
+ ### Atualizar metadata em tempo real
403
+
404
+ Use `update_metadata` para enriquecer o perfil do cliente conforme ele interage com o sistema. Esses dados são usados pela IA nos e-mails de lembrete e parabéns.
405
+
406
+ ```python
407
+ # Quando o cliente atualiza o plano
408
+ client.onboarding.update_metadata(
409
+ flow_key=FLOW_KEY,
410
+ user_id="empresa-456",
411
+ metadata={"plan": "enterprise", "seats": 50},
412
+ )
413
+
414
+ # Quando detectar a timezone do cliente
415
+ client.onboarding.update_metadata(
416
+ flow_key=FLOW_KEY,
417
+ user_id="empresa-456",
418
+ metadata={"timezone": "America/Sao_Paulo", "locale": "pt-BR"},
419
+ )
420
+ ```
421
+
422
+ ### Admin: monitorar onboarding
423
+
424
+ ```python
425
+ # Requer api_token (Bearer token)
426
+ admin_client = AtendeAquiClient(api_token="seu-bearer-token")
427
+
428
+ # Listar todos os flows
429
+ flows = admin_client.onboarding.list_flows()
430
+ for flow in flows:
431
+ print(f"{flow['name']}: {flow['total_starts']} inícios, "
432
+ f"{flow['completion_rate']}% conclusão")
433
+
434
+ # Analytics de um flow específico
435
+ analytics = admin_client.onboarding.get_analytics(slug="onboarding-clientes")
436
+ print(f"Taxa de conclusão: {analytics.completion_rate}%")
437
+ print(f"Tempo médio: {analytics.average_completion_time}s")
438
+ print(f"Em progresso: {analytics.in_progress}")
439
+ print(f"Abandonados: {analytics.abandoned}")
440
+
441
+ # Drop-off por etapa
442
+ for step_key, data in analytics.step_drop_off.items():
443
+ print(f" {data['title']}: {data['completion_rate']}% "
444
+ f"({data['dropped']} desistiram)")
445
+
446
+ # Listar progresso de todos os usuários
447
+ progress_list = admin_client.onboarding.list_progress(
448
+ slug="onboarding-clientes",
449
+ page=1,
450
+ page_size=100,
451
+ )
452
+ ```
453
+
454
+ ## Referência: step_data e e-mails automáticos
455
+
456
+ O sistema de automação de e-mails usa IA para gerar conteúdo personalizado. Quanto mais dados você enviar via `step_data` e `metadata`, melhor a personalização.
457
+
458
+ ### Parâmetros diretos do `start_flow`
459
+
460
+ | Parâmetro | Exemplo | Uso |
461
+ |-----------|---------|-----|
462
+ | `flow_key` | `"f47ac10b-..."` | UUID público do flow (obrigatório se não definido no client) |
463
+ | `name` | `"João Silva"` | Saudação nos e-mails, busca no admin |
464
+ | `email` | `"joao@acme.com"` | Destinatário dos e-mails automáticos |
465
+ | `client_id` | `"uuid-do-cliente"` | Opcional. Vincula o onboarding ao cliente (para tickets de suporte) |
466
+
467
+ ### Dados recomendados no `metadata` (start_flow)
468
+
469
+ | Campo | Exemplo | Uso nos e-mails |
470
+ |-------|---------|--------------------|
471
+ | `company` | `"AgendaPro"` | Contextualizar a empresa |
472
+ | `sector` | `"tecnologia"` | Adaptar linguagem ao setor |
473
+ | `role` | `"CTO"` | Tom e nível técnico adequado |
474
+ | `plan` | `"professional"` | Sugestões baseadas no plano |
475
+ | `preferred_language` | `"pt-BR"` | Idioma do e-mail |
476
+
477
+ ### Dados recomendados no `step_data` (complete_step)
478
+
479
+ | Step | Campos sugeridos | Uso nos e-mails |
480
+ |------|------------------|--------------------|
481
+ | Perfil/Caso de uso | `uso_pretendido`, `tamanho_equipe`, `frequencia_uso` | "Como você vai usar para reuniões de vendas com 10 pessoas..." |
482
+ | Configuração técnica | `provider`, `webhook_url` | "Você já configurou a integração com Google Calendar..." |
483
+ | Equipe | `membros_convidados`, `emails` | "Você convidou 5 membros — falta apenas personalizar a agenda" |
484
+ | Personalização | `horario_inicio`, `horario_fim`, `duracao_padrao` | "Sua agenda está configurada para atendimentos de 30min..." |
485
+
486
+ > **Dica:** Campos com nomes como `token`, `password`, `secret`, `key` e `credential` são automaticamente mascarados nos prompts da IA por segurança.
487
+
488
+ ## Tratamento de Erros
489
+
490
+ ```python
491
+ from atendeaqui import (
492
+ AtendeAquiClient,
493
+ StepNotFoundError,
494
+ NotFoundError,
495
+ ValidationError,
496
+ AtendeAquiError,
497
+ )
498
+
499
+ try:
500
+ client.onboarding.complete_step(flow_key=FLOW_KEY, user_id="user-123", step_key="invalid")
501
+ except StepNotFoundError as e:
502
+ print(f"Step não existe: {e.message}")
503
+ except NotFoundError as e:
504
+ print(f"Não encontrado: {e.message}")
505
+ except ValidationError as e:
506
+ print(f"Dados inválidos: {e.message}")
507
+ except AtendeAquiError as e:
508
+ print(f"Erro [{e.code}]: {e.message}")
509
+ ```
510
+
511
+ ### Hierarquia
512
+
513
+ ```
514
+ AtendeAquiError
515
+ ├── AuthenticationError # 401/403
516
+ ├── NotFoundError # 404
517
+ ├── ValidationError # 400
518
+ │ ├── StepNotFoundError
519
+ │ └── StepNotSkippableError
520
+ ├── OriginNotAllowedError # CORS
521
+ ├── RateLimitError # 429
522
+ └── ServerError # 5xx
523
+ ```
524
+
525
+ ## Estrutura do Pacote
526
+
527
+ ```
528
+ atendeaqui/
529
+ ├── __init__.py # AtendeAquiClient + exports
530
+ ├── client.py # Cliente principal
531
+ ├── _http.py # Transport HTTP compartilhado
532
+ ├── exceptions.py # Exceções compartilhadas
533
+ ├── clients/ # Módulo de Clientes
534
+ │ ├── __init__.py # ClientsModule
535
+ │ └── models.py # Client, TeamMember
536
+ └── onboarding/ # Módulo de Onboarding
537
+ ├── __init__.py # OnboardingModule
538
+ └── models.py # FlowStructure, UserProgress, etc.
539
+ ```
540
+
541
+ Novos módulos (tickets, knowledge_base, etc.) seguirão o mesmo padrão.
542
+
543
+ ## Requisitos
544
+
545
+ - Python 3.10+
546
+ - requests >= 2.28
547
+
548
+ ## Licença
549
+
550
+ MIT