zoho 0.1.1__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.
Files changed (80) hide show
  1. zoho-0.1.1/LICENSE +21 -0
  2. zoho-0.1.1/PKG-INFO +325 -0
  3. zoho-0.1.1/README.md +293 -0
  4. zoho-0.1.1/pyproject.toml +100 -0
  5. zoho-0.1.1/setup.cfg +4 -0
  6. zoho-0.1.1/src/zoho/__init__.py +37 -0
  7. zoho-0.1.1/src/zoho/client.py +638 -0
  8. zoho-0.1.1/src/zoho/connections.py +158 -0
  9. zoho-0.1.1/src/zoho/core/__init__.py +47 -0
  10. zoho-0.1.1/src/zoho/core/auth.py +172 -0
  11. zoho-0.1.1/src/zoho/core/cache.py +47 -0
  12. zoho-0.1.1/src/zoho/core/errors.py +74 -0
  13. zoho-0.1.1/src/zoho/core/logging.py +60 -0
  14. zoho-0.1.1/src/zoho/core/pagination.py +55 -0
  15. zoho-0.1.1/src/zoho/core/token_store.py +286 -0
  16. zoho-0.1.1/src/zoho/core/transport.py +194 -0
  17. zoho-0.1.1/src/zoho/creator/__init__.py +18 -0
  18. zoho-0.1.1/src/zoho/creator/client.py +93 -0
  19. zoho-0.1.1/src/zoho/creator/data.py +121 -0
  20. zoho-0.1.1/src/zoho/creator/generated/__init__.py +1 -0
  21. zoho-0.1.1/src/zoho/creator/meta.py +84 -0
  22. zoho-0.1.1/src/zoho/creator/models.py +37 -0
  23. zoho-0.1.1/src/zoho/creator/publish.py +110 -0
  24. zoho-0.1.1/src/zoho/crm/__init__.py +23 -0
  25. zoho-0.1.1/src/zoho/crm/client.py +150 -0
  26. zoho-0.1.1/src/zoho/crm/discovery.py +225 -0
  27. zoho-0.1.1/src/zoho/crm/generated/__init__.py +5 -0
  28. zoho-0.1.1/src/zoho/crm/models.py +82 -0
  29. zoho-0.1.1/src/zoho/crm/modules.py +50 -0
  30. zoho-0.1.1/src/zoho/crm/org.py +22 -0
  31. zoho-0.1.1/src/zoho/crm/records.py +136 -0
  32. zoho-0.1.1/src/zoho/crm/users.py +43 -0
  33. zoho-0.1.1/src/zoho/ingestion/__init__.py +18 -0
  34. zoho-0.1.1/src/zoho/ingestion/_common.py +13 -0
  35. zoho-0.1.1/src/zoho/ingestion/crm.py +204 -0
  36. zoho-0.1.1/src/zoho/ingestion/models.py +39 -0
  37. zoho-0.1.1/src/zoho/ingestion/people.py +77 -0
  38. zoho-0.1.1/src/zoho/ingestion/sheet.py +85 -0
  39. zoho-0.1.1/src/zoho/ingestion/workdrive.py +82 -0
  40. zoho-0.1.1/src/zoho/people/__init__.py +18 -0
  41. zoho-0.1.1/src/zoho/people/client.py +83 -0
  42. zoho-0.1.1/src/zoho/people/employees.py +84 -0
  43. zoho-0.1.1/src/zoho/people/files.py +82 -0
  44. zoho-0.1.1/src/zoho/people/forms.py +114 -0
  45. zoho-0.1.1/src/zoho/people/generated/__init__.py +1 -0
  46. zoho-0.1.1/src/zoho/people/models.py +43 -0
  47. zoho-0.1.1/src/zoho/projects/__init__.py +18 -0
  48. zoho-0.1.1/src/zoho/projects/client.py +101 -0
  49. zoho-0.1.1/src/zoho/projects/generated/__init__.py +1 -0
  50. zoho-0.1.1/src/zoho/projects/models.py +58 -0
  51. zoho-0.1.1/src/zoho/projects/portals.py +32 -0
  52. zoho-0.1.1/src/zoho/projects/projects.py +94 -0
  53. zoho-0.1.1/src/zoho/projects/tasks.py +109 -0
  54. zoho-0.1.1/src/zoho/py.typed +0 -0
  55. zoho-0.1.1/src/zoho/scripts/__init__.py +2 -0
  56. zoho-0.1.1/src/zoho/scripts/auth_cli.py +711 -0
  57. zoho-0.1.1/src/zoho/settings.py +91 -0
  58. zoho-0.1.1/src/zoho/sheet/__init__.py +18 -0
  59. zoho-0.1.1/src/zoho/sheet/client.py +83 -0
  60. zoho-0.1.1/src/zoho/sheet/generated/__init__.py +1 -0
  61. zoho-0.1.1/src/zoho/sheet/models.py +27 -0
  62. zoho-0.1.1/src/zoho/sheet/tabular.py +93 -0
  63. zoho-0.1.1/src/zoho/sheet/workbooks.py +61 -0
  64. zoho-0.1.1/src/zoho/sheet/worksheets.py +76 -0
  65. zoho-0.1.1/src/zoho/workdrive/__init__.py +18 -0
  66. zoho-0.1.1/src/zoho/workdrive/admin.py +48 -0
  67. zoho-0.1.1/src/zoho/workdrive/changes.py +40 -0
  68. zoho-0.1.1/src/zoho/workdrive/client.py +103 -0
  69. zoho-0.1.1/src/zoho/workdrive/files.py +57 -0
  70. zoho-0.1.1/src/zoho/workdrive/folders.py +73 -0
  71. zoho-0.1.1/src/zoho/workdrive/generated/__init__.py +1 -0
  72. zoho-0.1.1/src/zoho/workdrive/models.py +45 -0
  73. zoho-0.1.1/src/zoho/workdrive/search.py +43 -0
  74. zoho-0.1.1/src/zoho.egg-info/PKG-INFO +325 -0
  75. zoho-0.1.1/src/zoho.egg-info/SOURCES.txt +78 -0
  76. zoho-0.1.1/src/zoho.egg-info/dependency_links.txt +1 -0
  77. zoho-0.1.1/src/zoho.egg-info/entry_points.txt +2 -0
  78. zoho-0.1.1/src/zoho.egg-info/requires.txt +12 -0
  79. zoho-0.1.1/src/zoho.egg-info/top_level.txt +1 -0
  80. zoho-0.1.1/tests/test_client.py +112 -0
zoho-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 trisongz
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.
zoho-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,325 @@
1
+ Metadata-Version: 2.4
2
+ Name: zoho
3
+ Version: 0.1.1
4
+ Summary: Async-first Zoho Python SDK focused on DX and performance
5
+ Author-email: Tri Nguyen <tnguyen@nu-devco.com>, AIUR <aiur@sparkenergy.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/SparkAIUR/zoho-sdk
8
+ Project-URL: Documentation, https://github.com/SparkAIUR/zoho-sdk
9
+ Project-URL: Repository, https://github.com/SparkAIUR/zoho-sdk
10
+ Project-URL: Issues, https://github.com/SparkAIUR/zoho-sdk/issues
11
+ Keywords: zoho,crm,sdk,async,api
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Typing :: Typed
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: httpx>=0.28.0
22
+ Requires-Dist: pydantic>=2.12.0
23
+ Requires-Dist: pydantic-settings>=2.11.0
24
+ Requires-Dist: python-dotenv>=1.2.1
25
+ Requires-Dist: structlog>=25.0.0
26
+ Requires-Dist: typer>=0.21.1
27
+ Provides-Extra: redis
28
+ Requires-Dist: redis>=6.0.0; extra == "redis"
29
+ Provides-Extra: orjson
30
+ Requires-Dist: orjson>=3.11.0; extra == "orjson"
31
+ Dynamic: license-file
32
+
33
+ # zoho
34
+
35
+ Async-first Python SDK for Zoho, designed for developer experience and performance.
36
+
37
+ ## Highlights
38
+
39
+ - Async-first transport built on `httpx`
40
+ - Explicit credential-first initialization (`from_credentials`)
41
+ - Strong typing with `pydantic` / `pydantic-settings`
42
+ - Pluggable token stores (memory, SQLite, Redis)
43
+ - Structlog-powered logging (`pretty` or `json`)
44
+ - Multi-account connection manager (`client.connections`)
45
+ - Product clients:
46
+ - CRM (`records`, `modules`, `org`, `users`, `dynamic`)
47
+ - Creator (`meta`, `data`, `publish`)
48
+ - Projects V3 (`portals`, `projects`, `tasks`)
49
+ - People (`forms`, `employees`, `files`)
50
+ - Sheet (`workbooks`, `worksheets`, `tabular`)
51
+ - WorkDrive (`files`, `folders`, `search`, `changes`, `admin`)
52
+ - Ingestion iterators for connector workloads (`zoho.ingestion`)
53
+ - Codegen tooling + golden tests for spec drift
54
+
55
+ ## Installation
56
+
57
+ ```bash
58
+ uv add zoho
59
+ ```
60
+
61
+ Optional extras:
62
+
63
+ ```bash
64
+ uv add "zoho[redis]" # Redis token store
65
+ uv add "zoho[orjson]" # Faster JSON usage patterns
66
+ ```
67
+
68
+ ## Quick Start (Explicit Credentials)
69
+
70
+ ```python
71
+ from zoho import Zoho
72
+
73
+ async def main() -> None:
74
+ async with Zoho.from_credentials(
75
+ client_id="your_client_id",
76
+ client_secret="your_client_secret",
77
+ refresh_token="your_refresh_token",
78
+ dc="US",
79
+ environment="production",
80
+ ) as client:
81
+ lead = await client.crm.records.get(module="Leads", record_id="123456789")
82
+ print(lead.id)
83
+ ```
84
+
85
+ ## Client Lifecycle: Context Manager vs Singleton
86
+
87
+ Both patterns are supported.
88
+
89
+ Use `async with` for one-shot scripts/jobs:
90
+
91
+ ```python
92
+ async with Zoho.from_credentials(
93
+ client_id="...",
94
+ client_secret="...",
95
+ refresh_token="...",
96
+ ) as client:
97
+ org = await client.crm.org.get()
98
+ ```
99
+
100
+ Use a long-lived singleton for web apps/workers and close on shutdown:
101
+
102
+ ```python
103
+ zoho_client = Zoho.from_credentials(
104
+ client_id="...",
105
+ client_secret="...",
106
+ refresh_token="...",
107
+ )
108
+
109
+ project_rows = await zoho_client.projects.projects.list(portal_id="12345678")
110
+
111
+ # shutdown hook
112
+ await zoho_client.close()
113
+ ```
114
+
115
+ After `close()`, `zoho_client.closed` is `True` and that instance must not be reused.
116
+
117
+ ## Multi-Account Connections
118
+
119
+ ```python
120
+ from zoho import Zoho, ZohoConnectionProfile
121
+
122
+ client = Zoho.from_credentials(
123
+ client_id="primary_client_id",
124
+ client_secret="primary_client_secret",
125
+ refresh_token="primary_refresh_token",
126
+ )
127
+
128
+ client.register_connection(
129
+ ZohoConnectionProfile(
130
+ name="tenant_b",
131
+ client_id="tenant_b_client_id",
132
+ client_secret="tenant_b_client_secret",
133
+ refresh_token="tenant_b_refresh_token",
134
+ dc="EU",
135
+ token_store_backend="sqlite",
136
+ )
137
+ )
138
+
139
+ tenant_b = client.for_connection("tenant_b")
140
+ forms = await tenant_b.people.forms.list_forms()
141
+ print(forms.result_rows)
142
+ ```
143
+
144
+ ## Product Usage Examples
145
+
146
+ ### People
147
+
148
+ ```python
149
+ records = await client.people.forms.list_records(
150
+ form_link_name="employee",
151
+ limit=200,
152
+ )
153
+ print(records.result_rows)
154
+ ```
155
+
156
+ ### Sheet
157
+
158
+ ```python
159
+ rows = await client.sheet.tabular.fetch_worksheet_records(
160
+ workbook_id="workbook_123",
161
+ worksheet_name="Data",
162
+ limit=500,
163
+ )
164
+ print(rows.records)
165
+ ```
166
+
167
+ ### WorkDrive
168
+
169
+ ```python
170
+ changes = await client.workdrive.changes.list_recent(
171
+ folder_id="folder_123",
172
+ limit=200,
173
+ )
174
+ print(changes.resources)
175
+ ```
176
+
177
+ ### CRM Dynamic Discovery
178
+
179
+ ```python
180
+ if await client.crm.dynamic.has_module("Leads"):
181
+ leads = client.crm.dynamic.Leads
182
+ rows = await leads.list(page=1, per_page=200)
183
+ print(rows.data)
184
+ ```
185
+
186
+ ## Ingestion Helpers (`pipeshub-ai`-friendly)
187
+
188
+ ```python
189
+ from zoho.ingestion import iter_people_form_documents
190
+
191
+ async for batch in iter_people_form_documents(
192
+ client,
193
+ form_link_name="employee",
194
+ connection_name="tenant_b",
195
+ page_size=200,
196
+ ):
197
+ for doc in batch.documents:
198
+ print(doc.id, doc.title)
199
+ print(batch.checkpoint)
200
+ ```
201
+
202
+ Additional iterators:
203
+ - `iter_crm_module_documents(...)`
204
+ - `iter_crm_documents(...)`
205
+ - `iter_sheet_worksheet_documents(...)`
206
+ - `iter_workdrive_recent_documents(...)`
207
+
208
+ ## Getting OAuth Credentials
209
+
210
+ If you still need OAuth credentials, follow:
211
+ - `docs/auth-credentials.md`
212
+ - `docs/scopes.md`
213
+
214
+ At a high level:
215
+ 1. Create a client in Zoho API Console.
216
+ 2. Generate grant code(s) with required product scopes.
217
+ 3. Exchange grant code for access/refresh tokens.
218
+ 4. Use matching `dc` and accounts domain.
219
+
220
+ ## Auth Helper CLI
221
+
222
+ Use the helper command for token exchange and self-client payload generation:
223
+
224
+ ```bash
225
+ export ZOHO_CREDENTIALS_FILE=refs/notes/zoho-live.env
226
+ uv run zoho-auth exchange-token --grant-code "<grant-code>"
227
+
228
+ uv run zoho-auth grant-code \
229
+ --self-client-id "1000..." \
230
+ --scopes "ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL"
231
+
232
+ uv run zoho-auth scope-builder \
233
+ --product CRM \
234
+ --product WorkDrive \
235
+ --access read \
236
+ --format env
237
+ ```
238
+
239
+ See `docs/auth-cli.md` for execute mode and header/cookie options.
240
+
241
+ ## Environment-Based Setup (Convenience)
242
+
243
+ ```bash
244
+ export ZOHO_CLIENT_ID="..."
245
+ export ZOHO_CLIENT_SECRET="..."
246
+ export ZOHO_REFRESH_TOKEN="..."
247
+ export ZOHO_DC="US"
248
+ export ZOHO_ENVIRONMENT="production"
249
+ ```
250
+
251
+ ```python
252
+ from zoho import Zoho
253
+
254
+ async with Zoho.from_env() as client:
255
+ org = await client.crm.org.get()
256
+ print(org)
257
+ ```
258
+
259
+ ## Live Credential Validation (Admin)
260
+
261
+ Use the read-only validator before production rollout:
262
+
263
+ ```bash
264
+ export ZOHO_CREDENTIALS_FILE=refs/notes/zoho-live.env
265
+ uv sync --group dev
266
+ uv run python tools/admin_validate_live.py
267
+ ```
268
+
269
+ The script only runs read-oriented product checks and prints non-sensitive summaries
270
+ (counts/status only). See `docs/admin-live-validation.md` for required/optional vars.
271
+
272
+ ## Development
273
+
274
+ ```bash
275
+ uv sync --group dev
276
+ uv run ruff format .
277
+ uv run ruff check .
278
+ uv run mypy
279
+ uv run pytest
280
+ uv run mkdocs build --strict
281
+ ```
282
+
283
+ ## Codegen Workflows
284
+
285
+ ### CRM summary
286
+
287
+ ```bash
288
+ uv run python tools/codegen/main.py \
289
+ --json-details tests/fixtures/json_details_minimal.json \
290
+ --openapi tests/fixtures/openapi_minimal.json \
291
+ --output /tmp/zoho_ir_summary.json
292
+ ```
293
+
294
+ ### Creator summary
295
+
296
+ ```bash
297
+ uv run python tools/codegen/creator_summary.py \
298
+ --openapi tests/fixtures/creator_openapi_minimal.json \
299
+ --output /tmp/creator_summary.json
300
+ ```
301
+
302
+ ### Projects extraction
303
+
304
+ ```bash
305
+ uv run python tools/codegen/projects_extract.py \
306
+ --html tests/fixtures/projects/api_docs_sample.html \
307
+ --output /tmp/projects_mvp.json
308
+ ```
309
+
310
+ ### Curated product specs summary (People/Sheet/WorkDrive)
311
+
312
+ ```bash
313
+ uv run python tools/codegen/curated_summary.py \
314
+ --spec tools/specs/people_v1_curated.json \
315
+ --spec tools/specs/sheet_v2_curated.json \
316
+ --spec tools/specs/workdrive_v1_curated.json \
317
+ --output /tmp/curated_summary.json
318
+ ```
319
+
320
+ ## Repository Docs
321
+
322
+ - Product docs: `docs/`
323
+ - API research notes: `refs/apis/`
324
+ - Design specs: `refs/docs/specs/`
325
+ - Contributor guide: `AGENTS.md`
zoho-0.1.1/README.md ADDED
@@ -0,0 +1,293 @@
1
+ # zoho
2
+
3
+ Async-first Python SDK for Zoho, designed for developer experience and performance.
4
+
5
+ ## Highlights
6
+
7
+ - Async-first transport built on `httpx`
8
+ - Explicit credential-first initialization (`from_credentials`)
9
+ - Strong typing with `pydantic` / `pydantic-settings`
10
+ - Pluggable token stores (memory, SQLite, Redis)
11
+ - Structlog-powered logging (`pretty` or `json`)
12
+ - Multi-account connection manager (`client.connections`)
13
+ - Product clients:
14
+ - CRM (`records`, `modules`, `org`, `users`, `dynamic`)
15
+ - Creator (`meta`, `data`, `publish`)
16
+ - Projects V3 (`portals`, `projects`, `tasks`)
17
+ - People (`forms`, `employees`, `files`)
18
+ - Sheet (`workbooks`, `worksheets`, `tabular`)
19
+ - WorkDrive (`files`, `folders`, `search`, `changes`, `admin`)
20
+ - Ingestion iterators for connector workloads (`zoho.ingestion`)
21
+ - Codegen tooling + golden tests for spec drift
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ uv add zoho
27
+ ```
28
+
29
+ Optional extras:
30
+
31
+ ```bash
32
+ uv add "zoho[redis]" # Redis token store
33
+ uv add "zoho[orjson]" # Faster JSON usage patterns
34
+ ```
35
+
36
+ ## Quick Start (Explicit Credentials)
37
+
38
+ ```python
39
+ from zoho import Zoho
40
+
41
+ async def main() -> None:
42
+ async with Zoho.from_credentials(
43
+ client_id="your_client_id",
44
+ client_secret="your_client_secret",
45
+ refresh_token="your_refresh_token",
46
+ dc="US",
47
+ environment="production",
48
+ ) as client:
49
+ lead = await client.crm.records.get(module="Leads", record_id="123456789")
50
+ print(lead.id)
51
+ ```
52
+
53
+ ## Client Lifecycle: Context Manager vs Singleton
54
+
55
+ Both patterns are supported.
56
+
57
+ Use `async with` for one-shot scripts/jobs:
58
+
59
+ ```python
60
+ async with Zoho.from_credentials(
61
+ client_id="...",
62
+ client_secret="...",
63
+ refresh_token="...",
64
+ ) as client:
65
+ org = await client.crm.org.get()
66
+ ```
67
+
68
+ Use a long-lived singleton for web apps/workers and close on shutdown:
69
+
70
+ ```python
71
+ zoho_client = Zoho.from_credentials(
72
+ client_id="...",
73
+ client_secret="...",
74
+ refresh_token="...",
75
+ )
76
+
77
+ project_rows = await zoho_client.projects.projects.list(portal_id="12345678")
78
+
79
+ # shutdown hook
80
+ await zoho_client.close()
81
+ ```
82
+
83
+ After `close()`, `zoho_client.closed` is `True` and that instance must not be reused.
84
+
85
+ ## Multi-Account Connections
86
+
87
+ ```python
88
+ from zoho import Zoho, ZohoConnectionProfile
89
+
90
+ client = Zoho.from_credentials(
91
+ client_id="primary_client_id",
92
+ client_secret="primary_client_secret",
93
+ refresh_token="primary_refresh_token",
94
+ )
95
+
96
+ client.register_connection(
97
+ ZohoConnectionProfile(
98
+ name="tenant_b",
99
+ client_id="tenant_b_client_id",
100
+ client_secret="tenant_b_client_secret",
101
+ refresh_token="tenant_b_refresh_token",
102
+ dc="EU",
103
+ token_store_backend="sqlite",
104
+ )
105
+ )
106
+
107
+ tenant_b = client.for_connection("tenant_b")
108
+ forms = await tenant_b.people.forms.list_forms()
109
+ print(forms.result_rows)
110
+ ```
111
+
112
+ ## Product Usage Examples
113
+
114
+ ### People
115
+
116
+ ```python
117
+ records = await client.people.forms.list_records(
118
+ form_link_name="employee",
119
+ limit=200,
120
+ )
121
+ print(records.result_rows)
122
+ ```
123
+
124
+ ### Sheet
125
+
126
+ ```python
127
+ rows = await client.sheet.tabular.fetch_worksheet_records(
128
+ workbook_id="workbook_123",
129
+ worksheet_name="Data",
130
+ limit=500,
131
+ )
132
+ print(rows.records)
133
+ ```
134
+
135
+ ### WorkDrive
136
+
137
+ ```python
138
+ changes = await client.workdrive.changes.list_recent(
139
+ folder_id="folder_123",
140
+ limit=200,
141
+ )
142
+ print(changes.resources)
143
+ ```
144
+
145
+ ### CRM Dynamic Discovery
146
+
147
+ ```python
148
+ if await client.crm.dynamic.has_module("Leads"):
149
+ leads = client.crm.dynamic.Leads
150
+ rows = await leads.list(page=1, per_page=200)
151
+ print(rows.data)
152
+ ```
153
+
154
+ ## Ingestion Helpers (`pipeshub-ai`-friendly)
155
+
156
+ ```python
157
+ from zoho.ingestion import iter_people_form_documents
158
+
159
+ async for batch in iter_people_form_documents(
160
+ client,
161
+ form_link_name="employee",
162
+ connection_name="tenant_b",
163
+ page_size=200,
164
+ ):
165
+ for doc in batch.documents:
166
+ print(doc.id, doc.title)
167
+ print(batch.checkpoint)
168
+ ```
169
+
170
+ Additional iterators:
171
+ - `iter_crm_module_documents(...)`
172
+ - `iter_crm_documents(...)`
173
+ - `iter_sheet_worksheet_documents(...)`
174
+ - `iter_workdrive_recent_documents(...)`
175
+
176
+ ## Getting OAuth Credentials
177
+
178
+ If you still need OAuth credentials, follow:
179
+ - `docs/auth-credentials.md`
180
+ - `docs/scopes.md`
181
+
182
+ At a high level:
183
+ 1. Create a client in Zoho API Console.
184
+ 2. Generate grant code(s) with required product scopes.
185
+ 3. Exchange grant code for access/refresh tokens.
186
+ 4. Use matching `dc` and accounts domain.
187
+
188
+ ## Auth Helper CLI
189
+
190
+ Use the helper command for token exchange and self-client payload generation:
191
+
192
+ ```bash
193
+ export ZOHO_CREDENTIALS_FILE=refs/notes/zoho-live.env
194
+ uv run zoho-auth exchange-token --grant-code "<grant-code>"
195
+
196
+ uv run zoho-auth grant-code \
197
+ --self-client-id "1000..." \
198
+ --scopes "ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL"
199
+
200
+ uv run zoho-auth scope-builder \
201
+ --product CRM \
202
+ --product WorkDrive \
203
+ --access read \
204
+ --format env
205
+ ```
206
+
207
+ See `docs/auth-cli.md` for execute mode and header/cookie options.
208
+
209
+ ## Environment-Based Setup (Convenience)
210
+
211
+ ```bash
212
+ export ZOHO_CLIENT_ID="..."
213
+ export ZOHO_CLIENT_SECRET="..."
214
+ export ZOHO_REFRESH_TOKEN="..."
215
+ export ZOHO_DC="US"
216
+ export ZOHO_ENVIRONMENT="production"
217
+ ```
218
+
219
+ ```python
220
+ from zoho import Zoho
221
+
222
+ async with Zoho.from_env() as client:
223
+ org = await client.crm.org.get()
224
+ print(org)
225
+ ```
226
+
227
+ ## Live Credential Validation (Admin)
228
+
229
+ Use the read-only validator before production rollout:
230
+
231
+ ```bash
232
+ export ZOHO_CREDENTIALS_FILE=refs/notes/zoho-live.env
233
+ uv sync --group dev
234
+ uv run python tools/admin_validate_live.py
235
+ ```
236
+
237
+ The script only runs read-oriented product checks and prints non-sensitive summaries
238
+ (counts/status only). See `docs/admin-live-validation.md` for required/optional vars.
239
+
240
+ ## Development
241
+
242
+ ```bash
243
+ uv sync --group dev
244
+ uv run ruff format .
245
+ uv run ruff check .
246
+ uv run mypy
247
+ uv run pytest
248
+ uv run mkdocs build --strict
249
+ ```
250
+
251
+ ## Codegen Workflows
252
+
253
+ ### CRM summary
254
+
255
+ ```bash
256
+ uv run python tools/codegen/main.py \
257
+ --json-details tests/fixtures/json_details_minimal.json \
258
+ --openapi tests/fixtures/openapi_minimal.json \
259
+ --output /tmp/zoho_ir_summary.json
260
+ ```
261
+
262
+ ### Creator summary
263
+
264
+ ```bash
265
+ uv run python tools/codegen/creator_summary.py \
266
+ --openapi tests/fixtures/creator_openapi_minimal.json \
267
+ --output /tmp/creator_summary.json
268
+ ```
269
+
270
+ ### Projects extraction
271
+
272
+ ```bash
273
+ uv run python tools/codegen/projects_extract.py \
274
+ --html tests/fixtures/projects/api_docs_sample.html \
275
+ --output /tmp/projects_mvp.json
276
+ ```
277
+
278
+ ### Curated product specs summary (People/Sheet/WorkDrive)
279
+
280
+ ```bash
281
+ uv run python tools/codegen/curated_summary.py \
282
+ --spec tools/specs/people_v1_curated.json \
283
+ --spec tools/specs/sheet_v2_curated.json \
284
+ --spec tools/specs/workdrive_v1_curated.json \
285
+ --output /tmp/curated_summary.json
286
+ ```
287
+
288
+ ## Repository Docs
289
+
290
+ - Product docs: `docs/`
291
+ - API research notes: `refs/apis/`
292
+ - Design specs: `refs/docs/specs/`
293
+ - Contributor guide: `AGENTS.md`